linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [Linux Kernel Bug] UBSAN: array-index-out-of-bounds in rds_cmsg_recv
@ 2024-01-19 14:29 Chenyuan Yang
  2024-01-21  8:34 ` Zhu Yanjun
  0 siblings, 1 reply; 7+ messages in thread
From: Chenyuan Yang @ 2024-01-19 14:29 UTC (permalink / raw)
  To: santosh.shilimkar, netdev, linux-rdma, rds-devel, linux-kernel
  Cc: davem, edumazet, kuba, pabeni, syzkaller, Zijie Zhao

[-- Attachment #1: Type: text/plain, Size: 1012 bytes --]

Dear Linux Kernel Developers for Network RDS,

We encountered "UBSAN: array-index-out-of-bounds in rds_cmsg_recv"
when testing the RDS with our generated specifications. The C
reproduce program and logs for this crash are attached.

This crash happens when RDS receives messages by using
`rds_cmsg_recv`, which reads the `j+1` index of the array
`inc->i_rx_lat_trace`
(https://elixir.bootlin.com/linux/v6.7/source/net/rds/recv.c#L585).
The length of `inc->i_rx_lat_trace` array is 4 (defined by
`RDS_RX_MAX_TRACES`,
https://elixir.bootlin.com/linux/v6.7/source/net/rds/rds.h#L289) while
`j` is the value stored in another array `rs->rs_rx_trace`
(https://elixir.bootlin.com/linux/v6.7/source/net/rds/recv.c#L583),
which is sent from others and could be arbitrary value.

This crash might be exploited to read the value out-of-bound from the
array by setting arbitrary values for the array `rs->rs_rx_trace`.

If you have any questions or require more information, please feel
free to contact us.

Best,
Chenyuan

[-- Attachment #2: repro.prog --]
[-- Type: application/octet-stream, Size: 925 bytes --]

# {Threaded:false Repeat:false RepeatTimes:0 Procs:1 Slowdown:1 Sandbox:none SandboxArg:0 Leak:false NetInjection:false NetDevices:true NetReset:false Cgroups:false BinfmtMisc:false CloseFDs:false KCSAN:false DevlinkPCI:false NicVF:false USB:false VhciInjection:false Wifi:false IEEE802154:false Sysctl:false Swap:false UseTmpDir:false HandleSegv:false Repro:false Trace:false LegacyOptions:{Collide:false Fault:false FaultCall:0 FaultNth:0}}
r0 = socket$KGPT_RDS(0x15, 0x5, 0x0)
setsockopt$KGPT_SO_RDS_MSG_RXPATH_LATENCY(r0, 0x114, 0xa, &(0x7f00000000c0)=ANY=[@ANYRES8=r0, @ANYRES16=r0, @ANYRES8=r0, @ANYRESHEX=r0, @ANYRES8=0x0, @ANYRES64=r0, @ANYRES8=0x0, @ANYRES16, @ANYRES32, @ANYRES8], 0x4)
connect$rds(r0, &(0x7f0000000080)={0x2, 0x0, @local}, 0x10)
bind$rds(r0, &(0x7f0000000540)={0x2, 0x0, @local}, 0x10)
sendto$KGPT_rds_proto_ops(r0, 0x0, 0x0, 0x0, 0x0, 0x0)
recvfrom$KGPT_rds_proto_ops(r0, 0x0, 0x0, 0x0, 0x0, 0x0)

[-- Attachment #3: repro.report --]
[-- Type: application/octet-stream, Size: 1925 bytes --]

netdevsim netdevsim0 netdevsim2: set [1, 0] type 2 family 0 port 6081 - 0
netdevsim netdevsim0 netdevsim3: set [1, 0] type 2 family 0 port 6081 - 0
================================================================================
UBSAN: array-index-out-of-bounds in net/rds/recv.c:585:39
index 4 is out of range for type 'u64 [4]'
CPU: 1 PID: 8058 Comm: syz-executor228 Not tainted 6.6.0-gd2f51b3516da #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
Call Trace:
 <TASK>
 __dump_stack lib/dump_stack.c:88 [inline]
 dump_stack_lvl+0x136/0x150 lib/dump_stack.c:106
 ubsan_epilogue lib/ubsan.c:217 [inline]
 __ubsan_handle_out_of_bounds+0xd5/0x130 lib/ubsan.c:348
 rds_cmsg_recv+0x60d/0x700 net/rds/recv.c:585
 rds_recvmsg+0x3fb/0x1610 net/rds/recv.c:716
 sock_recvmsg_nosec net/socket.c:1044 [inline]
 sock_recvmsg+0xe2/0x160 net/socket.c:1066
 __sys_recvfrom+0x1b6/0x2f0 net/socket.c:2246
 __do_sys_recvfrom net/socket.c:2264 [inline]
 __se_sys_recvfrom net/socket.c:2260 [inline]
 __x64_sys_recvfrom+0xe0/0x1b0 net/socket.c:2260
 do_syscall_x64 arch/x86/entry/common.c:51 [inline]
 do_syscall_64+0x40/0x110 arch/x86/entry/common.c:82
 entry_SYSCALL_64_after_hwframe+0x63/0x6b
RIP: 0033:0x7fdd574dad9d
Code: 28 c3 e8 e6 22 00 00 66 0f 1f 44 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:00007fff993d59f8 EFLAGS: 00000246 ORIG_RAX: 000000000000002d
RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00007fdd574dad9d
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000003
RBP: 00007fdd57533380 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 00007fff993d5a40
R13: 00007fff993d5a60 R14: 00007fdd57567300 R15: 00007fdd57533366
 </TASK>
================================================================================

[-- Attachment #4: repro.log --]
[-- Type: application/octet-stream, Size: 15746 bytes --]


Debian GNU/Linux 11 syzkaller ttyS0

Warning: Permanently added '[localhost]:34396' (ED25519) to the list of known hosts.
syzkaller login: [   76.563563][ T8058] chnl_net:caif_netlink_parms(): no params data found
[   76.658011][ T8058] bridge0: port 1(bridge_slave_0) entered blocking state
[   76.658506][ T8058] bridge0: port 1(bridge_slave_0) entered disabled state
[   76.659084][ T8058] bridge_slave_0: entered allmulticast mode
[   76.660299][ T8058] bridge_slave_0: entered promiscuous mode
[   76.663217][ T8058] bridge0: port 2(bridge_slave_1) entered blocking state
[   76.663702][ T8058] bridge0: port 2(bridge_slave_1) entered disabled state
[   76.664144][ T8058] bridge_slave_1: entered allmulticast mode
[   76.665860][ T8058] bridge_slave_1: entered promiscuous mode
[   76.705902][ T8058] bond0: (slave bond_slave_0): Enslaving as an active interface with an up link
[   76.711053][ T8058] bond0: (slave bond_slave_1): Enslaving as an active interface with an up link
[   76.744093][ T8058] team0: Port device team_slave_0 added
[   76.747721][ T8058] team0: Port device team_slave_1 added
[   76.773132][ T8058] batman_adv: batadv0: Adding interface: batadv_slave_0
[   76.774069][ T8058] batman_adv: batadv0: The MTU of interface batadv_slave_0 is too small (1500) to handle the transport of batman-adv packets. Packets going over this interface will be fragmented on layer2 which could impact the performance. Setting the MTU to 1560 would solve the problem.
[   76.775801][ T8058] batman_adv: batadv0: Not using interface batadv_slave_0 (retrying later): interface not active
[   76.780194][ T8058] batman_adv: batadv0: Adding interface: batadv_slave_1
[   76.780722][ T8058] batman_adv: batadv0: The MTU of interface batadv_slave_1 is too small (1500) to handle the transport of batman-adv packets. Packets going over this interface will be fragmented on layer2 which could impact the performance. Setting the MTU to 1560 would solve the problem.
[   76.782464][ T8058] batman_adv: batadv0: Not using interface batadv_slave_1 (retrying later): interface not active
[   76.823268][ T8058] hsr_slave_0: entered promiscuous mode
[   76.824366][ T8058] hsr_slave_1: entered promiscuous mode
[   77.009502][ T8058] netdevsim netdevsim0 netdevsim0: renamed from eth0
[   77.016829][ T8058] netdevsim netdevsim0 netdevsim1: renamed from eth1
[   77.022014][ T8058] netdevsim netdevsim0 netdevsim2: renamed from eth2
[   77.027136][ T8058] netdevsim netdevsim0 netdevsim3: renamed from eth3
[   77.058249][ T8058] bridge0: port 2(bridge_slave_1) entered blocking state
[   77.058848][ T8058] bridge0: port 2(bridge_slave_1) entered forwarding state
[   77.059787][ T8058] bridge0: port 1(bridge_slave_0) entered blocking state
[   77.060270][ T8058] bridge0: port 1(bridge_slave_0) entered forwarding state
[   77.121388][ T8058] 8021q: adding VLAN 0 to HW filter on device bond0
[   77.132911][   T55] bridge0: port 1(bridge_slave_0) entered disabled state
[   77.134359][   T55] bridge0: port 2(bridge_slave_1) entered disabled state
[   77.145134][ T8058] 8021q: adding VLAN 0 to HW filter on device team0
[   77.153978][   T27] bridge0: port 1(bridge_slave_0) entered blocking state
[   77.154733][   T27] bridge0: port 1(bridge_slave_0) entered forwarding state
[   77.170108][   T55] bridge0: port 2(bridge_slave_1) entered blocking state
[   77.170751][   T55] bridge0: port 2(bridge_slave_1) entered forwarding state
[   77.259307][ T8058] 8021q: adding VLAN 0 to HW filter on device batadv0
[   77.319233][ T8058] veth0_vlan: entered promiscuous mode
[   77.331313][ T8058] veth1_vlan: entered promiscuous mode
[   77.362228][ T8058] veth0_macvtap: entered promiscuous mode
[   77.367879][ T8058] veth1_macvtap: entered promiscuous mode
[   77.393904][ T8058] batman_adv: batadv0: Interface activated: batadv_slave_0
[   77.404207][ T8058] batman_adv: batadv0: Interface activated: batadv_slave_1
[   77.409640][ T8058] netdevsim netdevsim0 netdevsim0: set [1, 0] type 2 family 0 port 6081 - 0
[   77.410260][ T8058] netdevsim netdevsim0 netdevsim1: set [1, 0] type 2 family 0 port 6081 - 0
[   77.410845][ T8058] netdevsim netdevsim0 netdevsim2: set [1, 0] type 2 family 0 port 6081 - 0
[   77.411419][ T8058] netdevsim netdevsim0 netdevsim3: set [1, 0] type 2 family 0 port 6081 - 0
executing program
[   77.476675][ T8058] ================================================================================
[   77.477434][ T8058] UBSAN: array-index-out-of-bounds in net/rds/recv.c:585:39
[   77.477981][ T8058] index 4 is out of range for type 'u64 [4]'
[   77.478419][ T8058] CPU: 1 PID: 8058 Comm: syz-executor228 Not tainted 6.6.0-gd2f51b3516da #1
[   77.479015][ T8058] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
[   77.479836][ T8058] Call Trace:
[   77.480190][ T8058]  <TASK>
[   77.480448][ T8058]  dump_stack_lvl+0x136/0x150
[   77.480825][ T8058]  __ubsan_handle_out_of_bounds+0xd5/0x130
[   77.481488][ T8058]  ? kvm_sched_clock_read+0x16/0x20
[   77.481933][ T8058]  rds_cmsg_recv+0x60d/0x700
[   77.482537][ T8058]  ? rds_recvmsg_zcookie+0x490/0x490
[   77.483058][ T8058]  ? rds_recvmsg+0x695/0x1610
[   77.483436][ T8058]  ? lock_downgrade+0x6a0/0x6a0
[   77.483836][ T8058]  ? _raw_write_unlock_irqrestore+0x54/0x70
[   77.484287][ T8058]  rds_recvmsg+0x3fb/0x1610
[   77.484646][ T8058]  ? rds_notify_queue_get+0x760/0x760
[   77.485120][ T8058]  ? aa_af_perm+0x240/0x240
[   77.485475][ T8058]  ? prepare_to_swait_exclusive+0x240/0x240
[   77.485934][ T8058]  ? bpf_lsm_socket_recvmsg+0x9/0x10
[   77.486345][ T8058]  ? security_socket_recvmsg+0x93/0xc0
[   77.486751][ T8058]  ? rds_notify_queue_get+0x760/0x760
[   77.487175][ T8058]  sock_recvmsg+0xe2/0x160
[   77.487517][ T8058]  __sys_recvfrom+0x1b6/0x2f0
[   77.487876][ T8058]  ? __ia32_sys_send+0x100/0x100
[   77.488261][ T8058]  ? lock_downgrade+0x6a0/0x6a0
[   77.488684][ T8058]  ? __rseq_handle_notify_resume+0x5cf/0x1000
[   77.489175][ T8058]  ? __ia32_sys_socketpair+0x100/0x100
[   77.489590][ T8058]  ? __sys_connect+0x10e/0x1a0
[   77.489963][ T8058]  ? __do_sys_rseq+0x750/0x750
[   77.490362][ T8058]  ? folio_memcg_unlock+0x240/0x240
[   77.490756][ T8058]  __x64_sys_recvfrom+0xe0/0x1b0
[   77.491183][ T8058]  ? syscall_enter_from_user_mode+0x7f/0x120
[   77.491727][ T8058]  do_syscall_64+0x40/0x110
[   77.492118][ T8058]  entry_SYSCALL_64_after_hwframe+0x63/0x6b
[   77.492591][ T8058] RIP: 0033:0x7fdd574dad9d
[   77.492938][ T8058] Code: 28 c3 e8 e6 22 00 00 66 0f 1f 44 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
[   77.494300][ T8058] RSP: 002b:00007fff993d59f8 EFLAGS: 00000246 ORIG_RAX: 000000000000002d
[   77.494971][ T8058] RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00007fdd574dad9d
[   77.495631][ T8058] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000003
[   77.496221][ T8058] RBP: 00007fdd57533380 R08: 0000000000000000 R09: 0000000000000000
[   77.496798][ T8058] R10: 0000000000000000 R11: 0000000000000246 R12: 00007fff993d5a40
[   77.497409][ T8058] R13: 00007fff993d5a60 R14: 00007fdd57567300 R15: 00007fdd57533366
[   77.498041][ T8058]  </TASK>
[   77.504343][ T8058] ================================================================================
[   77.505104][ T8058] Kernel panic - not syncing: UBSAN: panic_on_warn set ...
[   77.505643][ T8058] CPU: 1 PID: 8058 Comm: syz-executor228 Not tainted 6.6.0-gd2f51b3516da #1
[   77.506306][ T8058] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.15.0-1 04/01/2014
[   77.507003][ T8058] Call Trace:
[   77.507285][ T8058]  <TASK>
[   77.507510][ T8058]  dump_stack_lvl+0xd9/0x150
[   77.507896][ T8058]  panic+0x6b9/0x760
[   77.508213][ T8058]  ? panic_smp_self_stop+0xa0/0xa0
[   77.508633][ T8058]  ? kmsg_dump_get_line+0x330/0x330
[   77.509070][ T8058]  ? check_panic_on_warn+0x1f/0xc0
[   77.509501][ T8058]  check_panic_on_warn+0xb1/0xc0
[   77.509866][ T8058]  __ubsan_handle_out_of_bounds+0xfd/0x130
[   77.510342][ T8058]  ? kvm_sched_clock_read+0x16/0x20
[   77.510763][ T8058]  rds_cmsg_recv+0x60d/0x700
[   77.511150][ T8058]  ? rds_recvmsg_zcookie+0x490/0x490
[   77.511575][ T8058]  ? rds_recvmsg+0x695/0x1610
[   77.512017][ T8058]  ? lock_downgrade+0x6a0/0x6a0
[   77.512425][ T8058]  ? _raw_write_unlock_irqrestore+0x54/0x70
[   77.512914][ T8058]  rds_recvmsg+0x3fb/0x1610
[   77.513276][ T8058]  ? rds_notify_queue_get+0x760/0x760
[   77.513706][ T8058]  ? aa_af_perm+0x240/0x240
[   77.514081][ T8058]  ? prepare_to_swait_exclusive+0x240/0x240
[   77.514573][ T8058]  ? bpf_lsm_socket_recvmsg+0x9/0x10
[   77.515053][ T8058]  ? security_socket_recvmsg+0x93/0xc0
[   77.515518][ T8058]  ? rds_notify_queue_get+0x760/0x760
[   77.515977][ T8058]  sock_recvmsg+0xe2/0x160
[   77.516379][ T8058]  __sys_recvfrom+0x1b6/0x2f0
[   77.516775][ T8058]  ? __ia32_sys_send+0x100/0x100
[   77.517210][ T8058]  ? lock_downgrade+0x6a0/0x6a0
[   77.517641][ T8058]  ? __rseq_handle_notify_resume+0x5cf/0x1000
[   77.518178][ T8058]  ? __ia32_sys_socketpair+0x100/0x100
[   77.518655][ T8058]  ? __sys_connect+0x10e/0x1a0
[   77.519083][ T8058]  ? __do_sys_rseq+0x750/0x750
[   77.519497][ T8058]  ? folio_memcg_unlock+0x240/0x240
[   77.519908][ T8058]  __x64_sys_recvfrom+0xe0/0x1b0
[   77.520325][ T8058]  ? syscall_enter_from_user_mode+0x7f/0x120
[   77.520809][ T8058]  do_syscall_64+0x40/0x110
[   77.521178][ T8058]  entry_SYSCALL_64_after_hwframe+0x63/0x6b
[   77.521724][ T8058] RIP: 0033:0x7fdd574dad9d
[   77.522156][ T8058] Code: 28 c3 e8 e6 22 00 00 66 0f 1f 44 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
[   77.523535][ T8058] RSP: 002b:00007fff993d59f8 EFLAGS: 00000246 ORIG_RAX: 000000000000002d
[   77.524134][ T8058] RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00007fdd574dad9d
[   77.524683][ T8058] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000003
[   77.525239][ T8058] RBP: 00007fdd57533380 R08: 0000000000000000 R09: 0000000000000000
[   77.525799][ T8058] R10: 0000000000000000 R11: 0000000000000246 R12: 00007fff993d5a40
[   77.526362][ T8058] R13: 00007fff993d5a60 R14: 00007fdd57567300 R15: 00007fdd57533366
[   77.526984][ T8058]  </TASK>
[   77.527362][ T8058] Kernel Offset: disabled
[   77.527767][ T8058] Rebooting in 86400 seconds..

VM DIAGNOSIS:
19:50:56  Registers:
info registers vcpu 0
RAX=00000000000220e9 RBX=0000000000000000 RCX=ffffffff8a6223db RDX=0000000000000000
RSI=0000000000000001 RDI=0000000000000000 RBP=dffffc0000000000 RSP=ffffffff8ca07e08
R8 =0000000000000001 R9 =ffffed1005946dbd R10=ffff88802ca36deb R11=0000000000000000
R12=0000000000000000 R13=ffffffff8ef7d250 R14=0000000000000000 R15=0000000000000000
RIP=ffffffff8a623bfe RFL=00000202 [-------] CPL=0 II=0 A20=1 SMM=0 HLT=1
ES =0000 0000000000000000 00000000 00000000
CS =0010 0000000000000000 ffffffff 00a09b00 DPL=0 CS64 [-RA]
SS =0018 0000000000000000 ffffffff 00c09300 DPL=0 DS   [-WA]
DS =0000 0000000000000000 00000000 00000000
FS =0000 0000000000000000 00000000 00000000
GS =0000 ffff88802ca00000 00000000 00000000
LDT=0000 fffffe5900000000 00000000 00000000
TR =0040 fffffe0000003000 00004087 00008b00 DPL=0 TSS64-busy
GDT=     fffffe0000001000 0000007f
IDT=     fffffe0000000000 00000fff
CR0=80050033 CR2=00007f906224d648 CR3=0000000017398000 CR4=00350ef0
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
EFER=0000000000000d01
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
YMM00=0000000000000000 0000000000000000 512e60cee616e48b a7a17fa2a98833e0
YMM01=0000000000000000 0000000000000000 1bb8cee680be1f6e 7a6bb8571aee9717
YMM02=0000000000000000 0000000000000000 a6280bc585993577 c6e81887f0754763
YMM03=0000000000000000 0000000000000000 7eb7b8fd75791865 81a912d699d3c682
YMM04=0000000000000000 0000000000000000 0000000000000000 0000000000000000
YMM05=0000000000000000 0000000000000000 0000000000000000 0000000000000000
YMM06=0000000000000000 0000000000000000 0000000000000000 0000000000000000
YMM07=0000000000000000 0000000000000000 0000000000000000 0000000002eed311
YMM08=0000000000000000 0000000000000000 8a00000030000000 180000006c000000
YMM09=0000000000000000 0000000000000000 0000000000000000 0000000000000000
YMM10=0000000000000000 0000000000000000 a6964d585ee97e45 a80c335293b2e155
YMM11=0000000000000000 0000000000000000 ef65dbfbc5faeef7 e3da409fef92181f
YMM12=0000000000000000 0000000000000000 0d0c0f0e09080b0a 0504070601000302
YMM13=0000000000000000 0000000000000000 0c0f0e0d080b0a09 0407060500030201
YMM14=0000000000000000 0000000000000000 00000000ffffffff 0000000000000060
YMM15=0000000000000000 0000000000000000 0000000000000000 0000000000000020
info registers vcpu 1
RAX=dffffc0000000005 RBX=00000000000003f9 RCX=0000000000000000 RDX=00000000000003f9
RSI=ffffffff84c81d00 RDI=ffffffff9286ff60 RBP=ffffffff9286ff20 RSP=ffffc90003e67490
R8 =0000000000000001 R9 =000000000000001f R10=0000000000000000 R11=0000000000000000
R12=0000000000000000 R13=ffffffff9286ff20 R14=ffffffff928701e0 R15=ffffffff9286ff70
RIP=ffffffff84c81d27 RFL=00000006 [-----P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
ES =0000 0000000000000000 00000000 00000000
CS =0010 0000000000000000 ffffffff 00a09b00 DPL=0 CS64 [-RA]
SS =0018 0000000000000000 ffffffff 00c09300 DPL=0 DS   [-WA]
DS =0000 0000000000000000 00000000 00000000
FS =0000 0000555556eea3c0 00000000 00000000
GS =0000 ffff88807ec00000 00000000 00000000
LDT=0000 fffffe1d00000000 00000000 00000000
TR =0040 fffffe000004a000 00004087 00008b00 DPL=0 TSS64-busy
GDT=     fffffe0000048000 0000007f
IDT=     fffffe0000000000 00000fff
CR0=80050033 CR2=00000000200000c0 CR3=000000001d2f2000 CR4=00350ef0
DR0=0000000000000000 DR1=0000000000000000 DR2=0000000000000000 DR3=0000000000000000 
DR6=00000000ffff0ff0 DR7=0000000000000400
EFER=0000000000000d01
FCW=037f FSW=0000 [ST=0] FTW=00 MXCSR=00001f80
FPR0=0000000000000000 0000 FPR1=0000000000000000 0000
FPR2=0000000000000000 0000 FPR3=0000000000000000 0000
FPR4=0000000000000000 0000 FPR5=0000000000000000 0000
FPR6=0000000000000000 0000 FPR7=0000000000000000 0000
YMM00=0000000000000000 0000000000000000 249dd689f4b472fe d82d68dcbe16388a
YMM01=0000000000000000 0000000000000000 43b409cde8b7e134 26c925d3087d519f
YMM02=0000000000000000 0000000000000000 a47a2bb03ce18847 f002136ae62620c4
YMM03=0000000000000000 0000000000000000 4d00908ea79f2da6 073fdb521fd6c940
YMM04=0000000000000000 0000000000000000 0000000000000000 00000000ed27fd12
YMM05=0000000000000000 0000000000000000 0000000000000000 612d1be5cf3ea66a
YMM06=0000000000000000 0000000000000000 0000000000000000 00000000612d1be5
YMM07=0000000000000000 0000000000000000 612d1be5cf3ea66a ed27fd1217933eae
YMM08=0000000000000000 0000000000000000 5400000050000000 ba00000046000000
YMM09=0000000000000000 0000000000000000 0000000000000000 0000000000000000
YMM10=0000000000000000 0000000000000000 a54ff53a3c6ef372 bb67ae856b08e647
YMM11=0000000000000000 0000000000000000 5be0cd191f83d9ab 9b05688c510e527f
YMM12=0000000000000000 0000000000000000 0d0c0f0e09080b0a 0504070601000302
YMM13=0000000000000000 0000000000000000 0c0f0e0d080b0a09 0407060500030201
YMM14=0000000000000000 0000000000000000 00000000ffffffff 000000000000003c
YMM15=0000000000000000 0000000000000000 0000000000000000 000000000000003c

[-- Attachment #5: repro.cprog --]
[-- Type: application/octet-stream, Size: 34342 bytes --]

// autogenerated by syzkaller (https://github.com/google/syzkaller)

#define _GNU_SOURCE 

#include <arpa/inet.h>
#include <endian.h>
#include <errno.h>
#include <fcntl.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <netinet/in.h>
#include <sched.h>
#include <stdarg.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/prctl.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <unistd.h>

#include <linux/capability.h>
#include <linux/genetlink.h>
#include <linux/if_addr.h>
#include <linux/if_ether.h>
#include <linux/if_link.h>
#include <linux/if_tun.h>
#include <linux/in6.h>
#include <linux/ip.h>
#include <linux/neighbour.h>
#include <linux/net.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
#include <linux/tcp.h>
#include <linux/veth.h>

static unsigned long long procid;

static bool write_file(const char* file, const char* what, ...)
{
	char buf[1024];
	va_list args;
	va_start(args, what);
	vsnprintf(buf, sizeof(buf), what, args);
	va_end(args);
	buf[sizeof(buf) - 1] = 0;
	int len = strlen(buf);
	int fd = open(file, O_WRONLY | O_CLOEXEC);
	if (fd == -1)
		return false;
	if (write(fd, buf, len) != len) {
		int err = errno;
		close(fd);
		errno = err;
		return false;
	}
	close(fd);
	return true;
}

struct nlmsg {
	char* pos;
	int nesting;
	struct nlattr* nested[8];
	char buf[4096];
};

static void netlink_init(struct nlmsg* nlmsg, int typ, int flags,
			 const void* data, int size)
{
	memset(nlmsg, 0, sizeof(*nlmsg));
	struct nlmsghdr* hdr = (struct nlmsghdr*)nlmsg->buf;
	hdr->nlmsg_type = typ;
	hdr->nlmsg_flags = NLM_F_REQUEST | NLM_F_ACK | flags;
	memcpy(hdr + 1, data, size);
	nlmsg->pos = (char*)(hdr + 1) + NLMSG_ALIGN(size);
}

static void netlink_attr(struct nlmsg* nlmsg, int typ,
			 const void* data, int size)
{
	struct nlattr* attr = (struct nlattr*)nlmsg->pos;
	attr->nla_len = sizeof(*attr) + size;
	attr->nla_type = typ;
	if (size > 0)
		memcpy(attr + 1, data, size);
	nlmsg->pos += NLMSG_ALIGN(attr->nla_len);
}

static void netlink_nest(struct nlmsg* nlmsg, int typ)
{
	struct nlattr* attr = (struct nlattr*)nlmsg->pos;
	attr->nla_type = typ;
	nlmsg->pos += sizeof(*attr);
	nlmsg->nested[nlmsg->nesting++] = attr;
}

static void netlink_done(struct nlmsg* nlmsg)
{
	struct nlattr* attr = nlmsg->nested[--nlmsg->nesting];
	attr->nla_len = nlmsg->pos - (char*)attr;
}

static int netlink_send_ext(struct nlmsg* nlmsg, int sock,
			    uint16_t reply_type, int* reply_len, bool dofail)
{
	if (nlmsg->pos > nlmsg->buf + sizeof(nlmsg->buf) || nlmsg->nesting)
	exit(1);
	struct nlmsghdr* hdr = (struct nlmsghdr*)nlmsg->buf;
	hdr->nlmsg_len = nlmsg->pos - nlmsg->buf;
	struct sockaddr_nl addr;
	memset(&addr, 0, sizeof(addr));
	addr.nl_family = AF_NETLINK;
	ssize_t n = sendto(sock, nlmsg->buf, hdr->nlmsg_len, 0, (struct sockaddr*)&addr, sizeof(addr));
	if (n != (ssize_t)hdr->nlmsg_len) {
		if (dofail)
	exit(1);
		return -1;
	}
	n = recv(sock, nlmsg->buf, sizeof(nlmsg->buf), 0);
	if (reply_len)
		*reply_len = 0;
	if (n < 0) {
		if (dofail)
	exit(1);
		return -1;
	}
	if (n < (ssize_t)sizeof(struct nlmsghdr)) {
		errno = EINVAL;
		if (dofail)
	exit(1);
		return -1;
	}
	if (hdr->nlmsg_type == NLMSG_DONE)
		return 0;
	if (reply_len && hdr->nlmsg_type == reply_type) {
		*reply_len = n;
		return 0;
	}
	if (n < (ssize_t)(sizeof(struct nlmsghdr) + sizeof(struct nlmsgerr))) {
		errno = EINVAL;
		if (dofail)
	exit(1);
		return -1;
	}
	if (hdr->nlmsg_type != NLMSG_ERROR) {
		errno = EINVAL;
		if (dofail)
	exit(1);
		return -1;
	}
	errno = -((struct nlmsgerr*)(hdr + 1))->error;
	return -errno;
}

static int netlink_send(struct nlmsg* nlmsg, int sock)
{
	return netlink_send_ext(nlmsg, sock, 0, NULL, true);
}

static int netlink_query_family_id(struct nlmsg* nlmsg, int sock, const char* family_name, bool dofail)
{
	struct genlmsghdr genlhdr;
	memset(&genlhdr, 0, sizeof(genlhdr));
	genlhdr.cmd = CTRL_CMD_GETFAMILY;
	netlink_init(nlmsg, GENL_ID_CTRL, 0, &genlhdr, sizeof(genlhdr));
	netlink_attr(nlmsg, CTRL_ATTR_FAMILY_NAME, family_name, strnlen(family_name, GENL_NAMSIZ - 1) + 1);
	int n = 0;
	int err = netlink_send_ext(nlmsg, sock, GENL_ID_CTRL, &n, dofail);
	if (err < 0) {
		return -1;
	}
	uint16_t id = 0;
	struct nlattr* attr = (struct nlattr*)(nlmsg->buf + NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(genlhdr)));
	for (; (char*)attr < nlmsg->buf + n; attr = (struct nlattr*)((char*)attr + NLMSG_ALIGN(attr->nla_len))) {
		if (attr->nla_type == CTRL_ATTR_FAMILY_ID) {
			id = *(uint16_t*)(attr + 1);
			break;
		}
	}
	if (!id) {
		errno = EINVAL;
		return -1;
	}
	recv(sock, nlmsg->buf, sizeof(nlmsg->buf), 0);
	return id;
}

static int netlink_next_msg(struct nlmsg* nlmsg, unsigned int offset,
			    unsigned int total_len)
{
	struct nlmsghdr* hdr = (struct nlmsghdr*)(nlmsg->buf + offset);
	if (offset == total_len || offset + hdr->nlmsg_len > total_len)
		return -1;
	return hdr->nlmsg_len;
}

static void netlink_add_device_impl(struct nlmsg* nlmsg, const char* type,
				    const char* name, bool up)
{
	struct ifinfomsg hdr;
	memset(&hdr, 0, sizeof(hdr));
	if (up)
		hdr.ifi_flags = hdr.ifi_change = IFF_UP;
	netlink_init(nlmsg, RTM_NEWLINK, NLM_F_EXCL | NLM_F_CREATE, &hdr, sizeof(hdr));
	if (name)
		netlink_attr(nlmsg, IFLA_IFNAME, name, strlen(name));
	netlink_nest(nlmsg, IFLA_LINKINFO);
	netlink_attr(nlmsg, IFLA_INFO_KIND, type, strlen(type));
}

static void netlink_add_device(struct nlmsg* nlmsg, int sock, const char* type,
			       const char* name)
{
	netlink_add_device_impl(nlmsg, type, name, false);
	netlink_done(nlmsg);
	int err = netlink_send(nlmsg, sock);
	if (err < 0) {
	}
}

static void netlink_add_veth(struct nlmsg* nlmsg, int sock, const char* name,
			     const char* peer)
{
	netlink_add_device_impl(nlmsg, "veth", name, false);
	netlink_nest(nlmsg, IFLA_INFO_DATA);
	netlink_nest(nlmsg, VETH_INFO_PEER);
	nlmsg->pos += sizeof(struct ifinfomsg);
	netlink_attr(nlmsg, IFLA_IFNAME, peer, strlen(peer));
	netlink_done(nlmsg);
	netlink_done(nlmsg);
	netlink_done(nlmsg);
	int err = netlink_send(nlmsg, sock);
	if (err < 0) {
	}
}

static void netlink_add_xfrm(struct nlmsg* nlmsg, int sock, const char* name)
{
	netlink_add_device_impl(nlmsg, "xfrm", name, true);
	netlink_nest(nlmsg, IFLA_INFO_DATA);
	int if_id = 1;
	netlink_attr(nlmsg, 2, &if_id, sizeof(if_id));
	netlink_done(nlmsg);
	netlink_done(nlmsg);
	int err = netlink_send(nlmsg, sock);
	if (err < 0) {
	}
}

static void netlink_add_hsr(struct nlmsg* nlmsg, int sock, const char* name,
			    const char* slave1, const char* slave2)
{
	netlink_add_device_impl(nlmsg, "hsr", name, false);
	netlink_nest(nlmsg, IFLA_INFO_DATA);
	int ifindex1 = if_nametoindex(slave1);
	netlink_attr(nlmsg, IFLA_HSR_SLAVE1, &ifindex1, sizeof(ifindex1));
	int ifindex2 = if_nametoindex(slave2);
	netlink_attr(nlmsg, IFLA_HSR_SLAVE2, &ifindex2, sizeof(ifindex2));
	netlink_done(nlmsg);
	netlink_done(nlmsg);
	int err = netlink_send(nlmsg, sock);
	if (err < 0) {
	}
}

static void netlink_add_linked(struct nlmsg* nlmsg, int sock, const char* type, const char* name, const char* link)
{
	netlink_add_device_impl(nlmsg, type, name, false);
	netlink_done(nlmsg);
	int ifindex = if_nametoindex(link);
	netlink_attr(nlmsg, IFLA_LINK, &ifindex, sizeof(ifindex));
	int err = netlink_send(nlmsg, sock);
	if (err < 0) {
	}
}

static void netlink_add_vlan(struct nlmsg* nlmsg, int sock, const char* name, const char* link, uint16_t id, uint16_t proto)
{
	netlink_add_device_impl(nlmsg, "vlan", name, false);
	netlink_nest(nlmsg, IFLA_INFO_DATA);
	netlink_attr(nlmsg, IFLA_VLAN_ID, &id, sizeof(id));
	netlink_attr(nlmsg, IFLA_VLAN_PROTOCOL, &proto, sizeof(proto));
	netlink_done(nlmsg);
	netlink_done(nlmsg);
	int ifindex = if_nametoindex(link);
	netlink_attr(nlmsg, IFLA_LINK, &ifindex, sizeof(ifindex));
	int err = netlink_send(nlmsg, sock);
	if (err < 0) {
	}
}

static void netlink_add_macvlan(struct nlmsg* nlmsg, int sock, const char* name, const char* link)
{
	netlink_add_device_impl(nlmsg, "macvlan", name, false);
	netlink_nest(nlmsg, IFLA_INFO_DATA);
	uint32_t mode = MACVLAN_MODE_BRIDGE;
	netlink_attr(nlmsg, IFLA_MACVLAN_MODE, &mode, sizeof(mode));
	netlink_done(nlmsg);
	netlink_done(nlmsg);
	int ifindex = if_nametoindex(link);
	netlink_attr(nlmsg, IFLA_LINK, &ifindex, sizeof(ifindex));
	int err = netlink_send(nlmsg, sock);
	if (err < 0) {
	}
}

static void netlink_add_geneve(struct nlmsg* nlmsg, int sock, const char* name, uint32_t vni, struct in_addr* addr4, struct in6_addr* addr6)
{
	netlink_add_device_impl(nlmsg, "geneve", name, false);
	netlink_nest(nlmsg, IFLA_INFO_DATA);
	netlink_attr(nlmsg, IFLA_GENEVE_ID, &vni, sizeof(vni));
	if (addr4)
		netlink_attr(nlmsg, IFLA_GENEVE_REMOTE, addr4, sizeof(*addr4));
	if (addr6)
		netlink_attr(nlmsg, IFLA_GENEVE_REMOTE6, addr6, sizeof(*addr6));
	netlink_done(nlmsg);
	netlink_done(nlmsg);
	int err = netlink_send(nlmsg, sock);
	if (err < 0) {
	}
}

#define IFLA_IPVLAN_FLAGS 2
#define IPVLAN_MODE_L3S 2
#undef IPVLAN_F_VEPA
#define IPVLAN_F_VEPA 2

static void netlink_add_ipvlan(struct nlmsg* nlmsg, int sock, const char* name, const char* link, uint16_t mode, uint16_t flags)
{
	netlink_add_device_impl(nlmsg, "ipvlan", name, false);
	netlink_nest(nlmsg, IFLA_INFO_DATA);
	netlink_attr(nlmsg, IFLA_IPVLAN_MODE, &mode, sizeof(mode));
	netlink_attr(nlmsg, IFLA_IPVLAN_FLAGS, &flags, sizeof(flags));
	netlink_done(nlmsg);
	netlink_done(nlmsg);
	int ifindex = if_nametoindex(link);
	netlink_attr(nlmsg, IFLA_LINK, &ifindex, sizeof(ifindex));
	int err = netlink_send(nlmsg, sock);
	if (err < 0) {
	}
}

static void netlink_device_change(struct nlmsg* nlmsg, int sock, const char* name, bool up,
				  const char* master, const void* mac, int macsize,
				  const char* new_name)
{
	struct ifinfomsg hdr;
	memset(&hdr, 0, sizeof(hdr));
	if (up)
		hdr.ifi_flags = hdr.ifi_change = IFF_UP;
	hdr.ifi_index = if_nametoindex(name);
	netlink_init(nlmsg, RTM_NEWLINK, 0, &hdr, sizeof(hdr));
	if (new_name)
		netlink_attr(nlmsg, IFLA_IFNAME, new_name, strlen(new_name));
	if (master) {
		int ifindex = if_nametoindex(master);
		netlink_attr(nlmsg, IFLA_MASTER, &ifindex, sizeof(ifindex));
	}
	if (macsize)
		netlink_attr(nlmsg, IFLA_ADDRESS, mac, macsize);
	int err = netlink_send(nlmsg, sock);
	if (err < 0) {
	}
}

static int netlink_add_addr(struct nlmsg* nlmsg, int sock, const char* dev,
			    const void* addr, int addrsize)
{
	struct ifaddrmsg hdr;
	memset(&hdr, 0, sizeof(hdr));
	hdr.ifa_family = addrsize == 4 ? AF_INET : AF_INET6;
	hdr.ifa_prefixlen = addrsize == 4 ? 24 : 120;
	hdr.ifa_scope = RT_SCOPE_UNIVERSE;
	hdr.ifa_index = if_nametoindex(dev);
	netlink_init(nlmsg, RTM_NEWADDR, NLM_F_CREATE | NLM_F_REPLACE, &hdr, sizeof(hdr));
	netlink_attr(nlmsg, IFA_LOCAL, addr, addrsize);
	netlink_attr(nlmsg, IFA_ADDRESS, addr, addrsize);
	return netlink_send(nlmsg, sock);
}

static void netlink_add_addr4(struct nlmsg* nlmsg, int sock,
			      const char* dev, const char* addr)
{
	struct in_addr in_addr;
	inet_pton(AF_INET, addr, &in_addr);
	int err = netlink_add_addr(nlmsg, sock, dev, &in_addr, sizeof(in_addr));
	if (err < 0) {
	}
}

static void netlink_add_addr6(struct nlmsg* nlmsg, int sock,
			      const char* dev, const char* addr)
{
	struct in6_addr in6_addr;
	inet_pton(AF_INET6, addr, &in6_addr);
	int err = netlink_add_addr(nlmsg, sock, dev, &in6_addr, sizeof(in6_addr));
	if (err < 0) {
	}
}

static struct nlmsg nlmsg;

#define DEVLINK_FAMILY_NAME "devlink"

#define DEVLINK_CMD_PORT_GET 5
#define DEVLINK_ATTR_BUS_NAME 1
#define DEVLINK_ATTR_DEV_NAME 2
#define DEVLINK_ATTR_NETDEV_NAME 7

static struct nlmsg nlmsg2;

static void initialize_devlink_ports(const char* bus_name, const char* dev_name,
				     const char* netdev_prefix)
{
	struct genlmsghdr genlhdr;
	int len, total_len, id, err, offset;
	uint16_t netdev_index;
	int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
	if (sock == -1)
	exit(1);
	int rtsock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
	if (rtsock == -1)
	exit(1);
	id = netlink_query_family_id(&nlmsg, sock, DEVLINK_FAMILY_NAME, true);
	if (id == -1)
		goto error;
	memset(&genlhdr, 0, sizeof(genlhdr));
	genlhdr.cmd = DEVLINK_CMD_PORT_GET;
	netlink_init(&nlmsg, id, NLM_F_DUMP, &genlhdr, sizeof(genlhdr));
	netlink_attr(&nlmsg, DEVLINK_ATTR_BUS_NAME, bus_name, strlen(bus_name) + 1);
	netlink_attr(&nlmsg, DEVLINK_ATTR_DEV_NAME, dev_name, strlen(dev_name) + 1);
	err = netlink_send_ext(&nlmsg, sock, id, &total_len, true);
	if (err < 0) {
		goto error;
	}
	offset = 0;
	netdev_index = 0;
	while ((len = netlink_next_msg(&nlmsg, offset, total_len)) != -1) {
		struct nlattr* attr = (struct nlattr*)(nlmsg.buf + offset + NLMSG_HDRLEN + NLMSG_ALIGN(sizeof(genlhdr)));
		for (; (char*)attr < nlmsg.buf + offset + len; attr = (struct nlattr*)((char*)attr + NLMSG_ALIGN(attr->nla_len))) {
			if (attr->nla_type == DEVLINK_ATTR_NETDEV_NAME) {
				char* port_name;
				char netdev_name[IFNAMSIZ];
				port_name = (char*)(attr + 1);
				snprintf(netdev_name, sizeof(netdev_name), "%s%d", netdev_prefix, netdev_index);
				netlink_device_change(&nlmsg2, rtsock, port_name, true, 0, 0, 0, netdev_name);
				break;
			}
		}
		offset += len;
		netdev_index++;
	}
error:
	close(rtsock);
	close(sock);
}

#define DEV_IPV4 "172.20.20.%d"
#define DEV_IPV6 "fe80::%02x"
#define DEV_MAC 0x00aaaaaaaaaa

static void netdevsim_add(unsigned int addr, unsigned int port_count)
{
	write_file("/sys/bus/netdevsim/del_device", "%u", addr);
	if (write_file("/sys/bus/netdevsim/new_device", "%u %u", addr, port_count)) {
		char buf[32];
		snprintf(buf, sizeof(buf), "netdevsim%d", addr);
		initialize_devlink_ports("netdevsim", buf, "netdevsim");
	}
}

#define WG_GENL_NAME "wireguard"
enum wg_cmd {
	WG_CMD_GET_DEVICE,
	WG_CMD_SET_DEVICE,
};
enum wgdevice_attribute {
	WGDEVICE_A_UNSPEC,
	WGDEVICE_A_IFINDEX,
	WGDEVICE_A_IFNAME,
	WGDEVICE_A_PRIVATE_KEY,
	WGDEVICE_A_PUBLIC_KEY,
	WGDEVICE_A_FLAGS,
	WGDEVICE_A_LISTEN_PORT,
	WGDEVICE_A_FWMARK,
	WGDEVICE_A_PEERS,
};
enum wgpeer_attribute {
	WGPEER_A_UNSPEC,
	WGPEER_A_PUBLIC_KEY,
	WGPEER_A_PRESHARED_KEY,
	WGPEER_A_FLAGS,
	WGPEER_A_ENDPOINT,
	WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL,
	WGPEER_A_LAST_HANDSHAKE_TIME,
	WGPEER_A_RX_BYTES,
	WGPEER_A_TX_BYTES,
	WGPEER_A_ALLOWEDIPS,
	WGPEER_A_PROTOCOL_VERSION,
};
enum wgallowedip_attribute {
	WGALLOWEDIP_A_UNSPEC,
	WGALLOWEDIP_A_FAMILY,
	WGALLOWEDIP_A_IPADDR,
	WGALLOWEDIP_A_CIDR_MASK,
};

static void netlink_wireguard_setup(void)
{
	const char ifname_a[] = "wg0";
	const char ifname_b[] = "wg1";
	const char ifname_c[] = "wg2";
	const char private_a[] = "\xa0\x5c\xa8\x4f\x6c\x9c\x8e\x38\x53\xe2\xfd\x7a\x70\xae\x0f\xb2\x0f\xa1\x52\x60\x0c\xb0\x08\x45\x17\x4f\x08\x07\x6f\x8d\x78\x43";
	const char private_b[] = "\xb0\x80\x73\xe8\xd4\x4e\x91\xe3\xda\x92\x2c\x22\x43\x82\x44\xbb\x88\x5c\x69\xe2\x69\xc8\xe9\xd8\x35\xb1\x14\x29\x3a\x4d\xdc\x6e";
	const char private_c[] = "\xa0\xcb\x87\x9a\x47\xf5\xbc\x64\x4c\x0e\x69\x3f\xa6\xd0\x31\xc7\x4a\x15\x53\xb6\xe9\x01\xb9\xff\x2f\x51\x8c\x78\x04\x2f\xb5\x42";
	const char public_a[] = "\x97\x5c\x9d\x81\xc9\x83\xc8\x20\x9e\xe7\x81\x25\x4b\x89\x9f\x8e\xd9\x25\xae\x9f\x09\x23\xc2\x3c\x62\xf5\x3c\x57\xcd\xbf\x69\x1c";
	const char public_b[] = "\xd1\x73\x28\x99\xf6\x11\xcd\x89\x94\x03\x4d\x7f\x41\x3d\xc9\x57\x63\x0e\x54\x93\xc2\x85\xac\xa4\x00\x65\xcb\x63\x11\xbe\x69\x6b";
	const char public_c[] = "\xf4\x4d\xa3\x67\xa8\x8e\xe6\x56\x4f\x02\x02\x11\x45\x67\x27\x08\x2f\x5c\xeb\xee\x8b\x1b\xf5\xeb\x73\x37\x34\x1b\x45\x9b\x39\x22";
	const uint16_t listen_a = 20001;
	const uint16_t listen_b = 20002;
	const uint16_t listen_c = 20003;
	const uint16_t af_inet = AF_INET;
	const uint16_t af_inet6 = AF_INET6;
	const struct sockaddr_in endpoint_b_v4 = {
	    .sin_family = AF_INET,
	    .sin_port = htons(listen_b),
	    .sin_addr = {htonl(INADDR_LOOPBACK)}};
	const struct sockaddr_in endpoint_c_v4 = {
	    .sin_family = AF_INET,
	    .sin_port = htons(listen_c),
	    .sin_addr = {htonl(INADDR_LOOPBACK)}};
	struct sockaddr_in6 endpoint_a_v6 = {
	    .sin6_family = AF_INET6,
	    .sin6_port = htons(listen_a)};
	endpoint_a_v6.sin6_addr = in6addr_loopback;
	struct sockaddr_in6 endpoint_c_v6 = {
	    .sin6_family = AF_INET6,
	    .sin6_port = htons(listen_c)};
	endpoint_c_v6.sin6_addr = in6addr_loopback;
	const struct in_addr first_half_v4 = {0};
	const struct in_addr second_half_v4 = {(uint32_t)htonl(128 << 24)};
	const struct in6_addr first_half_v6 = {{{0}}};
	const struct in6_addr second_half_v6 = {{{0x80}}};
	const uint8_t half_cidr = 1;
	const uint16_t persistent_keepalives[] = {1, 3, 7, 9, 14, 19};
	struct genlmsghdr genlhdr = {
	    .cmd = WG_CMD_SET_DEVICE,
	    .version = 1};
	int sock;
	int id, err;
	sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_GENERIC);
	if (sock == -1) {
		return;
	}
	id = netlink_query_family_id(&nlmsg, sock, WG_GENL_NAME, true);
	if (id == -1)
		goto error;
	netlink_init(&nlmsg, id, 0, &genlhdr, sizeof(genlhdr));
	netlink_attr(&nlmsg, WGDEVICE_A_IFNAME, ifname_a, strlen(ifname_a) + 1);
	netlink_attr(&nlmsg, WGDEVICE_A_PRIVATE_KEY, private_a, 32);
	netlink_attr(&nlmsg, WGDEVICE_A_LISTEN_PORT, &listen_a, 2);
	netlink_nest(&nlmsg, NLA_F_NESTED | WGDEVICE_A_PEERS);
	netlink_nest(&nlmsg, NLA_F_NESTED | 0);
	netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_b, 32);
	netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_b_v4, sizeof(endpoint_b_v4));
	netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, &persistent_keepalives[0], 2);
	netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS);
	netlink_nest(&nlmsg, NLA_F_NESTED | 0);
	netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2);
	netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v4, sizeof(first_half_v4));
	netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
	netlink_done(&nlmsg);
	netlink_nest(&nlmsg, NLA_F_NESTED | 0);
	netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2);
	netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v6, sizeof(first_half_v6));
	netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
	netlink_done(&nlmsg);
	netlink_done(&nlmsg);
	netlink_done(&nlmsg);
	netlink_nest(&nlmsg, NLA_F_NESTED | 0);
	netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_c, 32);
	netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_c_v6, sizeof(endpoint_c_v6));
	netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, &persistent_keepalives[1], 2);
	netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS);
	netlink_nest(&nlmsg, NLA_F_NESTED | 0);
	netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2);
	netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v4, sizeof(second_half_v4));
	netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
	netlink_done(&nlmsg);
	netlink_nest(&nlmsg, NLA_F_NESTED | 0);
	netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2);
	netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v6, sizeof(second_half_v6));
	netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
	netlink_done(&nlmsg);
	netlink_done(&nlmsg);
	netlink_done(&nlmsg);
	netlink_done(&nlmsg);
	err = netlink_send(&nlmsg, sock);
	if (err < 0) {
	}
	netlink_init(&nlmsg, id, 0, &genlhdr, sizeof(genlhdr));
	netlink_attr(&nlmsg, WGDEVICE_A_IFNAME, ifname_b, strlen(ifname_b) + 1);
	netlink_attr(&nlmsg, WGDEVICE_A_PRIVATE_KEY, private_b, 32);
	netlink_attr(&nlmsg, WGDEVICE_A_LISTEN_PORT, &listen_b, 2);
	netlink_nest(&nlmsg, NLA_F_NESTED | WGDEVICE_A_PEERS);
	netlink_nest(&nlmsg, NLA_F_NESTED | 0);
	netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_a, 32);
	netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_a_v6, sizeof(endpoint_a_v6));
	netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, &persistent_keepalives[2], 2);
	netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS);
	netlink_nest(&nlmsg, NLA_F_NESTED | 0);
	netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2);
	netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v4, sizeof(first_half_v4));
	netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
	netlink_done(&nlmsg);
	netlink_nest(&nlmsg, NLA_F_NESTED | 0);
	netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2);
	netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v6, sizeof(first_half_v6));
	netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
	netlink_done(&nlmsg);
	netlink_done(&nlmsg);
	netlink_done(&nlmsg);
	netlink_nest(&nlmsg, NLA_F_NESTED | 0);
	netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_c, 32);
	netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_c_v4, sizeof(endpoint_c_v4));
	netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, &persistent_keepalives[3], 2);
	netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS);
	netlink_nest(&nlmsg, NLA_F_NESTED | 0);
	netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2);
	netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v4, sizeof(second_half_v4));
	netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
	netlink_done(&nlmsg);
	netlink_nest(&nlmsg, NLA_F_NESTED | 0);
	netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2);
	netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v6, sizeof(second_half_v6));
	netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
	netlink_done(&nlmsg);
	netlink_done(&nlmsg);
	netlink_done(&nlmsg);
	netlink_done(&nlmsg);
	err = netlink_send(&nlmsg, sock);
	if (err < 0) {
	}
	netlink_init(&nlmsg, id, 0, &genlhdr, sizeof(genlhdr));
	netlink_attr(&nlmsg, WGDEVICE_A_IFNAME, ifname_c, strlen(ifname_c) + 1);
	netlink_attr(&nlmsg, WGDEVICE_A_PRIVATE_KEY, private_c, 32);
	netlink_attr(&nlmsg, WGDEVICE_A_LISTEN_PORT, &listen_c, 2);
	netlink_nest(&nlmsg, NLA_F_NESTED | WGDEVICE_A_PEERS);
	netlink_nest(&nlmsg, NLA_F_NESTED | 0);
	netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_a, 32);
	netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_a_v6, sizeof(endpoint_a_v6));
	netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, &persistent_keepalives[4], 2);
	netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS);
	netlink_nest(&nlmsg, NLA_F_NESTED | 0);
	netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2);
	netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v4, sizeof(first_half_v4));
	netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
	netlink_done(&nlmsg);
	netlink_nest(&nlmsg, NLA_F_NESTED | 0);
	netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2);
	netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &first_half_v6, sizeof(first_half_v6));
	netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
	netlink_done(&nlmsg);
	netlink_done(&nlmsg);
	netlink_done(&nlmsg);
	netlink_nest(&nlmsg, NLA_F_NESTED | 0);
	netlink_attr(&nlmsg, WGPEER_A_PUBLIC_KEY, public_b, 32);
	netlink_attr(&nlmsg, WGPEER_A_ENDPOINT, &endpoint_b_v4, sizeof(endpoint_b_v4));
	netlink_attr(&nlmsg, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL, &persistent_keepalives[5], 2);
	netlink_nest(&nlmsg, NLA_F_NESTED | WGPEER_A_ALLOWEDIPS);
	netlink_nest(&nlmsg, NLA_F_NESTED | 0);
	netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet, 2);
	netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v4, sizeof(second_half_v4));
	netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
	netlink_done(&nlmsg);
	netlink_nest(&nlmsg, NLA_F_NESTED | 0);
	netlink_attr(&nlmsg, WGALLOWEDIP_A_FAMILY, &af_inet6, 2);
	netlink_attr(&nlmsg, WGALLOWEDIP_A_IPADDR, &second_half_v6, sizeof(second_half_v6));
	netlink_attr(&nlmsg, WGALLOWEDIP_A_CIDR_MASK, &half_cidr, 1);
	netlink_done(&nlmsg);
	netlink_done(&nlmsg);
	netlink_done(&nlmsg);
	netlink_done(&nlmsg);
	err = netlink_send(&nlmsg, sock);
	if (err < 0) {
	}

error:
	close(sock);
}

static void initialize_netdevices(void)
{
	char netdevsim[16];
	sprintf(netdevsim, "netdevsim%d", (int)procid);
	struct {
		const char* type;
		const char* dev;
	} devtypes[] = {
		{"ip6gretap", "ip6gretap0"},
		{"bridge", "bridge0"},
		{"vcan", "vcan0"},
		{"bond", "bond0"},
		{"team", "team0"},
		{"dummy", "dummy0"},
		{"nlmon", "nlmon0"},
		{"caif", "caif0"},
		{"batadv", "batadv0"},
		{"vxcan", "vxcan1"},
		{"veth", 0},
		{"wireguard", "wg0"},
		{"wireguard", "wg1"},
		{"wireguard", "wg2"},
	};
	const char* devmasters[] = {"bridge", "bond", "team", "batadv"};
	struct {
		const char* name;
		int macsize;
		bool noipv6;
	} devices[] = {
		{"lo", ETH_ALEN},
		{"sit0", 0},
		{"bridge0", ETH_ALEN},
		{"vcan0", 0, true},
		{"tunl0", 0},
		{"gre0", 0},
		{"gretap0", ETH_ALEN},
		{"ip_vti0", 0},
		{"ip6_vti0", 0},
		{"ip6tnl0", 0},
		{"ip6gre0", 0},
		{"ip6gretap0", ETH_ALEN},
		{"erspan0", ETH_ALEN},
		{"bond0", ETH_ALEN},
		{"veth0", ETH_ALEN},
		{"veth1", ETH_ALEN},
		{"team0", ETH_ALEN},
		{"veth0_to_bridge", ETH_ALEN},
		{"veth1_to_bridge", ETH_ALEN},
		{"veth0_to_bond", ETH_ALEN},
		{"veth1_to_bond", ETH_ALEN},
		{"veth0_to_team", ETH_ALEN},
		{"veth1_to_team", ETH_ALEN},
		{"veth0_to_hsr", ETH_ALEN},
		{"veth1_to_hsr", ETH_ALEN},
		{"hsr0", 0},
		{"dummy0", ETH_ALEN},
		{"nlmon0", 0},
		{"vxcan0", 0, true},
		{"vxcan1", 0, true},
		{"caif0", ETH_ALEN},
		{"batadv0", ETH_ALEN},
		{netdevsim, ETH_ALEN},
		{"xfrm0", ETH_ALEN},
		{"veth0_virt_wifi", ETH_ALEN},
		{"veth1_virt_wifi", ETH_ALEN},
		{"virt_wifi0", ETH_ALEN},
		{"veth0_vlan", ETH_ALEN},
		{"veth1_vlan", ETH_ALEN},
		{"vlan0", ETH_ALEN},
		{"vlan1", ETH_ALEN},
		{"macvlan0", ETH_ALEN},
		{"macvlan1", ETH_ALEN},
		{"ipvlan0", ETH_ALEN},
		{"ipvlan1", ETH_ALEN},
		{"veth0_macvtap", ETH_ALEN},
		{"veth1_macvtap", ETH_ALEN},
		{"macvtap0", ETH_ALEN},
		{"macsec0", ETH_ALEN},
		{"veth0_to_batadv", ETH_ALEN},
		{"veth1_to_batadv", ETH_ALEN},
		{"batadv_slave_0", ETH_ALEN},
		{"batadv_slave_1", ETH_ALEN},
		{"geneve0", ETH_ALEN},
		{"geneve1", ETH_ALEN},
		{"wg0", 0},
		{"wg1", 0},
		{"wg2", 0},
	};
	int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
	if (sock == -1)
	exit(1);
	unsigned i;
	for (i = 0; i < sizeof(devtypes) / sizeof(devtypes[0]); i++)
		netlink_add_device(&nlmsg, sock, devtypes[i].type, devtypes[i].dev);
	for (i = 0; i < sizeof(devmasters) / (sizeof(devmasters[0])); i++) {
		char master[32], slave0[32], veth0[32], slave1[32], veth1[32];
		sprintf(slave0, "%s_slave_0", devmasters[i]);
		sprintf(veth0, "veth0_to_%s", devmasters[i]);
		netlink_add_veth(&nlmsg, sock, slave0, veth0);
		sprintf(slave1, "%s_slave_1", devmasters[i]);
		sprintf(veth1, "veth1_to_%s", devmasters[i]);
		netlink_add_veth(&nlmsg, sock, slave1, veth1);
		sprintf(master, "%s0", devmasters[i]);
		netlink_device_change(&nlmsg, sock, slave0, false, master, 0, 0, NULL);
		netlink_device_change(&nlmsg, sock, slave1, false, master, 0, 0, NULL);
	}
	netlink_add_xfrm(&nlmsg, sock, "xfrm0");
	netlink_device_change(&nlmsg, sock, "bridge_slave_0", true, 0, 0, 0, NULL);
	netlink_device_change(&nlmsg, sock, "bridge_slave_1", true, 0, 0, 0, NULL);
	netlink_add_veth(&nlmsg, sock, "hsr_slave_0", "veth0_to_hsr");
	netlink_add_veth(&nlmsg, sock, "hsr_slave_1", "veth1_to_hsr");
	netlink_add_hsr(&nlmsg, sock, "hsr0", "hsr_slave_0", "hsr_slave_1");
	netlink_device_change(&nlmsg, sock, "hsr_slave_0", true, 0, 0, 0, NULL);
	netlink_device_change(&nlmsg, sock, "hsr_slave_1", true, 0, 0, 0, NULL);
	netlink_add_veth(&nlmsg, sock, "veth0_virt_wifi", "veth1_virt_wifi");
	netlink_add_linked(&nlmsg, sock, "virt_wifi", "virt_wifi0", "veth1_virt_wifi");
	netlink_add_veth(&nlmsg, sock, "veth0_vlan", "veth1_vlan");
	netlink_add_vlan(&nlmsg, sock, "vlan0", "veth0_vlan", 0, htons(ETH_P_8021Q));
	netlink_add_vlan(&nlmsg, sock, "vlan1", "veth0_vlan", 1, htons(ETH_P_8021AD));
	netlink_add_macvlan(&nlmsg, sock, "macvlan0", "veth1_vlan");
	netlink_add_macvlan(&nlmsg, sock, "macvlan1", "veth1_vlan");
	netlink_add_ipvlan(&nlmsg, sock, "ipvlan0", "veth0_vlan", IPVLAN_MODE_L2, 0);
	netlink_add_ipvlan(&nlmsg, sock, "ipvlan1", "veth0_vlan", IPVLAN_MODE_L3S, IPVLAN_F_VEPA);
	netlink_add_veth(&nlmsg, sock, "veth0_macvtap", "veth1_macvtap");
	netlink_add_linked(&nlmsg, sock, "macvtap", "macvtap0", "veth0_macvtap");
	netlink_add_linked(&nlmsg, sock, "macsec", "macsec0", "veth1_macvtap");
	char addr[32];
	sprintf(addr, DEV_IPV4, 14 + 10);
	struct in_addr geneve_addr4;
	if (inet_pton(AF_INET, addr, &geneve_addr4) <= 0)
	exit(1);
	struct in6_addr geneve_addr6;
	if (inet_pton(AF_INET6, "fc00::01", &geneve_addr6) <= 0)
	exit(1);
	netlink_add_geneve(&nlmsg, sock, "geneve0", 0, &geneve_addr4, 0);
	netlink_add_geneve(&nlmsg, sock, "geneve1", 1, 0, &geneve_addr6);
	netdevsim_add((int)procid, 4);
	netlink_wireguard_setup();
	for (i = 0; i < sizeof(devices) / (sizeof(devices[0])); i++) {
		char addr[32];
		sprintf(addr, DEV_IPV4, i + 10);
		netlink_add_addr4(&nlmsg, sock, devices[i].name, addr);
		if (!devices[i].noipv6) {
			sprintf(addr, DEV_IPV6, i + 10);
			netlink_add_addr6(&nlmsg, sock, devices[i].name, addr);
		}
		uint64_t macaddr = DEV_MAC + ((i + 10ull) << 40);
		netlink_device_change(&nlmsg, sock, devices[i].name, true, 0, &macaddr, devices[i].macsize, NULL);
	}
	close(sock);
}
static void initialize_netdevices_init(void)
{
	int sock = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
	if (sock == -1)
	exit(1);
	struct {
		const char* type;
		int macsize;
		bool noipv6;
		bool noup;
	} devtypes[] = {
	    {"nr", 7, true},
	    {"rose", 5, true, true},
	};
	unsigned i;
	for (i = 0; i < sizeof(devtypes) / sizeof(devtypes[0]); i++) {
		char dev[32], addr[32];
		sprintf(dev, "%s%d", devtypes[i].type, (int)procid);
		sprintf(addr, "172.30.%d.%d", i, (int)procid + 1);
		netlink_add_addr4(&nlmsg, sock, dev, addr);
		if (!devtypes[i].noipv6) {
			sprintf(addr, "fe88::%02x:%02x", i, (int)procid + 1);
			netlink_add_addr6(&nlmsg, sock, dev, addr);
		}
		int macsize = devtypes[i].macsize;
		uint64_t macaddr = 0xbbbbbb + ((unsigned long long)i << (8 * (macsize - 2))) +
				 (procid << (8 * (macsize - 1)));
		netlink_device_change(&nlmsg, sock, dev, !devtypes[i].noup, 0, &macaddr, macsize, NULL);
	}
	close(sock);

}

static void setup_common()
{
	if (mount(0, "/sys/fs/fuse/connections", "fusectl", 0, 0)) {
	}
}

static void setup_binderfs()
{
	if (mkdir("/dev/binderfs", 0777)) {
	}
	if (mount("binder", "/dev/binderfs", "binder", 0, NULL)) {
	}
	if (symlink("/dev/binderfs", "./binderfs")) {
	}
}

static void loop();

static void sandbox_common()
{
	prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
	setsid();
	struct rlimit rlim;
	rlim.rlim_cur = rlim.rlim_max = (200 << 20);
	setrlimit(RLIMIT_AS, &rlim);
	rlim.rlim_cur = rlim.rlim_max = 32 << 20;
	setrlimit(RLIMIT_MEMLOCK, &rlim);
	rlim.rlim_cur = rlim.rlim_max = 136 << 20;
	setrlimit(RLIMIT_FSIZE, &rlim);
	rlim.rlim_cur = rlim.rlim_max = 1 << 20;
	setrlimit(RLIMIT_STACK, &rlim);
	rlim.rlim_cur = rlim.rlim_max = 128 << 20;
	setrlimit(RLIMIT_CORE, &rlim);
	rlim.rlim_cur = rlim.rlim_max = 256;
	setrlimit(RLIMIT_NOFILE, &rlim);
	if (unshare(CLONE_NEWNS)) {
	}
	if (mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, NULL)) {
	}
	if (unshare(CLONE_NEWIPC)) {
	}
	if (unshare(0x02000000)) {
	}
	if (unshare(CLONE_NEWUTS)) {
	}
	if (unshare(CLONE_SYSVSEM)) {
	}
	typedef struct {
		const char* name;
		const char* value;
	} sysctl_t;
	static const sysctl_t sysctls[] = {
	    {"/proc/sys/kernel/shmmax", "16777216"},
	    {"/proc/sys/kernel/shmall", "536870912"},
	    {"/proc/sys/kernel/shmmni", "1024"},
	    {"/proc/sys/kernel/msgmax", "8192"},
	    {"/proc/sys/kernel/msgmni", "1024"},
	    {"/proc/sys/kernel/msgmnb", "1024"},
	    {"/proc/sys/kernel/sem", "1024 1048576 500 1024"},
	};
	unsigned i;
	for (i = 0; i < sizeof(sysctls) / sizeof(sysctls[0]); i++)
		write_file(sysctls[i].name, sysctls[i].value);
}

static int wait_for_loop(int pid)
{
	if (pid < 0)
	exit(1);
	int status = 0;
	while (waitpid(-1, &status, __WALL) != pid) {
	}
	return WEXITSTATUS(status);
}

static void drop_caps(void)
{
	struct __user_cap_header_struct cap_hdr = {};
	struct __user_cap_data_struct cap_data[2] = {};
	cap_hdr.version = _LINUX_CAPABILITY_VERSION_3;
	cap_hdr.pid = getpid();
	if (syscall(SYS_capget, &cap_hdr, &cap_data))
	exit(1);
	const int drop = (1 << CAP_SYS_PTRACE) | (1 << CAP_SYS_NICE);
	cap_data[0].effective &= ~drop;
	cap_data[0].permitted &= ~drop;
	cap_data[0].inheritable &= ~drop;
	if (syscall(SYS_capset, &cap_hdr, &cap_data))
	exit(1);
}

static int do_sandbox_none(void)
{
	if (unshare(CLONE_NEWPID)) {
	}
	int pid = fork();
	if (pid != 0)
		return wait_for_loop(pid);
	setup_common();
	sandbox_common();
	drop_caps();
	initialize_netdevices_init();
	if (unshare(CLONE_NEWNET)) {
	}
	write_file("/proc/sys/net/ipv4/ping_group_range", "0 65535");
	initialize_netdevices();
	setup_binderfs();
	loop();
	exit(1);
}

uint64_t r[1] = {0xffffffffffffffff};

void loop(void)
{
		intptr_t res = 0;
	res = syscall(__NR_socket, /*domain=*/0x15ul, /*type=*/5ul, /*proto=*/0);
	if (res != -1)
		r[0] = res;
*(uint8_t*)0x200000c0 = r[0];
*(uint16_t*)0x200000c1 = r[0];
*(uint8_t*)0x200000c3 = r[0];
sprintf((char*)0x200000c4, "0x%016llx", (long long)r[0]);
*(uint8_t*)0x200000d6 = 0;
*(uint64_t*)0x200000d7 = r[0];
*(uint8_t*)0x200000df = 0;
*(uint16_t*)0x200000e0 = -1;
*(uint32_t*)0x200000e2 = -1;
*(uint8_t*)0x200000e6 = -1;
	syscall(__NR_setsockopt, /*fd=*/r[0], /*level=*/0x114, /*opt=*/0xa, /*val=*/0x200000c0ul, /*len=*/4ul);
*(uint16_t*)0x20000080 = 2;
*(uint16_t*)0x20000082 = htobe16(0);
*(uint8_t*)0x20000084 = 0xac;
*(uint8_t*)0x20000085 = 0x14;
*(uint8_t*)0x20000086 = 0x14;
*(uint8_t*)0x20000087 = 0xaa;
	syscall(__NR_connect, /*fd=*/r[0], /*addr=*/0x20000080ul, /*addrlen=*/0x10ul);
*(uint16_t*)0x20000540 = 2;
*(uint16_t*)0x20000542 = htobe16(0);
*(uint8_t*)0x20000544 = 0xac;
*(uint8_t*)0x20000545 = 0x14;
*(uint8_t*)0x20000546 = 0x14;
*(uint8_t*)0x20000547 = 0xaa;
	syscall(__NR_bind, /*fd=*/r[0], /*addr=*/0x20000540ul, /*addrlen=*/0x10ul);
	syscall(__NR_sendto, /*fd=*/r[0], /*buf=*/0ul, /*len=*/0ul, /*f=*/0ul, /*addr=*/0ul, /*addrlen=*/0ul);
	syscall(__NR_recvfrom, /*fd=*/r[0], /*buf=*/0ul, /*len=*/0ul, /*f=*/0ul, /*addr=*/0ul, /*addrlen=*/0ul);

}
int main(void)
{
		syscall(__NR_mmap, /*addr=*/0x1ffff000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=*/0x32ul, /*fd=*/-1, /*offset=*/0ul);
	syscall(__NR_mmap, /*addr=*/0x20000000ul, /*len=*/0x1000000ul, /*prot=*/7ul, /*flags=*/0x32ul, /*fd=*/-1, /*offset=*/0ul);
	syscall(__NR_mmap, /*addr=*/0x21000000ul, /*len=*/0x1000ul, /*prot=*/0ul, /*flags=*/0x32ul, /*fd=*/-1, /*offset=*/0ul);
			do_sandbox_none();
	return 0;
}

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Linux Kernel Bug] UBSAN: array-index-out-of-bounds in rds_cmsg_recv
  2024-01-19 14:29 [Linux Kernel Bug] UBSAN: array-index-out-of-bounds in rds_cmsg_recv Chenyuan Yang
@ 2024-01-21  8:34 ` Zhu Yanjun
  2024-01-22  5:48   ` Randy Dunlap
  0 siblings, 1 reply; 7+ messages in thread
From: Zhu Yanjun @ 2024-01-21  8:34 UTC (permalink / raw)
  To: Chenyuan Yang, santosh.shilimkar, netdev, linux-rdma, rds-devel,
	linux-kernel
  Cc: davem, edumazet, kuba, pabeni, syzkaller, Zijie Zhao

在 2024/1/19 22:29, Chenyuan Yang 写道:
> Dear Linux Kernel Developers for Network RDS,
> 
> We encountered "UBSAN: array-index-out-of-bounds in rds_cmsg_recv"
> when testing the RDS with our generated specifications. The C
> reproduce program and logs for this crash are attached.
> 
> This crash happens when RDS receives messages by using
> `rds_cmsg_recv`, which reads the `j+1` index of the array
> `inc->i_rx_lat_trace`
> (https://elixir.bootlin.com/linux/v6.7/source/net/rds/recv.c#L585).
> The length of `inc->i_rx_lat_trace` array is 4 (defined by
> `RDS_RX_MAX_TRACES`,
> https://elixir.bootlin.com/linux/v6.7/source/net/rds/rds.h#L289) while
> `j` is the value stored in another array `rs->rs_rx_trace`
> (https://elixir.bootlin.com/linux/v6.7/source/net/rds/recv.c#L583),
> which is sent from others and could be arbitrary value.

I recommend to use the latest rds to make tests. The rds in linux kernel 
upstream is too old. The rds in oracle linux is newer.

Zhu Yanjun

> 
> This crash might be exploited to read the value out-of-bound from the
> array by setting arbitrary values for the array `rs->rs_rx_trace`.
> 
> If you have any questions or require more information, please feel
> free to contact us.
> 
> Best,
> Chenyuan


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Linux Kernel Bug] UBSAN: array-index-out-of-bounds in rds_cmsg_recv
  2024-01-21  8:34 ` Zhu Yanjun
@ 2024-01-22  5:48   ` Randy Dunlap
  2024-01-22  8:49     ` Zhu Yanjun
  0 siblings, 1 reply; 7+ messages in thread
From: Randy Dunlap @ 2024-01-22  5:48 UTC (permalink / raw)
  To: Zhu Yanjun, Chenyuan Yang, santosh.shilimkar, netdev, linux-rdma,
	rds-devel, linux-kernel
  Cc: davem, edumazet, kuba, pabeni, syzkaller, Zijie Zhao

Hi,


On 1/21/24 00:34, Zhu Yanjun wrote:
> 在 2024/1/19 22:29, Chenyuan Yang 写道:
>> Dear Linux Kernel Developers for Network RDS,
>>
>> We encountered "UBSAN: array-index-out-of-bounds in rds_cmsg_recv"
>> when testing the RDS with our generated specifications. The C
>> reproduce program and logs for this crash are attached.
>>
>> This crash happens when RDS receives messages by using
>> `rds_cmsg_recv`, which reads the `j+1` index of the array
>> `inc->i_rx_lat_trace`
>> (https://elixir.bootlin.com/linux/v6.7/source/net/rds/recv.c#L585).
>> The length of `inc->i_rx_lat_trace` array is 4 (defined by
>> `RDS_RX_MAX_TRACES`,
>> https://elixir.bootlin.com/linux/v6.7/source/net/rds/rds.h#L289) while
>> `j` is the value stored in another array `rs->rs_rx_trace`
>> (https://elixir.bootlin.com/linux/v6.7/source/net/rds/recv.c#L583),
>> which is sent from others and could be arbitrary value.
> 
> I recommend to use the latest rds to make tests. The rds in linux kernel upstream is too old. The rds in oracle linux is newer.

Why is the upstream kernel lagging behind?  Is the RDS maintainer going
to submit patches to update mainline?

Thanks.

> Zhu Yanjun
> 
>>
>> This crash might be exploited to read the value out-of-bound from the
>> array by setting arbitrary values for the array `rs->rs_rx_trace`.
>>
>> If you have any questions or require more information, please feel
>> free to contact us.
>>
>> Best,
>> Chenyuan
> 
> 

-- 
#Randy

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Linux Kernel Bug] UBSAN: array-index-out-of-bounds in rds_cmsg_recv
  2024-01-22  5:48   ` Randy Dunlap
@ 2024-01-22  8:49     ` Zhu Yanjun
  2024-01-27  0:00       ` Allison Henderson
  0 siblings, 1 reply; 7+ messages in thread
From: Zhu Yanjun @ 2024-01-22  8:49 UTC (permalink / raw)
  To: Randy Dunlap, Chenyuan Yang, santosh.shilimkar, netdev,
	linux-rdma, rds-devel, linux-kernel
  Cc: davem, edumazet, kuba, pabeni, syzkaller, Zijie Zhao

在 2024/1/22 13:48, Randy Dunlap 写道:
> Hi,
> 
> 
> On 1/21/24 00:34, Zhu Yanjun wrote:
>> 在 2024/1/19 22:29, Chenyuan Yang 写道:
>>> Dear Linux Kernel Developers for Network RDS,
>>>
>>> We encountered "UBSAN: array-index-out-of-bounds in rds_cmsg_recv"
>>> when testing the RDS with our generated specifications. The C
>>> reproduce program and logs for this crash are attached.
>>>
>>> This crash happens when RDS receives messages by using
>>> `rds_cmsg_recv`, which reads the `j+1` index of the array
>>> `inc->i_rx_lat_trace`
>>> (https://elixir.bootlin.com/linux/v6.7/source/net/rds/recv.c#L585).
>>> The length of `inc->i_rx_lat_trace` array is 4 (defined by
>>> `RDS_RX_MAX_TRACES`,
>>> https://elixir.bootlin.com/linux/v6.7/source/net/rds/rds.h#L289) while
>>> `j` is the value stored in another array `rs->rs_rx_trace`
>>> (https://elixir.bootlin.com/linux/v6.7/source/net/rds/recv.c#L583),
>>> which is sent from others and could be arbitrary value.
>>
>> I recommend to use the latest rds to make tests. The rds in linux kernel upstream is too old. The rds in oracle linux is newer.
> 
> Why is the upstream kernel lagging behind?  Is the RDS maintainer going
> to submit patches to update mainline?

When I was in Oracle and worked with RDS, I have planned to upgrade 
kernel rds to the latest. But after I submitted several patch series, 
Oracle Developing Center of China was shutdown. I can not finish the 
plan. But the UEK kernel in Oracle linux has the latest RDS.

If you want to make tests with rds, I recommend to use UEK kernel in 
Oracle Linux.

Or you can install UEK kernel in RedHat. IMO, this UEK kernel can also 
work in RedHat Linux.

Zhu Yanjun

> 
> Thanks.
> 
>> Zhu Yanjun
>>
>>>
>>> This crash might be exploited to read the value out-of-bound from the
>>> array by setting arbitrary values for the array `rs->rs_rx_trace`.
>>>
>>> If you have any questions or require more information, please feel
>>> free to contact us.
>>>
>>> Best,
>>> Chenyuan
>>
>>
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Linux Kernel Bug] UBSAN: array-index-out-of-bounds in rds_cmsg_recv
  2024-01-22  8:49     ` Zhu Yanjun
@ 2024-01-27  0:00       ` Allison Henderson
  2024-01-27 16:18         ` Randy Dunlap
  2024-01-28  3:53         ` Zhu Yanjun
  0 siblings, 2 replies; 7+ messages in thread
From: Allison Henderson @ 2024-01-27  0:00 UTC (permalink / raw)
  To: linux-rdma, rdunlap, rds-devel, linux-kernel, Santosh Shilimkar,
	netdev, yanjun.zhu, chenyuan0y
  Cc: zzjas98, edumazet, davem, kuba, pabeni, syzkaller

On Mon, 2024-01-22 at 16:49 +0800, Zhu Yanjun wrote:
> 在 2024/1/22 13:48, Randy Dunlap 写道:
> > Hi,
> > 
> > 
> > On 1/21/24 00:34, Zhu Yanjun wrote:
> > > 在 2024/1/19 22:29, Chenyuan Yang 写道:
> > > > Dear Linux Kernel Developers for Network RDS,
> > > > 
> > > > We encountered "UBSAN: array-index-out-of-bounds in
> > > > rds_cmsg_recv"
> > > > when testing the RDS with our generated specifications. The C
> > > > reproduce program and logs for this crash are attached.
> > > > 
> > > > This crash happens when RDS receives messages by using
> > > > `rds_cmsg_recv`, which reads the `j+1` index of the array
> > > > `inc->i_rx_lat_trace`
> > > > (
> > > > https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.
> > > > 7/source/net/rds/recv.c*L585__;Iw!!ACWV5N9M2RV99hQ!J8QGG3fi_O0g
> > > > 6p3oOboqNj5BuTcMuLuF-7-
> > > > SATmNj8EFTKyC68co6cnoG6LQzY1lJ9M_XA6voErOfj-qXTq3BSnW21Tk$ ).
> > > > The length of `inc->i_rx_lat_trace` array is 4 (defined by
> > > > `RDS_RX_MAX_TRACES`,
> > > > https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7/source/net/rds/rds.h*L289__;Iw!!ACWV5N9M2RV99hQ!J8QGG3fi_O0g6p3oOboqNj5BuTcMuLuF-7-SATmNj8EFTKyC68co6cnoG6LQzY1lJ9M_XA6voErOfj-qXTq3BYX3yVFo$
> > > >  ) while
> > > > `j` is the value stored in another array `rs->rs_rx_trace`
> > > > (
> > > > https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.
> > > > 7/source/net/rds/recv.c*L583__;Iw!!ACWV5N9M2RV99hQ!J8QGG3fi_O0g
> > > > 6p3oOboqNj5BuTcMuLuF-7-
> > > > SATmNj8EFTKyC68co6cnoG6LQzY1lJ9M_XA6voErOfj-qXTq3BVTaaNkx$ ),
> > > > which is sent from others and could be arbitrary value.
> > > 
> > > I recommend to use the latest rds to make tests. The rds in linux
> > > kernel upstream is too old. The rds in oracle linux is newer.
> > 
> > Why is the upstream kernel lagging behind?  Is the RDS maintainer
> > going
> > to submit patches to update mainline?
> 
> When I was in Oracle and worked with RDS, I have planned to upgrade 
> kernel rds to the latest. But after I submitted several patch series,
> Oracle Developing Center of China was shutdown. I can not finish the 
> plan. But the UEK kernel in Oracle linux has the latest RDS.
> 
> If you want to make tests with rds, I recommend to use UEK kernel in 
> Oracle Linux.
> 
> Or you can install UEK kernel in RedHat. IMO, this UEK kernel can
> also 
> work in RedHat Linux.
> 
> Zhu Yanjun

The challenge with updateing rds in upstream is that the uek rds
diverged from upstream a long time ago.  So most of the uek patches
wont apply very well with a pretty big revert to bring it back to the
point of divergence.  It not entirly clear how much rds is used outside
of oracle linux, but we are looking at how we might go about updating
at least the rds_tcp module, as we think this area would have less
patching conflicts, and may be of more interest to community folks. 
This is still very much a work in progress though, and still undergoing
a lot of investigation, so Zhu is likley correct in that for now it's
probably best to simply use a uek kernel if you are just wanting to
develop test cases.

Zhu, I was unaware that an effort had been submitted, but I am still
very much learning rds.  If you want to point me to your set, I would
be happy to study it even if it was submitted a long time ago.  Thanks!

Allison

> 
> > 
> > Thanks.
> > 
> > > Zhu Yanjun
> > > 
> > > > 
> > > > This crash might be exploited to read the value out-of-bound
> > > > from the
> > > > array by setting arbitrary values for the array `rs-
> > > > >rs_rx_trace`.
> > > > 
> > > > If you have any questions or require more information, please
> > > > feel
> > > > free to contact us.
> > > > 
> > > > Best,
> > > > Chenyuan
> > > 
> > > 
> > 
> 
> 


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Linux Kernel Bug] UBSAN: array-index-out-of-bounds in rds_cmsg_recv
  2024-01-27  0:00       ` Allison Henderson
@ 2024-01-27 16:18         ` Randy Dunlap
  2024-01-28  3:53         ` Zhu Yanjun
  1 sibling, 0 replies; 7+ messages in thread
From: Randy Dunlap @ 2024-01-27 16:18 UTC (permalink / raw)
  To: Allison Henderson, linux-rdma, rds-devel, linux-kernel,
	Santosh Shilimkar, netdev, yanjun.zhu, chenyuan0y
  Cc: zzjas98, edumazet, davem, kuba, pabeni, syzkaller



On 1/26/24 16:00, Allison Henderson wrote:
> On Mon, 2024-01-22 at 16:49 +0800, Zhu Yanjun wrote:
>> 在 2024/1/22 13:48, Randy Dunlap 写道:
>>> Hi,
>>>
>>>
>>> On 1/21/24 00:34, Zhu Yanjun wrote:
>>>> 在 2024/1/19 22:29, Chenyuan Yang 写道:
>>>>> Dear Linux Kernel Developers for Network RDS,
>>>>>
>>>>> We encountered "UBSAN: array-index-out-of-bounds in
>>>>> rds_cmsg_recv"
>>>>> when testing the RDS with our generated specifications. The C
>>>>> reproduce program and logs for this crash are attached.
>>>>>
>>>>> This crash happens when RDS receives messages by using
>>>>> `rds_cmsg_recv`, which reads the `j+1` index of the array
>>>>> `inc->i_rx_lat_trace`
>>>>> (
>>>>> https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.
>>>>> 7/source/net/rds/recv.c*L585__;Iw!!ACWV5N9M2RV99hQ!J8QGG3fi_O0g
>>>>> 6p3oOboqNj5BuTcMuLuF-7-
>>>>> SATmNj8EFTKyC68co6cnoG6LQzY1lJ9M_XA6voErOfj-qXTq3BSnW21Tk$ ).
>>>>> The length of `inc->i_rx_lat_trace` array is 4 (defined by
>>>>> `RDS_RX_MAX_TRACES`,
>>>>> https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7/source/net/rds/rds.h*L289__;Iw!!ACWV5N9M2RV99hQ!J8QGG3fi_O0g6p3oOboqNj5BuTcMuLuF-7-SATmNj8EFTKyC68co6cnoG6LQzY1lJ9M_XA6voErOfj-qXTq3BYX3yVFo$
>>>>>  ) while
>>>>> `j` is the value stored in another array `rs->rs_rx_trace`
>>>>> (
>>>>> https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.
>>>>> 7/source/net/rds/recv.c*L583__;Iw!!ACWV5N9M2RV99hQ!J8QGG3fi_O0g
>>>>> 6p3oOboqNj5BuTcMuLuF-7-
>>>>> SATmNj8EFTKyC68co6cnoG6LQzY1lJ9M_XA6voErOfj-qXTq3BVTaaNkx$ ),
>>>>> which is sent from others and could be arbitrary value.
>>>>
>>>> I recommend to use the latest rds to make tests. The rds in linux
>>>> kernel upstream is too old. The rds in oracle linux is newer.
>>>
>>> Why is the upstream kernel lagging behind?  Is the RDS maintainer
>>> going
>>> to submit patches to update mainline?
>>
>> When I was in Oracle and worked with RDS, I have planned to upgrade 
>> kernel rds to the latest. But after I submitted several patch series,
>> Oracle Developing Center of China was shutdown. I can not finish the 
>> plan. But the UEK kernel in Oracle linux has the latest RDS.
>>
>> If you want to make tests with rds, I recommend to use UEK kernel in 
>> Oracle Linux.
>>
>> Or you can install UEK kernel in RedHat. IMO, this UEK kernel can
>> also 
>> work in RedHat Linux.
>>
>> Zhu Yanjun
> 
> The challenge with updateing rds in upstream is that the uek rds
> diverged from upstream a long time ago.  So most of the uek patches
> wont apply very well with a pretty big revert to bring it back to the
> point of divergence.  It not entirly clear how much rds is used outside
> of oracle linux, but we are looking at how we might go about updating
> at least the rds_tcp module, as we think this area would have less
> patching conflicts, and may be of more interest to community folks. 
> This is still very much a work in progress though, and still undergoing
> a lot of investigation, so Zhu is likley correct in that for now it's
> probably best to simply use a uek kernel if you are just wanting to
> develop test cases.
> 
> Zhu, I was unaware that an effort had been submitted, but I am still
> very much learning rds.  If you want to point me to your set, I would
> be happy to study it even if it was submitted a long time ago.  Thanks!
> 
> Allison

Thanks for the update.

> 
>>
>>>
>>> Thanks.
>>>
>>>> Zhu Yanjun
>>>>
>>>>>
>>>>> This crash might be exploited to read the value out-of-bound
>>>>> from the
>>>>> array by setting arbitrary values for the array `rs-
>>>>>> rs_rx_trace`.
>>>>>
>>>>> If you have any questions or require more information, please
>>>>> feel
>>>>> free to contact us.
>>>>>
>>>>> Best,
>>>>> Chenyuan
>>>>
>>>>
>>>
>>
>>
> 

-- 
#Randy

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [Linux Kernel Bug] UBSAN: array-index-out-of-bounds in rds_cmsg_recv
  2024-01-27  0:00       ` Allison Henderson
  2024-01-27 16:18         ` Randy Dunlap
@ 2024-01-28  3:53         ` Zhu Yanjun
  1 sibling, 0 replies; 7+ messages in thread
From: Zhu Yanjun @ 2024-01-28  3:53 UTC (permalink / raw)
  To: Allison Henderson, linux-rdma, rdunlap, rds-devel, linux-kernel,
	Santosh Shilimkar, netdev, chenyuan0y
  Cc: zzjas98, edumazet, davem, kuba, pabeni, syzkaller


在 2024/1/27 8:00, Allison Henderson 写道:
> On Mon, 2024-01-22 at 16:49 +0800, Zhu Yanjun wrote:
>> 在 2024/1/22 13:48, Randy Dunlap 写道:
>>> Hi,
>>>
>>>
>>> On 1/21/24 00:34, Zhu Yanjun wrote:
>>>> 在 2024/1/19 22:29, Chenyuan Yang 写道:
>>>>> Dear Linux Kernel Developers for Network RDS,
>>>>>
>>>>> We encountered "UBSAN: array-index-out-of-bounds in
>>>>> rds_cmsg_recv"
>>>>> when testing the RDS with our generated specifications. The C
>>>>> reproduce program and logs for this crash are attached.
>>>>>
>>>>> This crash happens when RDS receives messages by using
>>>>> `rds_cmsg_recv`, which reads the `j+1` index of the array
>>>>> `inc->i_rx_lat_trace`
>>>>> (
>>>>> https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.
>>>>> 7/source/net/rds/recv.c*L585__;Iw!!ACWV5N9M2RV99hQ!J8QGG3fi_O0g
>>>>> 6p3oOboqNj5BuTcMuLuF-7-
>>>>> SATmNj8EFTKyC68co6cnoG6LQzY1lJ9M_XA6voErOfj-qXTq3BSnW21Tk$ ).
>>>>> The length of `inc->i_rx_lat_trace` array is 4 (defined by
>>>>> `RDS_RX_MAX_TRACES`,
>>>>> https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.7/source/net/rds/rds.h*L289__;Iw!!ACWV5N9M2RV99hQ!J8QGG3fi_O0g6p3oOboqNj5BuTcMuLuF-7-SATmNj8EFTKyC68co6cnoG6LQzY1lJ9M_XA6voErOfj-qXTq3BYX3yVFo$
>>>>>   ) while
>>>>> `j` is the value stored in another array `rs->rs_rx_trace`
>>>>> (
>>>>> https://urldefense.com/v3/__https://elixir.bootlin.com/linux/v6.
>>>>> 7/source/net/rds/recv.c*L583__;Iw!!ACWV5N9M2RV99hQ!J8QGG3fi_O0g
>>>>> 6p3oOboqNj5BuTcMuLuF-7-
>>>>> SATmNj8EFTKyC68co6cnoG6LQzY1lJ9M_XA6voErOfj-qXTq3BVTaaNkx$ ),
>>>>> which is sent from others and could be arbitrary value.
>>>> I recommend to use the latest rds to make tests. The rds in linux
>>>> kernel upstream is too old. The rds in oracle linux is newer.
>>> Why is the upstream kernel lagging behind?  Is the RDS maintainer
>>> going
>>> to submit patches to update mainline?
>> When I was in Oracle and worked with RDS, I have planned to upgrade
>> kernel rds to the latest. But after I submitted several patch series,
>> Oracle Developing Center of China was shutdown. I can not finish the
>> plan. But the UEK kernel in Oracle linux has the latest RDS.
>>
>> If you want to make tests with rds, I recommend to use UEK kernel in
>> Oracle Linux.
>>
>> Or you can install UEK kernel in RedHat. IMO, this UEK kernel can
>> also
>> work in RedHat Linux.
>>
>> Zhu Yanjun
> The challenge with updateing rds in upstream is that the uek rds
> diverged from upstream a long time ago.  So most of the uek patches
> wont apply very well with a pretty big revert to bring it back to the
> point of divergence.  It not entirly clear how much rds is used outside
> of oracle linux, but we are looking at how we might go about updating
> at least the rds_tcp module, as we think this area would have less

 From my perspective, a lot of people are more interested in rds_rdma 
module.

Exactly the gap between linux upstream and UEK is very big. But based on 
the rds features,

we can backport these features to linux upstream.

Zhu Yanjun

> patching conflicts, and may be of more interest to community folks.
> This is still very much a work in progress though, and still undergoing
> a lot of investigation, so Zhu is likley correct in that for now it's
> probably best to simply use a uek kernel if you are just wanting to
> develop test cases.
>
> Zhu, I was unaware that an effort had been submitted, but I am still
> very much learning rds.  If you want to point me to your set, I would
> be happy to study it even if it was submitted a long time ago.  Thanks!
>
> Allison
>
>>> Thanks.
>>>
>>>> Zhu Yanjun
>>>>
>>>>> This crash might be exploited to read the value out-of-bound
>>>>> from the
>>>>> array by setting arbitrary values for the array `rs-
>>>>>> rs_rx_trace`.
>>>>> If you have any questions or require more information, please
>>>>> feel
>>>>> free to contact us.
>>>>>
>>>>> Best,
>>>>> Chenyuan
>>>>
>>

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2024-01-28  3:53 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-19 14:29 [Linux Kernel Bug] UBSAN: array-index-out-of-bounds in rds_cmsg_recv Chenyuan Yang
2024-01-21  8:34 ` Zhu Yanjun
2024-01-22  5:48   ` Randy Dunlap
2024-01-22  8:49     ` Zhu Yanjun
2024-01-27  0:00       ` Allison Henderson
2024-01-27 16:18         ` Randy Dunlap
2024-01-28  3:53         ` Zhu Yanjun

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).