Bug #2923
closedSIGSEGV on file upload
Description
Since commit a1b527e47374 ("[PATCH] [multiple] reduce initial buffer sz if large POST (fixes #2922)")
Uploading a file immediately leads to a SIGSEGV
The configuration is the same as #2922 plus :server.stream-request-body = 2
GDB:
Starting program: /usr/sbin/lighttpd -D -f /etc/lighttpd/lighttpd.conf Program received signal SIGSEGV, Segmentation fault. 0xb6c05a84 in fcgi_stdin_append (srv=0x6a008, hctx=0xb0ea0) at mod_fastcgi.c:190 190 hctx->wb->first->type == MEM_CHUNK /* else FILE_CHUNK for temp file */ (gdb) bt #0 0xb6c05a84 in fcgi_stdin_append (srv=0x6a008, hctx=0xb0ea0) at mod_fastcgi.c:190 #1 0x0003a508 in gw_handle_subrequest (srv=0x6a008, con=0x85558, p_d=0x77fb8) at gw_backend.c:2003 #2 0x0003e024 in plugins_call_handle_subrequest (srv=0x6a008, con=0x85558) at plugin.c:338 #3 0x000158e4 in http_response_prepare (srv=0x6a008, con=0x85558) at response.c:695 #4 0x00018790 in connection_state_machine (srv=0x6a008, con=0x85558) at connections.c:1157 #5 0x000138d0 in server_main (srv=0x6a008, argc=4, argv=0xbef9bc94) at server.c:2037 #6 0x00013b34 in main (argc=4, argv=0xbef9bc94) at server.c:2091
strace:
open("/var/www/lns_ihm/controller/chargeFMW.php", O_RDONLY|O_LARGEFILE) = 8 close(8) = 0 gettimeofday({1545042217, 899612}, NULL) = 0 open("/var/tmp/lighttpd-upload-Ikt0jd", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE, 0600) = 8 fcntl64(8, F_GETFL) = 0x20002 (flags O_RDWR|O_LARGEFILE) fcntl64(8, F_SETFL, O_RDWR|O_APPEND|O_LARGEFILE) = 0 fcntl64(8, F_SETFD, FD_CLOEXEC) = 0 write(8, "-----------------------------181"..., 93477) = 93477 socket(PF_LOCAL, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0) = 9 connect(9, {sa_family=AF_LOCAL, sun_path="/tmp/php.socket-0"}, 19) = 0 getsockname(7, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("192.168.5.1")}, [16]) = 0 epoll_ctl(6, EPOLL_CTL_ADD, 9, {EPOLLIN|EPOLLERR|EPOLLHUP|EPOLLRDHUP, {u32=9, u64=9}}) = 0 writev(9, [{"\1\1\0\1\0\10\0\0\0\1\0\0\0\0\0\0\1\4\0\1\0042\0\0\16\10CONTEN"..., 1114}], 1) = 1114 open("/var/tmp/lighttpd-upload-Ikt0jd", O_RDONLY|O_NOCTTY|O_LARGEFILE|O_CLOEXEC) = 10 fstat64(10, {st_mode=S_IFREG|0600, st_size=93477, ...}) = 0 _llseek(10, 0, [0], SEEK_SET) = 0 read(10, "-----------------------------181"..., 65535) = 65535 write(9, "-----------------------------181"..., 65535) = 65535 close(10) = 0 writev(9, [{"\1\5\0\1m&\0\0", 8}], 1) = 8 _llseek(8, 65535, [65535], SEEK_SET) = 0 read(8, "\275\205\310\326\360\1\331D\24\241\240\360\21\211@\343\320\342}\213\230\233\35)7\344\5\0T\335\302\314"..., 27942) = 27942 write(9, "\275\205\310\326\360\1\331D\24\241\240\360\21\211@\343\320\342}\213\230\233\35)7\344\5\0T\335\302\314"..., 27942) = 27942 unlink("/var/tmp/lighttpd-upload-Ikt0jd") = 0 close(8) = 0 epoll_ctl(6, EPOLL_CTL_ADD, 7, {EPOLLIN|EPOLLERR|EPOLLHUP|EPOLLRDHUP, {u32=7, u64=7}}) = 0 accept4(4, 0xbec5e818, [112], SOCK_CLOEXEC|SOCK_NONBLOCK) = -1 EAGAIN (Resource temporarily unavailable) gettimeofday({1545042217, 955984}, NULL) = 0 epoll_wait(6, {{EPOLLIN, {u32=7, u64=7}}}, 2049, 1000) = 1 ioctl(7, FIONREAD, [70952]) = 0 brk(0xf9000) = 0xf9000 read(7, "\301\2316\374ZcO\242P\274\365\341\346\335\233\245\343\272sD\362\2\364gS>\351\6\346\37=\306"..., 73727) = 70952 gettimeofday({1545042217, 997909}, NULL) = 0 open("/var/tmp/lighttpd-upload-4QaOvn", O_RDWR|O_CREAT|O_EXCL|O_LARGEFILE, 0600) = 8 fcntl64(8, F_GETFL) = 0x20002 (flags O_RDWR|O_LARGEFILE) fcntl64(8, F_SETFL, O_RDWR|O_APPEND|O_LARGEFILE) = 0 fcntl64(8, F_SETFD, FD_CLOEXEC) = 0 write(8, "\301\2316\374ZcO\242P\274\365\341\346\335\233\245\343\272sD\362\2\364gS>\351\6\346\37=\306"..., 70952) = 70952 --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x4} --- +++ killed by SIGSEGV +++
Updated by gstrauss about 6 years ago
I need to write a test case for large POST with server.stream-request-body = 2
Untested, but a likely fix follows. I'll try to find time to test later tonight.
--- a/src/mod_fastcgi.c +++ b/src/mod_fastcgi.c @@ -187,7 +187,7 @@ static handler_t fcgi_stdin_append(server *srv, handler_ctx *hctx) { } fcgi_header(&(header), FCGI_STDIN, request_id, weWant, 0); - hctx->wb->first->type == MEM_CHUNK /* else FILE_CHUNK for temp file */ + (chunkqueue_is_empty(hctx->wb) || hctx->wb->first->type == MEM_CHUNK) /* else FILE_CHUNK for temp file */ ? chunkqueue_append_mem(hctx->wb, (const char *)&header, sizeof(header)) : chunkqueue_append_mem_min(hctx->wb, (const char *)&header, sizeof(header)); chunkqueue_steal(hctx->wb, req_cq, weWant);
Updated by gstrauss about 6 years ago
- Category changed from core to mod_fastcgi
- Status changed from New to Patch Pending
- Target version changed from 1.4.x to 1.4.53
Updated by gstrauss about 6 years ago
I was able to reproduce this manually, and the patch above addresses the issue. Thanks for reporting it.
It requires both server.stream-request-body=2 and a delay between sending request headers and pieces of the request body.
I could not (quickly) reproduce this with pauses between packets in the existing lighttpd test framework, so I've added an item to my todo list.
Updated by gstrauss about 6 years ago
- Status changed from Patch Pending to Fixed
- % Done changed from 0 to 100
Applied in changeset fe3dc1796894d22ad60da24d2bfc25fbf612861c.
Updated by rgenoud about 6 years ago
gstrauss wrote:
Applied in changeset fe3dc1796894d22ad60da24d2bfc25fbf612861c.
Thanks,
It's working !
Also available in: Atom