Commit 68a2c3d
authored
tls: fix UAF in server ALPN callback under concurrent handshakes (#29800)
## What does this PR do?
Fixes a use-after-free in `selectALPNCallback`
(`src/bun.js/api/bun/socket.zig:17`) when a `node:tls` / `Bun.listen`
TLS server with `ALPNProtocols` handles overlapping handshakes.
`SSL_CTX_set_alpn_select_cb` registers on the **listener-level**
`SSL_CTX`, so its `arg` is shared across every accepted connection. The
old code passed the per-connection `*TLSSocket` as `arg`, so each
`onOpen` overwrote the previous one. When connection A's ClientHello is
processed after connection B's `onOpen` has run — and B has since been
freed — the callback dereferences a dangling pointer and feeds garbage
`protos` into `SSL_select_next_proto`:
```
#9 SSL_select_next_proto (..., peer=0xb10008886384bf6d, peer_len=1431130639,
supported="\002h2\bhttp/1.1", supported_len=12)
#10 selectALPNCallback (in="\002h2\bhttp/1.1", inlen=12, arg=<freed>) at socket.zig:23
#11 bssl::ssl_negotiate_alpn
#12 bssl::do_select_parameters
#21 ssl_on_data at openssl.c:505
```
(from `fetch-http2-client.test.ts` under `describe.concurrent` on
`:alpine: 3.23 aarch64`)
**Fix:** store the `*TLSSocket` on the per-connection `SSL` via
`SSL_set_ex_data(ssl, 0, this)` and read it back from the `SSL*`
parameter in the callback, ignoring the CTX-level `arg`. Slot 0 is
otherwise unused in the codebase.
## How did you verify your code works?
- `bun bd test test/js/node/tls/node-tls-server.test.ts
test/js/node/tls/node-tls-connect.test.ts
test/js/node/http2/node-http2.test.js
test/js/web/fetch/fetch-http2-client.test.ts` → 349 pass, 0 fail
- `bun run zig:check-all` → all platforms compile
- The existing `connectionListener should emit the right amount of
times, and with alpnProtocol available` test (50 parallel ALPN
connections) covers the path; the original crash was caught by
`fetch-http2-client.test.ts` on aarch64-musl CI1 parent 8e13869 commit 68a2c3d
1 file changed
Lines changed: 10 additions & 3 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
14 | 14 | | |
15 | 15 | | |
16 | 16 | | |
17 | | - | |
18 | | - | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
19 | 23 | | |
20 | 24 | | |
21 | 25 | | |
| |||
459 | 463 | | |
460 | 464 | | |
461 | 465 | | |
462 | | - | |
| 466 | + | |
| 467 | + | |
| 468 | + | |
| 469 | + | |
463 | 470 | | |
464 | 471 | | |
465 | 472 | | |
| |||
0 commit comments