Commit 1245fa0
committed
bugfix: prevent SIGSEGV in receiveuntil __gc on aborted multipart upload.
A client that POSTs a multipart body and aborts the connection
mid-pattern against ngx.req.socket():receiveuntil(boundary) can
SIGSEGV the worker from the LuaJIT GC's __gc finalizer on the
compiled-pattern userdata.
ngx_http_lua_socket_read_error_retval_handler calls
ngx_http_lua_socket_tcp_finalize_read_part directly when the
receiveuntil iterator's recv returns an error (e.g. client RST).
finalize_read_part clears u->buf_in / u->bufs_in and memzeros
u->buffer, but does not detach the compiled-pattern userdata held
in u->input_filter_ctx -- so cp->upstream stays pointing at u and
cp->state stays > 0 (the DFA stopped mid-match).
Later, when LuaJIT GC sweeps the cp userdata,
ngx_http_lua_socket_cleanup_compiled_pattern fires and calls
ngx_http_lua_socket_tcp_read_prepare(r, u, NULL). cp->state > 0
forces the recovery branches that read u->buf_in->buf->pos -- a
NULL deref.
Fix: in finalize_read_part, clear cp->upstream mirroring the same
detach that ngx_http_lua_socket_tcp_finalize already performs. This
short-circuits the __gc handler at its existing `if (u != NULL)`
guard, so the bad code path is never entered.
Reproducer:
POST a multipart body that ends mid-boundary, then close the
socket with SO_LINGER {1,0} so the server reads RST while the
DFA is mid-match. Lua handler does:
local sock = ngx.req.socket()
local iter = sock:receiveuntil("--" .. BOUNDARY)
while true do
local d = iter(1)
if not d then break end
end
collectgarbage("collect")
With the body shaped as six leading dashes against a 12-dash
boundary leader, cp->state lands at 6 with no DFA fallback,
and the synchronous collectgarbage runs cp's __gc inside the
request -- 100% crash rate.
Crash signature:
#0 ngx_http_lua_socket_tcp_read_prepare (data=0x0)
[inlined memcpy at ngx_http_lua_socket_tcp.c, recovery
branch, u->buf_in == NULL]
#1 ngx_http_lua_socket_cleanup_compiled_pattern
ngx_http_lua_socket_tcp.c
#2 lj_BC_FUNCC buildvm_x86.dasc
#3 gc_call_finalizer lj_gc.c
#4 gc_finalize lj_gc.c
#5 gc_onestep lj_gc.c
#6 lj_gc_fullgc lj_gc.c
#7 lua_gc (what=LUA_GCCOLLECT) lj_api.c
#8 lj_cf_collectgarbage lib_base.c
#9 lj_BC_FUNCC buildvm_x86.dasc
#10 ngx_http_lua_run_thread ngx_http_lua_util.c
#11 ngx_http_lua_socket_tcp_resume_helper ngx_http_lua_socket_tcp.c
#12 ngx_http_lua_socket_tcp_read ngx_http_lua_socket_tcp.c
#13 ngx_http_request_handler src/http/ngx_http_request.c1 parent 41ed26b commit 1245fa0
1 file changed
Lines changed: 8 additions & 0 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
4203 | 4203 | | |
4204 | 4204 | | |
4205 | 4205 | | |
| 4206 | + | |
| 4207 | + | |
| 4208 | + | |
| 4209 | + | |
| 4210 | + | |
| 4211 | + | |
| 4212 | + | |
| 4213 | + | |
4206 | 4214 | | |
4207 | 4215 | | |
4208 | 4216 | | |
| |||
0 commit comments