Skip to content

Commit 4083c73

Browse files
stephanboschJosef 'Jeff' Sipek
authored and
Josef 'Jeff' Sipek
committedJul 9, 2019
lib-http: guard against hshared use-after-free
This fixes a race condition where the http_client_host_shared_idle_timeout() function would get called with an already freed hshared argument. Specifically, the situation arises from the hshared idle timeout calling http_client_host_shared_free(), which removes the timeout and then proceeds to free the client queue. The client queue freeing code indirectly calls http_client_host_shared_check_idle(), which notices that there is no idle timeout and allocates one. The backtrace at the point of this new timeout allocation: frame #3: 0x00007f0c775897f0 libdovecot.so.0`timeout_add_to(...) ioloop.c:280 frame #4: 0x00007f0c7751a45f libdovecot.so.0`http_client_host_shared_check_idle(hshared=<unavailable>) at http-client-host.c:69 frame #5: 0x00007f0c7750de89 libdovecot.so.0`http_client_request_error(_req=<unavailable>, status=9000, error="") at http-client-request.c:1525 frame #6: 0x00007f0c77517f38 libdovecot.so.0`http_client_queue_fail_full(queue=0x000055e13cff0e10, status=9000, error="", all=<unavailable>) at http-client-queue.c:183 frame #7: 0x00007f0c77518baa libdovecot.so.0`http_client_queue_free(queue=0x000055e13cff0e10) at http-client-queue.c:141 frame #8: 0x00007f0c7751a8bc libdovecot.so.0`http_client_host_free_shared(_host=<unavailable>) at http-client-host.c:391 frame #9: 0x00007f0c7751ab4c libdovecot.so.0`http_client_host_shared_free(_hshared=0x00007ffdac109e48) at http-client-host.c:294 frame #10: 0x00007f0c7751ace8 libdovecot.so.0`http_client_host_shared_idle_timeout(hshared=<unavailable>) at http-client-host.c:40 frame #11: 0x00007f0c7758a1a4 libdovecot.so.0`io_loop_handle_timeouts at ioloop.c:682 frame #12: 0x00007f0c7758a089 libdovecot.so.0`io_loop_handle_timeouts(ioloop=0x000055e13cfc8d80) at ioloop.c:696 frame #13: 0x00007f0c7758befc libdovecot.so.0`io_loop_handler_run_internal(ioloop=0x000055e13cfc8d80) at ioloop-select.c:126 frame #14: 0x00007f0c7758a56d libdovecot.so.0`io_loop_handler_run(ioloop=<unavailable>) at ioloop.c:767 frame #15: 0x00007f0c7758a798 libdovecot.so.0`io_loop_run(ioloop=0x000055e13cfc8d80) at ioloop.c:740 frame #16: 0x00007f0c774f61eb libdovecot.so.0`master_service_run(service=0x000055e13cfc8c10, callback=<unavailable>) at master-service.c:782 frame #17: 0x000055e13b48e3a5 stats`main(argc=<unavailable>, argv=<unavailable>) at main.c:99 frame #18: 0x00007f0c771092e1 libc.so.6`__libc_start_main + 241 frame #19: 0x000055e13b48e41a stats`_start + 42
1 parent 8ec253d commit 4083c73

File tree

2 files changed

+7
-0
lines changed

2 files changed

+7
-0
lines changed
 

‎src/lib-http/http-client-host.c

+6
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ http_client_host_shared_check_idle(
4444
struct http_client_host *host;
4545
int timeout = 0;
4646

47+
if (hshared->destroyed)
48+
return;
4749
if (hshared->to_idle != NULL)
4850
return;
4951

@@ -266,6 +268,10 @@ void http_client_host_shared_free(struct http_client_host_shared **_hshared)
266268
struct http_client_host *host;
267269
const char *hostname = hshared->name;
268270

271+
if (hshared->destroyed)
272+
return;
273+
hshared->destroyed = TRUE;
274+
269275
e_debug(hshared->event, "Host destroy");
270276

271277
timeout_remove(&hshared->to_idle);

‎src/lib-http/http-client-private.h

+1
Original file line numberDiff line numberDiff line change
@@ -344,6 +344,7 @@ struct http_client_host_shared {
344344
/* timeouts */
345345
struct timeout *to_idle;
346346

347+
bool destroyed:1; /* shared host object is being destroyed */
347348
bool unix_local:1;
348349
bool explicit_ip:1;
349350
};

0 commit comments

Comments
 (0)