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]

Reply via email to