Since version 1.24, Go now defaults to opening MPTCP sockets for listeners when it believes this is supported by the kernel (see https://go-review.googlesource.com/c/go/+/607715).
This is a bit unfortunate as the kernel will crash immediately when TSI-highjacking is used:
[GIN-debug] Listening and serving HTTP on 0.0.0.0:3000
[ 35.475734] tsi_create (463): problem creating inet socket
[ 35.475829] BUG: kernel NULL pointer dereference, address: 0000000000000020
[ 35.475907] #PF: supervisor read access in kernel mode
[ 35.476048] #PF: error_code(0x0000) - not-present page
[ 35.476248] PGD 4ac9067 P4D 4ac9067 PUD 4aca067 PMD 0
[ 35.476359] Oops: Oops: 0000 [#1] PREEMPT SMP NOPTI
[ 35.476567] CPU: 3 UID: 0 PID: 463 Comm: ebuild Not tainted 6.12.20 #1
[ 35.476656] RIP: 0010:tsi_create.part.0.cold+0x30/0x7a
[ 35.476838] Code: 00 48 c7 c6 10 28 c8 81 48 c7 c7 d0 03 e4 81 e8 4e c7 fc ff 48 8b 7c 24 08 48 8b 47 20 48 8b 40 10 ff d0 0f 1f 00 48 8b 3c 24 <48> 8b 47 20 48 8b 40 10 ff d0 0f 1f 00 e9 58 b7 f9 ff 41 8b 95 c0
[ 35.477722] RSP: 0018:ffffc90000d9be70 EFLAGS: 00010246
[ 35.478107] RAX: 000000000000002e RBX: 00000000ffffffa3 RCX: 0000000000000003
[ 35.478211] RDX: 0000000000000000 RSI: 0000000000000003 RDI: 0000000000000000
[ 35.478311] RBP: ffff8880054c2700 R08: 0000000000000000 R09: ffffc90000d9bd08
[ 35.478411] R10: ffff88807ffc7fa8 R11: 0000000000000003 R12: ffff8880045a8000
[ 35.478508] R13: ffff888002b78000 R14: ffff8880054c2700 R15: ffffffff82261b80
[ 35.478596] FS: 00007f5e7e7fc6c0(0000) GS:ffff88807fcc0000(0000) knlGS:0000000000000000
[ 35.478683] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 35.478776] CR2: 0000000000000020 CR3: 00000000037f4003 CR4: 0000000000370eb0
[ 35.478866] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 35.479046] DR3: 0000000000000000 DR6: 00000000ffff07f0 DR7: 0000000000000400
[ 35.479185] Call Trace:
[ 35.479207] <TASK>
[ 35.479235] ? show_trace_log_lvl+0x148/0x1b0
[ 35.479309] ? show_trace_log_lvl+0x148/0x1b0
[ 35.479366] ? __die+0x4d/0x89
[ 35.479422] ? page_fault_oops+0x8b/0xe0
[ 35.479498] ? prb_read_valid+0x12/0x20
[ 35.479563] ? exc_page_fault+0x60/0xc0
[ 35.479605] ? asm_exc_page_fault+0x22/0x30
[ 35.479643] ? tsi_create.part.0.cold+0x30/0x7a
[ 35.479742] ? alloc_inode+0x31/0xc0
[ 35.479817] ? __sock_create+0xe3/0x190
[ 35.479893] ? __sys_socket+0x7a/0x100
[ 35.479968] ? __x64_sys_socket+0xe/0x20
[ 35.480024] ? do_syscall_64+0x47/0x110
[ 35.480086] ? entry_SYSCALL_64_after_hwframe+0x76/0x7e
[ 35.480143] </TASK>
[ 35.480189] CR2: 0000000000000020
[ 35.480270] ---[ end trace 0000000000000000 ]---
[ 35.480338] RIP: 0010:tsi_create.part.0.cold+0x30/0x7a
[ 35.480415] Code: 00 48 c7 c6 10 28 c8 81 48 c7 c7 d0 03 e4 81 e8 4e c7 fc ff 48 8b 7c 24 08 48 8b 47 20 48 8b 40 10 ff d0 0f 1f 00 48 8b 3c 24 <48> 8b 47 20 48 8b 40 10 ff d0 0f 1f 00 e9 58 b7 f9 ff 41 8b 95 c0
[ 35.480586] RSP: 0018:ffffc90000d9be70 EFLAGS: 00010246
[ 35.480628] RAX: 000000000000002e RBX: 00000000ffffffa3 RCX: 0000000000000003
[ 35.480684] RDX: 0000000000000000 RSI: 0000000000000003 RDI: 0000000000000000
[ 35.480742] RBP: ffff8880054c2700 R08: 0000000000000000 R09: ffffc90000d9bd08
[ 35.480797] R10: ffff88807ffc7fa8 R11: 0000000000000003 R12: ffff8880045a8000
[ 35.480850] R13: ffff888002b78000 R14: ffff8880054c2700 R15: ffffffff82261b80
[ 35.480919] FS: 00007f5e7e7fc6c0(0000) GS:ffff88807fcc0000(0000) knlGS:0000000000000000
[ 35.480974] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 35.481037] CR2: 0000000000000020 CR3: 00000000037f4003 CR4: 0000000000370eb0
[ 35.481140] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 35.481226] DR3: 0000000000000000 DR6: 00000000ffff07f0 DR7: 0000000000000400
[ 35.481322] note: ebuild[463] exited with irqs disabled
This can be reproduced easily with a Go program along these lines:
package main
import (
"fmt"
"net/http"
)
func hello(w http.ResponseWriter, req *http.Request) {
fmt.Fprintf(w, "hello\n")
}
func main() {
http.HandleFunc("/hello", hello)
http.ListenAndServe(":8090", nil)
}
The current work-around is to start with GODEBUG="multipathtcp=0". It would be better though to either return EPROTONOSUPPORT or disable MPTCP in the provided configurations (see https://cs.opensource.google/go/go/+/refs/tags/go1.25.1:src/net/mptcpsock_linux.go;l=36).
Since version 1.24, Go now defaults to opening MPTCP sockets for listeners when it believes this is supported by the kernel (see https://go-review.googlesource.com/c/go/+/607715).
This is a bit unfortunate as the kernel will crash immediately when TSI-highjacking is used:
This can be reproduced easily with a Go program along these lines:
The current work-around is to start with
GODEBUG="multipathtcp=0". It would be better though to either returnEPROTONOSUPPORTor disable MPTCP in the provided configurations (see https://cs.opensource.google/go/go/+/refs/tags/go1.25.1:src/net/mptcpsock_linux.go;l=36).