Skip to content

Commit 2e3f17f

Browse files
Eric Dumazetgregkh
Eric Dumazet
authored andcommitted
af_key: do not use GFP_KERNEL in atomic contexts
[ Upstream commit 36f41f8 ] pfkey_broadcast() might be called from non process contexts, we can not use GFP_KERNEL in these cases [1]. This patch partially reverts commit ba51b6b ("net: Fix RCU splat in af_key"), only keeping the GFP_ATOMIC forcing under rcu_read_lock() section. [1] : syzkaller reported : in_atomic(): 1, irqs_disabled(): 0, pid: 2932, name: syzkaller183439 3 locks held by syzkaller183439/2932: #0: (&net->xfrm.xfrm_cfg_mutex){+.+.+.}, at: [<ffffffff83b43888>] pfkey_sendmsg+0x4c8/0x9f0 net/key/af_key.c:3649 #1: (&pfk->dump_lock){+.+.+.}, at: [<ffffffff83b467f6>] pfkey_do_dump+0x76/0x3f0 net/key/af_key.c:293 #2: (&(&net->xfrm.xfrm_policy_lock)->rlock){+...+.}, at: [<ffffffff83957632>] spin_lock_bh include/linux/spinlock.h:304 [inline] #2: (&(&net->xfrm.xfrm_policy_lock)->rlock){+...+.}, at: [<ffffffff83957632>] xfrm_policy_walk+0x192/0xa30 net/xfrm/xfrm_policy.c:1028 CPU: 0 PID: 2932 Comm: syzkaller183439 Not tainted 4.13.0-rc4+ #24 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:16 [inline] dump_stack+0x194/0x257 lib/dump_stack.c:52 ___might_sleep+0x2b2/0x470 kernel/sched/core.c:5994 __might_sleep+0x95/0x190 kernel/sched/core.c:5947 slab_pre_alloc_hook mm/slab.h:416 [inline] slab_alloc mm/slab.c:3383 [inline] kmem_cache_alloc+0x24b/0x6e0 mm/slab.c:3559 skb_clone+0x1a0/0x400 net/core/skbuff.c:1037 pfkey_broadcast_one+0x4b2/0x6f0 net/key/af_key.c:207 pfkey_broadcast+0x4ba/0x770 net/key/af_key.c:281 dump_sp+0x3d6/0x500 net/key/af_key.c:2685 xfrm_policy_walk+0x2f1/0xa30 net/xfrm/xfrm_policy.c:1042 pfkey_dump_sp+0x42/0x50 net/key/af_key.c:2695 pfkey_do_dump+0xaa/0x3f0 net/key/af_key.c:299 pfkey_spddump+0x1a0/0x210 net/key/af_key.c:2722 pfkey_process+0x606/0x710 net/key/af_key.c:2814 pfkey_sendmsg+0x4d6/0x9f0 net/key/af_key.c:3650 sock_sendmsg_nosec net/socket.c:633 [inline] sock_sendmsg+0xca/0x110 net/socket.c:643 ___sys_sendmsg+0x755/0x890 net/socket.c:2035 __sys_sendmsg+0xe5/0x210 net/socket.c:2069 SYSC_sendmsg net/socket.c:2080 [inline] SyS_sendmsg+0x2d/0x50 net/socket.c:2076 entry_SYSCALL_64_fastpath+0x1f/0xbe RIP: 0033:0x445d79 RSP: 002b:00007f32447c1dc8 EFLAGS: 00000202 ORIG_RAX: 000000000000002e RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 0000000000445d79 RDX: 0000000000000000 RSI: 000000002023dfc8 RDI: 0000000000000008 RBP: 0000000000000086 R08: 00007f32447c2700 R09: 00007f32447c2700 R10: 00007f32447c2700 R11: 0000000000000202 R12: 0000000000000000 R13: 00007ffe33edec4f R14: 00007f32447c29c0 R15: 0000000000000000 Fixes: ba51b6b ("net: Fix RCU splat in af_key") Signed-off-by: Eric Dumazet <edumazet@google.com> Reported-by: Dmitry Vyukov <dvyukov@google.com> Cc: David Ahern <dsa@cumulusnetworks.com> Acked-by: David Ahern <dsahern@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent d0526ee commit 2e3f17f

File tree

1 file changed

+26
-22
lines changed

1 file changed

+26
-22
lines changed

net/key/af_key.c

Lines changed: 26 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2,
228228
#define BROADCAST_ONE 1
229229
#define BROADCAST_REGISTERED 2
230230
#define BROADCAST_PROMISC_ONLY 4
231-
static int pfkey_broadcast(struct sk_buff *skb,
231+
static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
232232
int broadcast_flags, struct sock *one_sk,
233233
struct net *net)
234234
{
@@ -278,7 +278,7 @@ static int pfkey_broadcast(struct sk_buff *skb,
278278
rcu_read_unlock();
279279

280280
if (one_sk != NULL)
281-
err = pfkey_broadcast_one(skb, &skb2, GFP_KERNEL, one_sk);
281+
err = pfkey_broadcast_one(skb, &skb2, allocation, one_sk);
282282

283283
kfree_skb(skb2);
284284
kfree_skb(skb);
@@ -311,7 +311,7 @@ static int pfkey_do_dump(struct pfkey_sock *pfk)
311311
hdr = (struct sadb_msg *) pfk->dump.skb->data;
312312
hdr->sadb_msg_seq = 0;
313313
hdr->sadb_msg_errno = rc;
314-
pfkey_broadcast(pfk->dump.skb, BROADCAST_ONE,
314+
pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE,
315315
&pfk->sk, sock_net(&pfk->sk));
316316
pfk->dump.skb = NULL;
317317
}
@@ -355,7 +355,7 @@ static int pfkey_error(const struct sadb_msg *orig, int err, struct sock *sk)
355355
hdr->sadb_msg_len = (sizeof(struct sadb_msg) /
356356
sizeof(uint64_t));
357357

358-
pfkey_broadcast(skb, BROADCAST_ONE, sk, sock_net(sk));
358+
pfkey_broadcast(skb, GFP_KERNEL, BROADCAST_ONE, sk, sock_net(sk));
359359

360360
return 0;
361361
}
@@ -1396,7 +1396,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, const struct sadb_
13961396

13971397
xfrm_state_put(x);
13981398

1399-
pfkey_broadcast(resp_skb, BROADCAST_ONE, sk, net);
1399+
pfkey_broadcast(resp_skb, GFP_KERNEL, BROADCAST_ONE, sk, net);
14001400

14011401
return 0;
14021402
}
@@ -1483,7 +1483,7 @@ static int key_notify_sa(struct xfrm_state *x, const struct km_event *c)
14831483
hdr->sadb_msg_seq = c->seq;
14841484
hdr->sadb_msg_pid = c->portid;
14851485

1486-
pfkey_broadcast(skb, BROADCAST_ALL, NULL, xs_net(x));
1486+
pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, xs_net(x));
14871487

14881488
return 0;
14891489
}
@@ -1596,7 +1596,7 @@ static int pfkey_get(struct sock *sk, struct sk_buff *skb, const struct sadb_msg
15961596
out_hdr->sadb_msg_reserved = 0;
15971597
out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;
15981598
out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;
1599-
pfkey_broadcast(out_skb, BROADCAST_ONE, sk, sock_net(sk));
1599+
pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, sk, sock_net(sk));
16001600

16011601
return 0;
16021602
}
@@ -1701,8 +1701,8 @@ static int pfkey_register(struct sock *sk, struct sk_buff *skb, const struct sad
17011701
return -ENOBUFS;
17021702
}
17031703

1704-
pfkey_broadcast(supp_skb, BROADCAST_REGISTERED, sk, sock_net(sk));
1705-
1704+
pfkey_broadcast(supp_skb, GFP_KERNEL, BROADCAST_REGISTERED, sk,
1705+
sock_net(sk));
17061706
return 0;
17071707
}
17081708

@@ -1720,7 +1720,8 @@ static int unicast_flush_resp(struct sock *sk, const struct sadb_msg *ihdr)
17201720
hdr->sadb_msg_errno = (uint8_t) 0;
17211721
hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
17221722

1723-
return pfkey_broadcast(skb, BROADCAST_ONE, sk, sock_net(sk));
1723+
return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ONE, sk,
1724+
sock_net(sk));
17241725
}
17251726

17261727
static int key_notify_sa_flush(const struct km_event *c)
@@ -1741,7 +1742,7 @@ static int key_notify_sa_flush(const struct km_event *c)
17411742
hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
17421743
hdr->sadb_msg_reserved = 0;
17431744

1744-
pfkey_broadcast(skb, BROADCAST_ALL, NULL, c->net);
1745+
pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net);
17451746

17461747
return 0;
17471748
}
@@ -1798,7 +1799,7 @@ static int dump_sa(struct xfrm_state *x, int count, void *ptr)
17981799
out_hdr->sadb_msg_pid = pfk->dump.msg_portid;
17991800

18001801
if (pfk->dump.skb)
1801-
pfkey_broadcast(pfk->dump.skb, BROADCAST_ONE,
1802+
pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE,
18021803
&pfk->sk, sock_net(&pfk->sk));
18031804
pfk->dump.skb = out_skb;
18041805

@@ -1886,7 +1887,7 @@ static int pfkey_promisc(struct sock *sk, struct sk_buff *skb, const struct sadb
18861887
new_hdr->sadb_msg_errno = 0;
18871888
}
18881889

1889-
pfkey_broadcast(skb, BROADCAST_ALL, NULL, sock_net(sk));
1890+
pfkey_broadcast(skb, GFP_KERNEL, BROADCAST_ALL, NULL, sock_net(sk));
18901891
return 0;
18911892
}
18921893

@@ -2219,7 +2220,7 @@ static int key_notify_policy(struct xfrm_policy *xp, int dir, const struct km_ev
22192220
out_hdr->sadb_msg_errno = 0;
22202221
out_hdr->sadb_msg_seq = c->seq;
22212222
out_hdr->sadb_msg_pid = c->portid;
2222-
pfkey_broadcast(out_skb, BROADCAST_ALL, NULL, xp_net(xp));
2223+
pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, NULL, xp_net(xp));
22232224
return 0;
22242225

22252226
}
@@ -2439,7 +2440,7 @@ static int key_pol_get_resp(struct sock *sk, struct xfrm_policy *xp, const struc
24392440
out_hdr->sadb_msg_errno = 0;
24402441
out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;
24412442
out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;
2442-
pfkey_broadcast(out_skb, BROADCAST_ONE, sk, xp_net(xp));
2443+
pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, sk, xp_net(xp));
24432444
err = 0;
24442445

24452446
out:
@@ -2695,7 +2696,7 @@ static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr)
26952696
out_hdr->sadb_msg_pid = pfk->dump.msg_portid;
26962697

26972698
if (pfk->dump.skb)
2698-
pfkey_broadcast(pfk->dump.skb, BROADCAST_ONE,
2699+
pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE,
26992700
&pfk->sk, sock_net(&pfk->sk));
27002701
pfk->dump.skb = out_skb;
27012702

@@ -2752,7 +2753,7 @@ static int key_notify_policy_flush(const struct km_event *c)
27522753
hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC;
27532754
hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
27542755
hdr->sadb_msg_reserved = 0;
2755-
pfkey_broadcast(skb_out, BROADCAST_ALL, NULL, c->net);
2756+
pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net);
27562757
return 0;
27572758

27582759
}
@@ -2814,7 +2815,7 @@ static int pfkey_process(struct sock *sk, struct sk_buff *skb, const struct sadb
28142815
void *ext_hdrs[SADB_EXT_MAX];
28152816
int err;
28162817

2817-
pfkey_broadcast(skb_clone(skb, GFP_KERNEL),
2818+
pfkey_broadcast(skb_clone(skb, GFP_KERNEL), GFP_KERNEL,
28182819
BROADCAST_PROMISC_ONLY, NULL, sock_net(sk));
28192820

28202821
memset(ext_hdrs, 0, sizeof(ext_hdrs));
@@ -3036,7 +3037,8 @@ static int key_notify_sa_expire(struct xfrm_state *x, const struct km_event *c)
30363037
out_hdr->sadb_msg_seq = 0;
30373038
out_hdr->sadb_msg_pid = 0;
30383039

3039-
pfkey_broadcast(out_skb, BROADCAST_REGISTERED, NULL, xs_net(x));
3040+
pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL,
3041+
xs_net(x));
30403042
return 0;
30413043
}
30423044

@@ -3226,7 +3228,8 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct
32263228
xfrm_ctx->ctx_len);
32273229
}
32283230

3229-
return pfkey_broadcast(skb, BROADCAST_REGISTERED, NULL, xs_net(x));
3231+
return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL,
3232+
xs_net(x));
32303233
}
32313234

32323235
static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt,
@@ -3424,7 +3427,8 @@ static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr,
34243427
n_port->sadb_x_nat_t_port_port = sport;
34253428
n_port->sadb_x_nat_t_port_reserved = 0;
34263429

3427-
return pfkey_broadcast(skb, BROADCAST_REGISTERED, NULL, xs_net(x));
3430+
return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL,
3431+
xs_net(x));
34283432
}
34293433

34303434
#ifdef CONFIG_NET_KEY_MIGRATE
@@ -3616,7 +3620,7 @@ static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
36163620
}
36173621

36183622
/* broadcast migrate message to sockets */
3619-
pfkey_broadcast(skb, BROADCAST_ALL, NULL, &init_net);
3623+
pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, &init_net);
36203624

36213625
return 0;
36223626

0 commit comments

Comments
 (0)