Skip to content

Commit 02c71b1

Browse files
edumazetdavem330
authored andcommitted
l2tp: do not use inet_hash()/inet_unhash()
syzbot recently found a way to crash the kernel [1] Issue here is that inet_hash() & inet_unhash() are currently only meant to be used by TCP & DCCP, since only these protocols provide the needed hashinfo pointer. L2TP uses a single list (instead of a hash table) This old bug became an issue after commit 6102365 ("bpf: Add new cgroup attach type to enable sock modifications") since after this commit, sk_common_release() can be called while the L2TP socket is still considered 'hashed'. general protection fault, probably for non-canonical address 0xdffffc0000000001: 0000 [#1] PREEMPT SMP KASAN KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f] CPU: 0 PID: 7063 Comm: syz-executor654 Not tainted 5.7.0-rc6-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 RIP: 0010:inet_unhash+0x11f/0x770 net/ipv4/inet_hashtables.c:600 Code: 03 0f b6 04 02 84 c0 74 08 3c 03 0f 8e dd 04 00 00 48 8d 7d 08 44 8b 73 08 48 b8 00 00 00 00 00 fc ff df 48 89 fa 48 c1 ea 03 <80> 3c 02 00 0f 85 55 05 00 00 48 8d 7d 14 4c 8b 6d 08 48 b8 00 00 RSP: 0018:ffffc90001777d30 EFLAGS: 00010202 RAX: dffffc0000000000 RBX: ffff88809a6df940 RCX: ffffffff8697c242 RDX: 0000000000000001 RSI: ffffffff8697c251 RDI: 0000000000000008 RBP: 0000000000000000 R08: ffff88809f3ae1c0 R09: fffffbfff1514cc1 R10: ffffffff8a8a6607 R11: fffffbfff1514cc0 R12: ffff88809a6df9b0 R13: 0000000000000007 R14: 0000000000000000 R15: ffffffff873a4d00 FS: 0000000001d2b880(0000) GS:ffff8880ae600000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000006cd090 CR3: 000000009403a000 CR4: 00000000001406f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: sk_common_release+0xba/0x370 net/core/sock.c:3210 inet_create net/ipv4/af_inet.c:390 [inline] inet_create+0x966/0xe00 net/ipv4/af_inet.c:248 __sock_create+0x3cb/0x730 net/socket.c:1428 sock_create net/socket.c:1479 [inline] __sys_socket+0xef/0x200 net/socket.c:1521 __do_sys_socket net/socket.c:1530 [inline] __se_sys_socket net/socket.c:1528 [inline] __x64_sys_socket+0x6f/0xb0 net/socket.c:1528 do_syscall_64+0xf6/0x7d0 arch/x86/entry/common.c:295 entry_SYSCALL_64_after_hwframe+0x49/0xb3 RIP: 0033:0x441e29 Code: e8 fc b3 02 00 48 83 c4 18 c3 0f 1f 80 00 00 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 0f 83 eb 08 fc ff c3 66 2e 0f 1f 84 00 00 00 00 RSP: 002b:00007ffdce184148 EFLAGS: 00000246 ORIG_RAX: 0000000000000029 RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 0000000000441e29 RDX: 0000000000000073 RSI: 0000000000000002 RDI: 0000000000000002 RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000000 R13: 0000000000402c30 R14: 0000000000000000 R15: 0000000000000000 Modules linked in: ---[ end trace 23b6578228ce553e ]--- RIP: 0010:inet_unhash+0x11f/0x770 net/ipv4/inet_hashtables.c:600 Code: 03 0f b6 04 02 84 c0 74 08 3c 03 0f 8e dd 04 00 00 48 8d 7d 08 44 8b 73 08 48 b8 00 00 00 00 00 fc ff df 48 89 fa 48 c1 ea 03 <80> 3c 02 00 0f 85 55 05 00 00 48 8d 7d 14 4c 8b 6d 08 48 b8 00 00 RSP: 0018:ffffc90001777d30 EFLAGS: 00010202 RAX: dffffc0000000000 RBX: ffff88809a6df940 RCX: ffffffff8697c242 RDX: 0000000000000001 RSI: ffffffff8697c251 RDI: 0000000000000008 RBP: 0000000000000000 R08: ffff88809f3ae1c0 R09: fffffbfff1514cc1 R10: ffffffff8a8a6607 R11: fffffbfff1514cc0 R12: ffff88809a6df9b0 R13: 0000000000000007 R14: 0000000000000000 R15: ffffffff873a4d00 FS: 0000000001d2b880(0000) GS:ffff8880ae600000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000006cd090 CR3: 000000009403a000 CR4: 00000000001406f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Fixes: 0d76751 ("l2tp: Add L2TPv3 IP encapsulation (no UDP) support") Signed-off-by: Eric Dumazet <[email protected]> Cc: James Chapman <[email protected]> Cc: Andrii Nakryiko <[email protected]> Reported-by: [email protected]
1 parent c6e08d6 commit 02c71b1

File tree

2 files changed

+44
-15
lines changed

2 files changed

+44
-15
lines changed

net/l2tp/l2tp_ip.c

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@
2020
#include <net/icmp.h>
2121
#include <net/udp.h>
2222
#include <net/inet_common.h>
23-
#include <net/inet_hashtables.h>
2423
#include <net/tcp_states.h>
2524
#include <net/protocol.h>
2625
#include <net/xfrm.h>
@@ -209,15 +208,31 @@ static int l2tp_ip_recv(struct sk_buff *skb)
209208
return 0;
210209
}
211210

212-
static int l2tp_ip_open(struct sock *sk)
211+
static int l2tp_ip_hash(struct sock *sk)
213212
{
214-
/* Prevent autobind. We don't have ports. */
215-
inet_sk(sk)->inet_num = IPPROTO_L2TP;
213+
if (sk_unhashed(sk)) {
214+
write_lock_bh(&l2tp_ip_lock);
215+
sk_add_node(sk, &l2tp_ip_table);
216+
write_unlock_bh(&l2tp_ip_lock);
217+
}
218+
return 0;
219+
}
216220

221+
static void l2tp_ip_unhash(struct sock *sk)
222+
{
223+
if (sk_unhashed(sk))
224+
return;
217225
write_lock_bh(&l2tp_ip_lock);
218-
sk_add_node(sk, &l2tp_ip_table);
226+
sk_del_node_init(sk);
219227
write_unlock_bh(&l2tp_ip_lock);
228+
}
229+
230+
static int l2tp_ip_open(struct sock *sk)
231+
{
232+
/* Prevent autobind. We don't have ports. */
233+
inet_sk(sk)->inet_num = IPPROTO_L2TP;
220234

235+
l2tp_ip_hash(sk);
221236
return 0;
222237
}
223238

@@ -594,8 +609,8 @@ static struct proto l2tp_ip_prot = {
594609
.sendmsg = l2tp_ip_sendmsg,
595610
.recvmsg = l2tp_ip_recvmsg,
596611
.backlog_rcv = l2tp_ip_backlog_recv,
597-
.hash = inet_hash,
598-
.unhash = inet_unhash,
612+
.hash = l2tp_ip_hash,
613+
.unhash = l2tp_ip_unhash,
599614
.obj_size = sizeof(struct l2tp_ip_sock),
600615
#ifdef CONFIG_COMPAT
601616
.compat_setsockopt = compat_ip_setsockopt,

net/l2tp/l2tp_ip6.c

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,6 @@
2020
#include <net/icmp.h>
2121
#include <net/udp.h>
2222
#include <net/inet_common.h>
23-
#include <net/inet_hashtables.h>
24-
#include <net/inet6_hashtables.h>
2523
#include <net/tcp_states.h>
2624
#include <net/protocol.h>
2725
#include <net/xfrm.h>
@@ -222,15 +220,31 @@ static int l2tp_ip6_recv(struct sk_buff *skb)
222220
return 0;
223221
}
224222

225-
static int l2tp_ip6_open(struct sock *sk)
223+
static int l2tp_ip6_hash(struct sock *sk)
226224
{
227-
/* Prevent autobind. We don't have ports. */
228-
inet_sk(sk)->inet_num = IPPROTO_L2TP;
225+
if (sk_unhashed(sk)) {
226+
write_lock_bh(&l2tp_ip6_lock);
227+
sk_add_node(sk, &l2tp_ip6_table);
228+
write_unlock_bh(&l2tp_ip6_lock);
229+
}
230+
return 0;
231+
}
229232

233+
static void l2tp_ip6_unhash(struct sock *sk)
234+
{
235+
if (sk_unhashed(sk))
236+
return;
230237
write_lock_bh(&l2tp_ip6_lock);
231-
sk_add_node(sk, &l2tp_ip6_table);
238+
sk_del_node_init(sk);
232239
write_unlock_bh(&l2tp_ip6_lock);
240+
}
241+
242+
static int l2tp_ip6_open(struct sock *sk)
243+
{
244+
/* Prevent autobind. We don't have ports. */
245+
inet_sk(sk)->inet_num = IPPROTO_L2TP;
233246

247+
l2tp_ip6_hash(sk);
234248
return 0;
235249
}
236250

@@ -728,8 +742,8 @@ static struct proto l2tp_ip6_prot = {
728742
.sendmsg = l2tp_ip6_sendmsg,
729743
.recvmsg = l2tp_ip6_recvmsg,
730744
.backlog_rcv = l2tp_ip6_backlog_recv,
731-
.hash = inet6_hash,
732-
.unhash = inet_unhash,
745+
.hash = l2tp_ip6_hash,
746+
.unhash = l2tp_ip6_unhash,
733747
.obj_size = sizeof(struct l2tp_ip6_sock),
734748
#ifdef CONFIG_COMPAT
735749
.compat_setsockopt = compat_ipv6_setsockopt,

0 commit comments

Comments
 (0)