mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 01:24:47 +01:00
syzbot reported null-ptr-deref of udp_sk(sk)->udp_prod_queue. [0]
Since the cited commit, udp_lib_init_sock() can fail, as can
udp_init_sock() and udpv6_init_sock().
Let's handle the error in udplite_sk_init() and udplitev6_sk_init().
[0]:
BUG: KASAN: null-ptr-deref in instrument_atomic_read include/linux/instrumented.h:82 [inline]
BUG: KASAN: null-ptr-deref in atomic_read include/linux/atomic/atomic-instrumented.h:32 [inline]
BUG: KASAN: null-ptr-deref in __udp_enqueue_schedule_skb+0x151/0x1480 net/ipv4/udp.c:1719
Read of size 4 at addr 0000000000000008 by task syz.2.18/2944
CPU: 1 UID: 0 PID: 2944 Comm: syz.2.18 Not tainted syzkaller #0 PREEMPTLAZY
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 10/25/2025
Call Trace:
<IRQ>
dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
kasan_report+0xa2/0xe0 mm/kasan/report.c:595
check_region_inline mm/kasan/generic.c:-1 [inline]
kasan_check_range+0x264/0x2c0 mm/kasan/generic.c:200
instrument_atomic_read include/linux/instrumented.h:82 [inline]
atomic_read include/linux/atomic/atomic-instrumented.h:32 [inline]
__udp_enqueue_schedule_skb+0x151/0x1480 net/ipv4/udp.c:1719
__udpv6_queue_rcv_skb net/ipv6/udp.c:795 [inline]
udpv6_queue_rcv_one_skb+0xa2e/0x1ad0 net/ipv6/udp.c:906
udp6_unicast_rcv_skb+0x227/0x380 net/ipv6/udp.c:1064
ip6_protocol_deliver_rcu+0xe17/0x1540 net/ipv6/ip6_input.c:438
ip6_input_finish+0x191/0x350 net/ipv6/ip6_input.c:489
NF_HOOK+0x354/0x3f0 include/linux/netfilter.h:318
ip6_input+0x16c/0x2b0 net/ipv6/ip6_input.c:500
NF_HOOK+0x354/0x3f0 include/linux/netfilter.h:318
__netif_receive_skb_one_core net/core/dev.c:6149 [inline]
__netif_receive_skb+0xd3/0x370 net/core/dev.c:6262
process_backlog+0x4d6/0x1160 net/core/dev.c:6614
__napi_poll+0xae/0x320 net/core/dev.c:7678
napi_poll net/core/dev.c:7741 [inline]
net_rx_action+0x60d/0xdc0 net/core/dev.c:7893
handle_softirqs+0x209/0x8d0 kernel/softirq.c:622
do_softirq+0x52/0x90 kernel/softirq.c:523
</IRQ>
<TASK>
__local_bh_enable_ip+0xe7/0x120 kernel/softirq.c:450
local_bh_enable include/linux/bottom_half.h:33 [inline]
rcu_read_unlock_bh include/linux/rcupdate.h:924 [inline]
__dev_queue_xmit+0x109c/0x2dc0 net/core/dev.c:4856
__ip6_finish_output net/ipv6/ip6_output.c:-1 [inline]
ip6_finish_output+0x158/0x4e0 net/ipv6/ip6_output.c:219
NF_HOOK_COND include/linux/netfilter.h:307 [inline]
ip6_output+0x342/0x580 net/ipv6/ip6_output.c:246
ip6_send_skb+0x1d7/0x3c0 net/ipv6/ip6_output.c:1984
udp_v6_send_skb+0x9a5/0x1770 net/ipv6/udp.c:1442
udp_v6_push_pending_frames+0xa2/0x140 net/ipv6/udp.c:1469
udpv6_sendmsg+0xfe0/0x2830 net/ipv6/udp.c:1759
sock_sendmsg_nosec net/socket.c:727 [inline]
__sock_sendmsg+0xe5/0x270 net/socket.c:742
__sys_sendto+0x3eb/0x580 net/socket.c:2206
__do_sys_sendto net/socket.c:2213 [inline]
__se_sys_sendto net/socket.c:2209 [inline]
__x64_sys_sendto+0xde/0x100 net/socket.c:2209
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0xd2/0xf20 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x76/0x7e
RIP: 0033:0x7f67b4d9c629
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 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 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007f67b5c98028 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
RAX: ffffffffffffffda RBX: 00007f67b5015fa0 RCX: 00007f67b4d9c629
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000003
RBP: 00007f67b4e32b39 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000040000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f67b5016038 R14: 00007f67b5015fa0 R15: 00007ffe3cb66dd8
</TASK>
Fixes: b650bf0977 ("udp: remove busylock and add per NUMA queues")
Reported-by: syzbot <syzkaller@googlegroups.com>
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
Link: https://patch.msgid.link/20260219173142.310741-1-kuniyu@google.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
135 lines
3.3 KiB
C
135 lines
3.3 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* UDPLITE An implementation of the UDP-Lite protocol (RFC 3828).
|
|
*
|
|
* Authors: Gerrit Renker <gerrit@erg.abdn.ac.uk>
|
|
*
|
|
* Changes:
|
|
* Fixes:
|
|
*/
|
|
|
|
#define pr_fmt(fmt) "UDPLite: " fmt
|
|
|
|
#include <linux/export.h>
|
|
#include <linux/proc_fs.h>
|
|
#include "udp_impl.h"
|
|
|
|
struct udp_table udplite_table __read_mostly;
|
|
EXPORT_SYMBOL(udplite_table);
|
|
|
|
/* Designate sk as UDP-Lite socket */
|
|
static int udplite_sk_init(struct sock *sk)
|
|
{
|
|
pr_warn_once("UDP-Lite is deprecated and scheduled to be removed in 2025, "
|
|
"please contact the netdev mailing list\n");
|
|
return udp_init_sock(sk);
|
|
}
|
|
|
|
static int udplite_rcv(struct sk_buff *skb)
|
|
{
|
|
return __udp4_lib_rcv(skb, &udplite_table, IPPROTO_UDPLITE);
|
|
}
|
|
|
|
static int udplite_err(struct sk_buff *skb, u32 info)
|
|
{
|
|
return __udp4_lib_err(skb, info, &udplite_table);
|
|
}
|
|
|
|
static const struct net_protocol udplite_protocol = {
|
|
.handler = udplite_rcv,
|
|
.err_handler = udplite_err,
|
|
.no_policy = 1,
|
|
};
|
|
|
|
struct proto udplite_prot = {
|
|
.name = "UDP-Lite",
|
|
.owner = THIS_MODULE,
|
|
.close = udp_lib_close,
|
|
.connect = ip4_datagram_connect,
|
|
.disconnect = udp_disconnect,
|
|
.ioctl = udp_ioctl,
|
|
.init = udplite_sk_init,
|
|
.destroy = udp_destroy_sock,
|
|
.setsockopt = udp_setsockopt,
|
|
.getsockopt = udp_getsockopt,
|
|
.sendmsg = udp_sendmsg,
|
|
.recvmsg = udp_recvmsg,
|
|
.hash = udp_lib_hash,
|
|
.unhash = udp_lib_unhash,
|
|
.rehash = udp_v4_rehash,
|
|
.get_port = udp_v4_get_port,
|
|
|
|
.memory_allocated = &net_aligned_data.udp_memory_allocated,
|
|
.per_cpu_fw_alloc = &udp_memory_per_cpu_fw_alloc,
|
|
|
|
.sysctl_mem = sysctl_udp_mem,
|
|
.sysctl_wmem_offset = offsetof(struct net, ipv4.sysctl_udp_wmem_min),
|
|
.sysctl_rmem_offset = offsetof(struct net, ipv4.sysctl_udp_rmem_min),
|
|
.obj_size = sizeof(struct udp_sock),
|
|
.h.udp_table = &udplite_table,
|
|
};
|
|
EXPORT_SYMBOL(udplite_prot);
|
|
|
|
static struct inet_protosw udplite4_protosw = {
|
|
.type = SOCK_DGRAM,
|
|
.protocol = IPPROTO_UDPLITE,
|
|
.prot = &udplite_prot,
|
|
.ops = &inet_dgram_ops,
|
|
.flags = INET_PROTOSW_PERMANENT,
|
|
};
|
|
|
|
#ifdef CONFIG_PROC_FS
|
|
static struct udp_seq_afinfo udplite4_seq_afinfo = {
|
|
.family = AF_INET,
|
|
.udp_table = &udplite_table,
|
|
};
|
|
|
|
static int __net_init udplite4_proc_init_net(struct net *net)
|
|
{
|
|
if (!proc_create_net_data("udplite", 0444, net->proc_net, &udp_seq_ops,
|
|
sizeof(struct udp_iter_state), &udplite4_seq_afinfo))
|
|
return -ENOMEM;
|
|
return 0;
|
|
}
|
|
|
|
static void __net_exit udplite4_proc_exit_net(struct net *net)
|
|
{
|
|
remove_proc_entry("udplite", net->proc_net);
|
|
}
|
|
|
|
static struct pernet_operations udplite4_net_ops = {
|
|
.init = udplite4_proc_init_net,
|
|
.exit = udplite4_proc_exit_net,
|
|
};
|
|
|
|
static __init int udplite4_proc_init(void)
|
|
{
|
|
return register_pernet_subsys(&udplite4_net_ops);
|
|
}
|
|
#else
|
|
static inline int udplite4_proc_init(void)
|
|
{
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
void __init udplite4_register(void)
|
|
{
|
|
udp_table_init(&udplite_table, "UDP-Lite");
|
|
if (proto_register(&udplite_prot, 1))
|
|
goto out_register_err;
|
|
|
|
if (inet_add_protocol(&udplite_protocol, IPPROTO_UDPLITE) < 0)
|
|
goto out_unregister_proto;
|
|
|
|
inet_register_protosw(&udplite4_protosw);
|
|
|
|
if (udplite4_proc_init())
|
|
pr_err("%s: Cannot register /proc!\n", __func__);
|
|
return;
|
|
|
|
out_unregister_proto:
|
|
proto_unregister(&udplite_prot);
|
|
out_register_err:
|
|
pr_crit("%s: Cannot add UDP-Lite protocol\n", __func__);
|
|
}
|