Re: [BUG] null-ptr-deref bug in sctp_packet_bundle_auth
Xin Long <[email protected]>
| Newsgroups | org.kernel.vger.linux-sctp |
|---|---|
| Message-ID | <CADvbK_dvRiP05x-+rfvz0vbRO5a4iVmEFKmSsKiQnLEmKENNxw@mail.gmail.com> |
On Thu, Jan 8, 2026 at 3:20 AM Chen Zhen <[email protected]> wrote: > > On 25/12/18 10:00, Chen Zhen wrote: > > ================== > > Syzkaller reproducer: > > > > {Threaded:false Repeat:true RepeatTimes:0 Procs:10 Slowdown:1 Sandbox:none SandboxArg:0 Leak:false NetInjection:true NetDevices:true NetReset:true Cgroups:true BinfmtMisc:true CloseFDs:true KCSAN:false DevlinkPCI:false NicVF:false USB:false VhciInjection:false Wifi:false IEEE802154:false Sysctl:true Swap:true UseTmpDir:true HandleSegv:true Repro:false Trace:false LegacyOptions:{Collide:false Fault:false FaultCall:0 FaultNth:0}} > > perf_event_open(0x0, 0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0x0) > > sendmsg$nl_route_sched(0xffffffffffffffff, 0x0, 0x0) > > r0 = perf_event_open(0x0, 0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0x0) > > r1 = socket$key(0xf, 0x3, 0x2) > > sendmsg$key(r1, 0x0, 0x0) > > fchown(r0, 0x0, 0xee01) > > sendmsg$key(r1, 0x0, 0x0) > > read$FUSE(0xffffffffffffffff, 0x0, 0x0) > > prlimit64(0x0, 0xe, 0x0, 0x0) > > sched_setscheduler(0x0, 0x2, 0x0) > > sched_setscheduler(0x0, 0x2, 0x0) > > ioctl$FS_IOC_SETFLAGS(0xffffffffffffffff, 0x40086602, 0x0) > > sendmmsg$unix(0xffffffffffffffff, 0x0, 0x0, 0x0) > > openat$null(0xffffffffffffff9c, 0x0, 0x600000, 0x0) > > getpgid(0x0) > > socket$nl_xfrm(0x10, 0x3, 0x6) > > perf_event_open(0x0, 0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0x0) > > perf_event_open(&(0x7f0000000200)={0x1, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, @perf_bp={0x0}}, 0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0x0) > > write$eventfd(0xffffffffffffffff, 0x0, 0x0) > > perf_event_open(0x0, 0xffffffffffffffff, 0x0, 0xffffffffffffffff, 0x3) > > perf_event_open(0x0, 0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0x0) > > socket$vsock_dgram(0x28, 0x2, 0x0) > > clock_adjtime(0x0, 0x0) > > perf_event_open(0x0, 0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0x0) > > perf_event_open(&(0x7f0000000200)={0x1, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x50d, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, @perf_bp={0x0}}, 0x0, 0xffffffffffffffff, 0xffffffffffffffff, 0x0) > > r2 = socket$inet6_sctp(0xa, 0x1, 0x84) > > setsockopt(r2, 0x84, 0x81, &(0x7f00000002c0)="1a00000019000000", 0x8) > > setsockopt$inet_sctp_SCTP_SOCKOPT_BINDX_ADD(r2, 0x84, 0x64, &(0x7f0000000380)=[@in6={0xa, 0x4e23, 0x0, @loopback}], 0x1c) > > setsockopt$inet_sctp6_SCTP_AUTH_CHUNK(r2, 0x84, 0x15, &(0x7f00000001c0), 0x1) > > r3 = syz_open_procfs$procfs_self_proc_file(0xffffffffffffffff, &(0x7f0000000180)='fail-nth\x00') > > write$cgroup_int(r3, &(0x7f0000000200)=0x48, 0x12) > > perf_event_open(&(0x7f0000000480)={0x0, 0x80, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, @perf_config_ext}, 0xffffffffffffffff, 0x0, 0xffffffffffffffff, 0x0) > > r4 = openat$euleros_proc_task_file(0xffffffffffffff9c, &(0x7f0000000440)='/proc/self/patch_state\x00', 0x20000, 0x0) > > perf_event_open(0x0, 0x0, 0x6, r4, 0x2) > > setsockopt$inet_sctp6_SCTP_ASSOCINFO(r3, 0x84, 0x1, &(0x7f0000000040)={0x0, 0xd6, 0x2, 0x2d820323, 0x7, 0x1}, 0x14) > > sendto$inet6(r2, &(0x7f0000000000)=' ', 0x1, 0x0, &(0x7f0000000080)={0xa, 0x4e23, 0x0, @loopback}, 0x1c) > > sendto$inet6(r2, &(0x7f0000000000)=' ', 0x1, 0x0, &(0x7f0000000080)={0xa, 0x4e23, 0x0, @loopback}, 0x1c) > > ================== > > > > It seems to be rare case because I cannot trigger this bug again with 24h+ of reproducing. > > > > Thanks. > After 10+ days of reproducing the bug finally re-occur... > I investigated the vmcore dmesg and found this fault-injection backtrace just > before the bug happened: > ====================== > FAULT_INJECTION: forcing a failure. > name failslab, interval 1, probability 0, space 0, times 0 > CPU: 0 PID: 2898 Comm: syz-executor.8 Kdump: loaded Tainted: G W 6.6.0 #2 > Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.13.0-1ubuntu1.1 04/01/2014 > Call Trace: > <TASK> > dump_stack_lvl+0xbd/0xe0 > should_fail_ex+0x4b0/0x5b0 > should_failslab+0xc3/0x120 > __kmem_cache_alloc_node+0x67/0x5f0 > __kmalloc+0x4e/0x150 > sctp_auth_create_key+0x3d/0xe0 > sctp_auth_make_key_vector+0x103/0x1e0 > sctp_auth_asoc_create_secret+0xc6/0x340 > sctp_auth_asoc_init_active_key.part.0+0x160/0x4b0 > sctp_auth_asoc_init_active_key+0x67/0x90 > sctp_cmd_interpreter.isra.0+0x2ccc/0x62c0 > sctp_do_sm+0x1a3/0x670 > sctp_assoc_bh_rcv+0x33e/0x640 > sctp_inq_push+0x1dd/0x280 > sctp_backlog_rcv+0x19e/0x11c0 > __release_sock+0x29c/0x310 > release_sock+0x59/0x1b0 > sctp_wait_for_connect+0x35f/0x5d0 > sctp_sendmsg_to_asoc+0x1865/0x1c90 > sctp_sendmsg+0xc98/0x1e40 > inet_sendmsg+0x122/0x150 > __sock_sendmsg+0x1c6/0x2a0 > __sys_sendto+0x203/0x2e0 > __x64_sys_sendto+0xe2/0x1c0 > do_syscall_64+0x6c/0x120 > entry_SYSCALL_64_after_hwframe+0x78/0xe2 > RIP: 0033:0x7f70f2493bdd > Code: c3 e8 17 32 00 00 0f 1f 80 00 00 00 00 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 b8 ff ff ff f7 d8 64 89 01 48 > RSP: 002b:00007f70f1ffebf8 EFLAGS: 00000246 ORIG_RAX: 000000000000002c > RAX: ffffffffffffffda RBX: 00007f70f25dbf80 RCX: 00007f70f2493bdd > RDX: 0000000000000001 RSI: 0000000020000000 RDI: 0000000000000005 > RBP: 00007f70f24f1499 R08: 0000000020000080 R09: 000000000000001c > R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 > R13: 00007fffe62d14df R14: 00007fffe62d1680 R15: 00007f70f1ffed80 > </TASK> > ====================== > And indeed the asoc->shkey、asoc->asoc_shared_key、chunk->auth_chunk、chunk->shkey > are all NULL in the vmcore memory. > Is there any possible that the slab force failure caused the asoc->shkey NULL > then chunk->shkey NULL after sctp_datamsg_from_user() but chunk->auth is true > so resulted in null-ptr-deref? > Hi Chen, Thanks for reproducing it. Yes, I think I can make sense of this now. The slab force failure happens while processing INIT_ACK along the following path: sctp_do_sm() -> sctp_sf_do_5_1C_ack() -> sctp_cmd_interpreter(SCTP_CMD_ASSOC_SHKEY) -> sctp_auth_asoc_init_active_key() <-- FAILED In sctp_sf_do_5_1C_ack(), the SCTP_CMD_ASSOC_SHKEY command (which calls sctp_auth_asoc_init_active_key) is currently added after: - SCTP_CMD_TIMER_START (starting the T1_COOKIE timer), and - SCTP_CMD_NEW_STATE (transition to COOKIE_ECHOED). If SCTP_CMD_ASSOC_SHKEY fails, asoc->shkey remains NULL. However, asoc->peer.auth_capable and asoc->peer.peer_chunks have already been set earlier by SCTP_CMD_PEER_INIT (via sctp_cmd_process_init). As a result, a DATA chunk with auth = 1 and shkey = NULL can still be queued for transmission. At that point, the association has already entered the COOKIE_ECHOED state, and the T1_COOKIE timer may generate a COOKIE_ECHO chunk. Then, sctp_outq_flush_data() allows the DATA chunk to send in COOKIE_ECHOED state when a COOKIE_ECHO chunk exists, which leads to the observed issue. My thought is to move the SCTP_CMD_ASSOC_SHKEY command before SCTP_CMD_TIMER_START (T1_COOKIE), even before SCTP_CMD_TIMER_STOP (T1_INIT). This way, if shared key generation fails, the DATA chunk in the outqueue won’t be allowed to send, and the T1_INIT timer can also retransmit INIT. The client can then receive/process INIT_ACK again and retry SCTP_CMD_ASSOC_SHKEY in sctp_sf_do_5_1C_ack(). Something like: diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 3755ba079d07..7b823d759141 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c @@ -603,6 +603,11 @@ enum sctp_disposition sctp_sf_do_5_1C_ack(struct net *net, sctp_add_cmd_sf(commands, SCTP_CMD_PEER_INIT, SCTP_PEER_INIT(initchunk)); + /* SCTP-AUTH: generate the association shared keys so that + * we can potentially sign the COOKIE-ECHO. + */ + sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_SHKEY, SCTP_NULL()); + /* Reset init error count upon receipt of INIT-ACK. */ sctp_add_cmd_sf(commands, SCTP_CMD_INIT_COUNTER_RESET, SCTP_NULL()); @@ -617,11 +622,6 @@ enum sctp_disposition sctp_sf_do_5_1C_ack(struct net *net, sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, SCTP_STATE(SCTP_STATE_COOKIE_ECHOED)); - /* SCTP-AUTH: generate the association shared keys so that - * we can potentially sign the COOKIE-ECHO. - */ - sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_SHKEY, SCTP_NULL()); - /* 5.1 C) "A" shall then send the State Cookie received in the * INIT ACK chunk in a COOKIE ECHO chunk, ... */ Could you give this a try? Thanks.