Skip to content

Commit da6c0d1

Browse files
committed
[core/collect] fix use after free during shutdown
Pass worker a collect cleanup (complete == FALSE) callback is called in; other workers might be gone already. Change-Id: Idbec63d1f0081ed2b588706b130c72ff1bd08c24
1 parent f692ec9 commit da6c0d1

File tree

6 files changed

+20
-13
lines changed

6 files changed

+20
-13
lines changed

include/lighttpd/collect.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,16 @@
1515
typedef gpointer (*liCollectFuncCB)(liWorker *wrk, gpointer fdata);
1616

1717
/** CollectCallback: the type of functions to call after a function was called in each workers context
18+
* - wrk: worker this callback is run in; if complete == TRUE this should be worker the job was started in.
1819
* - cbdata: optional callback data
1920
* depending on the data you should only use it when complete == TRUE
2021
* - fdata : the data the CollectFunc got (this data must be valid until cb is called)
2122
* - result: the return values
2223
* - complete: determines if cbdata is still valid
2324
* if this is FALSE, it may be called from another context than li_collect_start was called
25+
* (and the original worker may be already gone)
2426
*/
25-
typedef void (*liCollectCB)(gpointer cbdata, gpointer fdata, GPtrArray *result, gboolean complete);
27+
typedef void (*liCollectCB)(liWorker *wrk, gpointer cbdata, gpointer fdata, GPtrArray *result, gboolean complete);
2628

2729
typedef struct liCollectInfo liCollectInfo;
2830

src/main/backends.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -787,8 +787,9 @@ static gpointer backend_pool_worker_init(liWorker *wrk, gpointer fdata) {
787787
return NULL;
788788
}
789789

790-
static void backend_pool_worker_init_done(gpointer cbdata, gpointer fdata, GPtrArray *result, gboolean complete) {
790+
static void backend_pool_worker_init_done(liWorker *wrk, gpointer cbdata, gpointer fdata, GPtrArray *result, gboolean complete) {
791791
liBackendPool_p *pool = fdata;
792+
UNUSED(wrk);
792793
UNUSED(cbdata);
793794
UNUSED(result);
794795
UNUSED(complete);
@@ -861,7 +862,7 @@ static gpointer backend_pool_worker_shutdown(liWorker *wrk, gpointer fdata) {
861862
return NULL;
862863
}
863864

864-
static void backend_pool_worker_shutdown_done(gpointer cbdata, gpointer fdata, GPtrArray *result, gboolean complete) {
865+
static void backend_pool_worker_shutdown_done(liWorker *wrk, gpointer cbdata, gpointer fdata, GPtrArray *result, gboolean complete) {
865866
liBackendPool_p *pool = fdata;
866867
UNUSED(cbdata);
867868
UNUSED(result);
@@ -870,8 +871,7 @@ static void backend_pool_worker_shutdown_done(gpointer cbdata, gpointer fdata, G
870871
pool->public.config->callbacks->free_cb(&pool->public);
871872

872873
if (pool->worker_pools != NULL) {
873-
liServer *srv = pool->worker_pools[0].wrk->srv;
874-
g_slice_free1(sizeof(liBackendPool_p) * srv->worker_count, pool->worker_pools);
874+
g_slice_free1(sizeof(liBackendPool_p) * wrk->srv->worker_count, pool->worker_pools);
875875
}
876876

877877
g_mutex_free(pool->lock);
@@ -902,7 +902,7 @@ void li_backend_pool_free(liBackendPool *bpool) {
902902
g_mutex_unlock(pool->lock);
903903

904904
if (pool->worker_pools == NULL) {
905-
backend_pool_worker_shutdown_done(NULL, pool, NULL, TRUE);
905+
backend_pool_worker_shutdown_done(NULL, NULL, pool, NULL, TRUE);
906906
} else {
907907
liServer *srv = pool->worker_pools[0].wrk->srv;
908908

src/main/collect.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ static void collect_info_free(liCollectInfo *ci) {
4545
static gboolean collect_insert_callback(liWorker *ctx, liCollectInfo *ci) {
4646
if (ctx == ci->wrk) {
4747
/* we are in the destination context */
48-
ci->cb(ci->cbdata, ci->fdata, ci->results, !ci->stopped);
48+
ci->cb(ctx, ci->cbdata, ci->fdata, ci->results, !ci->stopped);
4949
collect_info_free(ci);
5050
return TRUE;
5151
} else {
@@ -64,7 +64,7 @@ static gboolean collect_send_result(liWorker *ctx, liCollectInfo *ci) {
6464
if (!g_atomic_int_dec_and_test(&ci->counter)) return FALSE; /* not all workers done yet */
6565
if (g_atomic_int_get(&ctx->srv->exiting)) {
6666
/* cleanup state, just call the callback with complete = FALSE */
67-
ci->cb(ci->cbdata, ci->fdata, ci->results, FALSE);
67+
ci->cb(ctx, ci->cbdata, ci->fdata, ci->results, FALSE);
6868
collect_info_free(ci);
6969
return TRUE;
7070
} else {
@@ -124,7 +124,7 @@ void li_collect_watcher_cb(liEventBase *watcher, int events) {
124124
collect_send_result(wrk, ci);
125125
break;
126126
case COLLECT_CB:
127-
ci->cb(ci->cbdata, ci->fdata, ci->results, !ci->stopped);
127+
ci->cb(wrk, ci->cbdata, ci->fdata, ci->results, !ci->stopped);
128128
collect_info_free(ci);
129129
break;
130130
}

src/modules/mod_debug.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -170,11 +170,12 @@ static gpointer debug_collect_func(liWorker *wrk, gpointer fdata) {
170170
}
171171

172172
/* the CollectCallback */
173-
static void debug_collect_cb(gpointer cbdata, gpointer fdata, GPtrArray *result, gboolean complete) {
173+
static void debug_collect_cb(liWorker *wrk, gpointer cbdata, gpointer fdata, GPtrArray *result, gboolean complete) {
174174
mod_debug_job_t *job = cbdata;
175175
liVRequest *vr;
176176
GString *html;
177177

178+
UNUSED(wrk);
178179
UNUSED(fdata);
179180

180181
if (!complete) {
@@ -486,9 +487,11 @@ static gpointer debug_show_events_func(liWorker *wrk, gpointer fdata) {
486487
}
487488

488489
/* the CollectCallback */
489-
static void debug_show_events_cb(gpointer cbdata, gpointer fdata, GPtrArray *result, gboolean complete) {
490+
static void debug_show_events_cb(liWorker *wrk, gpointer cbdata, gpointer fdata, GPtrArray *result, gboolean complete) {
490491
collect_events_job *job = fdata;
491492
liVRequest *vr;
493+
494+
UNUSED(wrk);
492495
UNUSED(cbdata);
493496

494497
if (complete) {

src/modules/mod_progress.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ static gpointer progress_collect_func(liWorker *wrk, gpointer fdata) {
192192
}
193193

194194
/* the CollectCallback */
195-
static void progress_collect_cb(gpointer cbdata, gpointer fdata, GPtrArray *result, gboolean complete) {
195+
static void progress_collect_cb(liWorker *wrk, gpointer cbdata, gpointer fdata, GPtrArray *result, gboolean complete) {
196196
guint i;
197197
GString *output;
198198
mod_progress_node *node = NULL;
@@ -201,6 +201,7 @@ static void progress_collect_cb(gpointer cbdata, gpointer fdata, GPtrArray *resu
201201
gboolean debug = job->debug;
202202
mod_progress_format format = job->format;
203203

204+
UNUSED(wrk);
204205
UNUSED(cbdata);
205206

206207
if (complete) {

src/modules/mod_status.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,13 +414,14 @@ static gpointer status_collect_func(liWorker *wrk, gpointer fdata) {
414414
}
415415

416416
/* the CollectCallback */
417-
static void status_collect_cb(gpointer cbdata, gpointer fdata, GPtrArray *result, gboolean complete) {
417+
static void status_collect_cb(liWorker *wrk, gpointer cbdata, gpointer fdata, GPtrArray *result, gboolean complete) {
418418
guint i, j;
419419
mod_status_job *job = fdata;
420420
liVRequest *vr = job->vr;
421421
liPlugin *p = job->p;
422422
gboolean short_info = job->short_info;
423423

424+
UNUSED(wrk);
424425
UNUSED(cbdata);
425426

426427
if (!complete) {

0 commit comments

Comments
 (0)