sxia-aviatrix opened a new pull request, #13574:
URL: https://github.com/apache/trafficserver/pull/13574
## Summary
Fix a use-after-free crash in `HttpSM::state_read_server_response_header()`
when `abort_tunnel()` is called while a request transform plugin registered
at `TS_HTTP_READ_REQUEST_HDR_HOOK` is active.
## Bug
When a POST request has a request transform and the origin server responds
before the full body is forwarded through the transform chain:
1. `state_read_server_response_header()` calls `abort_tunnel()`
2. `abort_tunnel()` frees the TransformVConnection chain but does NOT
clean up `post_transform_info.entry` in the vc_table
3. `cleanup_all()` in `kill_this()` later calls `do_io_close()` on the
freed pointer
4. Crash with SIGSEGV or `std::bad_function_call`
The bug only triggers when the request transform is added before the tunnel
starts (e.g. at `TS_HTTP_READ_REQUEST_HDR_HOOK`). Transforms added at
`TS_HTTP_TUNNEL_START_HOOK` become part of the tunnel chain and are properly
cleaned up by `abort_tunnel()`.
## How to reproduce
1. In `src/proxy/http/HttpSM.cc`, uncomment the assert after
`abort_tunnel()`:
`ink_release_assert(post_transform_info.entry == nullptr);`
This assert verifies that `post_transform_info.entry` should have been
cleaned up after `abort_tunnel()`, but without the fix it is left
dangling.
The assert turns the silent use-after-free (which depends on timing and
memory reuse to crash) into a guaranteed SIGABRT.
2. Load a request transform plugin that hooks at
`TS_HTTP_READ_REQUEST_HDR_HOOK`
3. Send a POST request with a large `Content-Length` but only a small body
4. Have the origin respond immediately (before ATS finishes forwarding the
body)
5. ATS crashes with SIGABRT from the assert (or in production without the
assert, crashes intermittently in `kill_this()` → `cleanup_all()` →
`do_io_close()` on the stale `post_transform_info.entry`)
## Fix
After `abort_tunnel()`, clean up the stale `post_transform_info.entry`:
set `in_tunnel = false` (since `abort_tunnel()` sets it to true) so that
`cleanup_entry()` calls `do_io_close()`, then null the entry pointer.
## Test
Added `post_early_response_transform.test.py` which:
- Loads `null_transform_request.so` — a copy of the existing
`tunnel_transform.cc` test plugin with two changes:
1. Hook changed from `TS_HTTP_TUNNEL_START_HOOK` to
`TS_HTTP_READ_REQUEST_HDR_HOOK` (registers the transform before the
tunnel starts, exposing the bug)
2. Output VIO size changed from `INT64_MAX` to `TSVIONBytesGet(input_vio)`
(uses actual content length so data flows through the transform when
hooked before the tunnel)
- Sends a partial POST (Content-Length: 100000, sends only 4096 bytes)
via `partial_post_client.py`
- Origin (`quick_server.py`) responds immediately before the full body
arrives
- Without the fix, ATS crashes (SIGABRT). With the fix, ATS handles the
abort cleanly.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]