summaryrefslogtreecommitdiffstats
path: root/net/key
diff options
context:
space:
mode:
authorEric Dumazet <edumazet@google.com>2017-08-14 13:16:45 -0400
committerDavid S. Miller <davem@davemloft.net>2017-08-15 01:18:12 -0400
commit36f41f8fc6d8aa9f8c9072d66ff7cf9055f5e69b (patch)
tree0360c2ff1fd2e000c9e46f21faddfd3773845850 /net/key
parent539a06baedd06127389b254f6b9f016ca072da13 (diff)
af_key: do not use GFP_KERNEL in atomic contexts
pfkey_broadcast() might be called from non process contexts, we can not use GFP_KERNEL in these cases [1]. This patch partially reverts commit ba51b6be38c1 ("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: ba51b6be38c1 ("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>
Diffstat (limited to 'net/key')
-rw-r--r--net/key/af_key.c48
1 files changed, 26 insertions, 22 deletions
diff --git a/net/key/af_key.c b/net/key/af_key.c
index ca9d3ae665e7..98f4d8211b9a 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -228,7 +228,7 @@ static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2,
228#define BROADCAST_ONE 1 228#define BROADCAST_ONE 1
229#define BROADCAST_REGISTERED 2 229#define BROADCAST_REGISTERED 2
230#define BROADCAST_PROMISC_ONLY 4 230#define BROADCAST_PROMISC_ONLY 4
231static int pfkey_broadcast(struct sk_buff *skb, 231static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
232 int broadcast_flags, struct sock *one_sk, 232 int broadcast_flags, struct sock *one_sk,
233 struct net *net) 233 struct net *net)
234{ 234{
@@ -278,7 +278,7 @@ static int pfkey_broadcast(struct sk_buff *skb,
278 rcu_read_unlock(); 278 rcu_read_unlock();
279 279
280 if (one_sk != NULL) 280 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);
282 282
283 kfree_skb(skb2); 283 kfree_skb(skb2);
284 kfree_skb(skb); 284 kfree_skb(skb);
@@ -311,7 +311,7 @@ static int pfkey_do_dump(struct pfkey_sock *pfk)
311 hdr = (struct sadb_msg *) pfk->dump.skb->data; 311 hdr = (struct sadb_msg *) pfk->dump.skb->data;
312 hdr->sadb_msg_seq = 0; 312 hdr->sadb_msg_seq = 0;
313 hdr->sadb_msg_errno = rc; 313 hdr->sadb_msg_errno = rc;
314 pfkey_broadcast(pfk->dump.skb, BROADCAST_ONE, 314 pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE,
315 &pfk->sk, sock_net(&pfk->sk)); 315 &pfk->sk, sock_net(&pfk->sk));
316 pfk->dump.skb = NULL; 316 pfk->dump.skb = NULL;
317 } 317 }
@@ -355,7 +355,7 @@ static int pfkey_error(const struct sadb_msg *orig, int err, struct sock *sk)
355 hdr->sadb_msg_len = (sizeof(struct sadb_msg) / 355 hdr->sadb_msg_len = (sizeof(struct sadb_msg) /
356 sizeof(uint64_t)); 356 sizeof(uint64_t));
357 357
358 pfkey_broadcast(skb, BROADCAST_ONE, sk, sock_net(sk)); 358 pfkey_broadcast(skb, GFP_KERNEL, BROADCAST_ONE, sk, sock_net(sk));
359 359
360 return 0; 360 return 0;
361} 361}
@@ -1389,7 +1389,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, const struct sadb_
1389 1389
1390 xfrm_state_put(x); 1390 xfrm_state_put(x);
1391 1391
1392 pfkey_broadcast(resp_skb, BROADCAST_ONE, sk, net); 1392 pfkey_broadcast(resp_skb, GFP_KERNEL, BROADCAST_ONE, sk, net);
1393 1393
1394 return 0; 1394 return 0;
1395} 1395}
@@ -1476,7 +1476,7 @@ static int key_notify_sa(struct xfrm_state *x, const struct km_event *c)
1476 hdr->sadb_msg_seq = c->seq; 1476 hdr->sadb_msg_seq = c->seq;
1477 hdr->sadb_msg_pid = c->portid; 1477 hdr->sadb_msg_pid = c->portid;
1478 1478
1479 pfkey_broadcast(skb, BROADCAST_ALL, NULL, xs_net(x)); 1479 pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, xs_net(x));
1480 1480
1481 return 0; 1481 return 0;
1482} 1482}
@@ -1589,7 +1589,7 @@ static int pfkey_get(struct sock *sk, struct sk_buff *skb, const struct sadb_msg
1589 out_hdr->sadb_msg_reserved = 0; 1589 out_hdr->sadb_msg_reserved = 0;
1590 out_hdr->sadb_msg_seq = hdr->sadb_msg_seq; 1590 out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;
1591 out_hdr->sadb_msg_pid = hdr->sadb_msg_pid; 1591 out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;
1592 pfkey_broadcast(out_skb, BROADCAST_ONE, sk, sock_net(sk)); 1592 pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, sk, sock_net(sk));
1593 1593
1594 return 0; 1594 return 0;
1595} 1595}
@@ -1694,8 +1694,8 @@ static int pfkey_register(struct sock *sk, struct sk_buff *skb, const struct sad
1694 return -ENOBUFS; 1694 return -ENOBUFS;
1695 } 1695 }
1696 1696
1697 pfkey_broadcast(supp_skb, BROADCAST_REGISTERED, sk, sock_net(sk)); 1697 pfkey_broadcast(supp_skb, GFP_KERNEL, BROADCAST_REGISTERED, sk,
1698 1698 sock_net(sk));
1699 return 0; 1699 return 0;
1700} 1700}
1701 1701
@@ -1712,7 +1712,8 @@ static int unicast_flush_resp(struct sock *sk, const struct sadb_msg *ihdr)
1712 hdr->sadb_msg_errno = (uint8_t) 0; 1712 hdr->sadb_msg_errno = (uint8_t) 0;
1713 hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); 1713 hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
1714 1714
1715 return pfkey_broadcast(skb, BROADCAST_ONE, sk, sock_net(sk)); 1715 return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ONE, sk,
1716 sock_net(sk));
1716} 1717}
1717 1718
1718static int key_notify_sa_flush(const struct km_event *c) 1719static int key_notify_sa_flush(const struct km_event *c)
@@ -1733,7 +1734,7 @@ static int key_notify_sa_flush(const struct km_event *c)
1733 hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); 1734 hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
1734 hdr->sadb_msg_reserved = 0; 1735 hdr->sadb_msg_reserved = 0;
1735 1736
1736 pfkey_broadcast(skb, BROADCAST_ALL, NULL, c->net); 1737 pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net);
1737 1738
1738 return 0; 1739 return 0;
1739} 1740}
@@ -1790,7 +1791,7 @@ static int dump_sa(struct xfrm_state *x, int count, void *ptr)
1790 out_hdr->sadb_msg_pid = pfk->dump.msg_portid; 1791 out_hdr->sadb_msg_pid = pfk->dump.msg_portid;
1791 1792
1792 if (pfk->dump.skb) 1793 if (pfk->dump.skb)
1793 pfkey_broadcast(pfk->dump.skb, BROADCAST_ONE, 1794 pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE,
1794 &pfk->sk, sock_net(&pfk->sk)); 1795 &pfk->sk, sock_net(&pfk->sk));
1795 pfk->dump.skb = out_skb; 1796 pfk->dump.skb = out_skb;
1796 1797
@@ -1878,7 +1879,7 @@ static int pfkey_promisc(struct sock *sk, struct sk_buff *skb, const struct sadb
1878 new_hdr->sadb_msg_errno = 0; 1879 new_hdr->sadb_msg_errno = 0;
1879 } 1880 }
1880 1881
1881 pfkey_broadcast(skb, BROADCAST_ALL, NULL, sock_net(sk)); 1882 pfkey_broadcast(skb, GFP_KERNEL, BROADCAST_ALL, NULL, sock_net(sk));
1882 return 0; 1883 return 0;
1883} 1884}
1884 1885
@@ -2206,7 +2207,7 @@ static int key_notify_policy(struct xfrm_policy *xp, int dir, const struct km_ev
2206 out_hdr->sadb_msg_errno = 0; 2207 out_hdr->sadb_msg_errno = 0;
2207 out_hdr->sadb_msg_seq = c->seq; 2208 out_hdr->sadb_msg_seq = c->seq;
2208 out_hdr->sadb_msg_pid = c->portid; 2209 out_hdr->sadb_msg_pid = c->portid;
2209 pfkey_broadcast(out_skb, BROADCAST_ALL, NULL, xp_net(xp)); 2210 pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, NULL, xp_net(xp));
2210 return 0; 2211 return 0;
2211 2212
2212} 2213}
@@ -2426,7 +2427,7 @@ static int key_pol_get_resp(struct sock *sk, struct xfrm_policy *xp, const struc
2426 out_hdr->sadb_msg_errno = 0; 2427 out_hdr->sadb_msg_errno = 0;
2427 out_hdr->sadb_msg_seq = hdr->sadb_msg_seq; 2428 out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;
2428 out_hdr->sadb_msg_pid = hdr->sadb_msg_pid; 2429 out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;
2429 pfkey_broadcast(out_skb, BROADCAST_ONE, sk, xp_net(xp)); 2430 pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, sk, xp_net(xp));
2430 err = 0; 2431 err = 0;
2431 2432
2432out: 2433out:
@@ -2682,7 +2683,7 @@ static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr)
2682 out_hdr->sadb_msg_pid = pfk->dump.msg_portid; 2683 out_hdr->sadb_msg_pid = pfk->dump.msg_portid;
2683 2684
2684 if (pfk->dump.skb) 2685 if (pfk->dump.skb)
2685 pfkey_broadcast(pfk->dump.skb, BROADCAST_ONE, 2686 pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE,
2686 &pfk->sk, sock_net(&pfk->sk)); 2687 &pfk->sk, sock_net(&pfk->sk));
2687 pfk->dump.skb = out_skb; 2688 pfk->dump.skb = out_skb;
2688 2689
@@ -2739,7 +2740,7 @@ static int key_notify_policy_flush(const struct km_event *c)
2739 hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC; 2740 hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC;
2740 hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); 2741 hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
2741 hdr->sadb_msg_reserved = 0; 2742 hdr->sadb_msg_reserved = 0;
2742 pfkey_broadcast(skb_out, BROADCAST_ALL, NULL, c->net); 2743 pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net);
2743 return 0; 2744 return 0;
2744 2745
2745} 2746}
@@ -2803,7 +2804,7 @@ static int pfkey_process(struct sock *sk, struct sk_buff *skb, const struct sadb
2803 void *ext_hdrs[SADB_EXT_MAX]; 2804 void *ext_hdrs[SADB_EXT_MAX];
2804 int err; 2805 int err;
2805 2806
2806 pfkey_broadcast(skb_clone(skb, GFP_KERNEL), 2807 pfkey_broadcast(skb_clone(skb, GFP_KERNEL), GFP_KERNEL,
2807 BROADCAST_PROMISC_ONLY, NULL, sock_net(sk)); 2808 BROADCAST_PROMISC_ONLY, NULL, sock_net(sk));
2808 2809
2809 memset(ext_hdrs, 0, sizeof(ext_hdrs)); 2810 memset(ext_hdrs, 0, sizeof(ext_hdrs));
@@ -3024,7 +3025,8 @@ static int key_notify_sa_expire(struct xfrm_state *x, const struct km_event *c)
3024 out_hdr->sadb_msg_seq = 0; 3025 out_hdr->sadb_msg_seq = 0;
3025 out_hdr->sadb_msg_pid = 0; 3026 out_hdr->sadb_msg_pid = 0;
3026 3027
3027 pfkey_broadcast(out_skb, BROADCAST_REGISTERED, NULL, xs_net(x)); 3028 pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL,
3029 xs_net(x));
3028 return 0; 3030 return 0;
3029} 3031}
3030 3032
@@ -3212,7 +3214,8 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct
3212 xfrm_ctx->ctx_len); 3214 xfrm_ctx->ctx_len);
3213 } 3215 }
3214 3216
3215 return pfkey_broadcast(skb, BROADCAST_REGISTERED, NULL, xs_net(x)); 3217 return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL,
3218 xs_net(x));
3216} 3219}
3217 3220
3218static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt, 3221static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt,
@@ -3408,7 +3411,8 @@ static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr,
3408 n_port->sadb_x_nat_t_port_port = sport; 3411 n_port->sadb_x_nat_t_port_port = sport;
3409 n_port->sadb_x_nat_t_port_reserved = 0; 3412 n_port->sadb_x_nat_t_port_reserved = 0;
3410 3413
3411 return pfkey_broadcast(skb, BROADCAST_REGISTERED, NULL, xs_net(x)); 3414 return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL,
3415 xs_net(x));
3412} 3416}
3413 3417
3414#ifdef CONFIG_NET_KEY_MIGRATE 3418#ifdef CONFIG_NET_KEY_MIGRATE
@@ -3599,7 +3603,7 @@ static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
3599 } 3603 }
3600 3604
3601 /* broadcast migrate message to sockets */ 3605 /* broadcast migrate message to sockets */
3602 pfkey_broadcast(skb, BROADCAST_ALL, NULL, &init_net); 3606 pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, &init_net);
3603 3607
3604 return 0; 3608 return 0;
3605 3609