aboutsummaryrefslogtreecommitdiffstats
path: root/net/key
diff options
context:
space:
mode:
authorDavid Ahern <dsa@cumulusnetworks.com>2015-08-24 17:17:17 -0400
committerDavid S. Miller <davem@davemloft.net>2015-08-24 17:48:10 -0400
commitba51b6be38c122f7dab40965b4397aaf6188a464 (patch)
tree0a6558d48be086558e55f083261148f55632c61a /net/key
parentb6df7d61c8776a882dd47ba4714d1445dd7ef2d9 (diff)
net: Fix RCU splat in af_key
Hit the following splat testing VRF change for ipsec: [ 113.475692] =============================== [ 113.476194] [ INFO: suspicious RCU usage. ] [ 113.476667] 4.2.0-rc6-1+deb7u2+clUNRELEASED #3.2.65-1+deb7u2+clUNRELEASED Not tainted [ 113.477545] ------------------------------- [ 113.478013] /work/monster-14/dsa/kernel.git/include/linux/rcupdate.h:568 Illegal context switch in RCU read-side critical section! [ 113.479288] [ 113.479288] other info that might help us debug this: [ 113.479288] [ 113.480207] [ 113.480207] rcu_scheduler_active = 1, debug_locks = 1 [ 113.480931] 2 locks held by setkey/6829: [ 113.481371] #0: (&net->xfrm.xfrm_cfg_mutex){+.+.+.}, at: [<ffffffff814e9887>] pfkey_sendmsg+0xfb/0x213 [ 113.482509] #1: (rcu_read_lock){......}, at: [<ffffffff814e767f>] rcu_read_lock+0x0/0x6e [ 113.483509] [ 113.483509] stack backtrace: [ 113.484041] CPU: 0 PID: 6829 Comm: setkey Not tainted 4.2.0-rc6-1+deb7u2+clUNRELEASED #3.2.65-1+deb7u2+clUNRELEASED [ 113.485422] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.7.5.1-0-g8936dbb-20141113_115728-nilsson.home.kraxel.org 04/01/2014 [ 113.486845] 0000000000000001 ffff88001d4c7a98 ffffffff81518af2 ffffffff81086962 [ 113.487732] ffff88001d538480 ffff88001d4c7ac8 ffffffff8107ae75 ffffffff8180a154 [ 113.488628] 0000000000000b30 0000000000000000 00000000000000d0 ffff88001d4c7ad8 [ 113.489525] Call Trace: [ 113.489813] [<ffffffff81518af2>] dump_stack+0x4c/0x65 [ 113.490389] [<ffffffff81086962>] ? console_unlock+0x3d6/0x405 [ 113.491039] [<ffffffff8107ae75>] lockdep_rcu_suspicious+0xfa/0x103 [ 113.491735] [<ffffffff81064032>] rcu_preempt_sleep_check+0x45/0x47 [ 113.492442] [<ffffffff8106404d>] ___might_sleep+0x19/0x1c8 [ 113.493077] [<ffffffff81064268>] __might_sleep+0x6c/0x82 [ 113.493681] [<ffffffff81133190>] cache_alloc_debugcheck_before.isra.50+0x1d/0x24 [ 113.494508] [<ffffffff81134876>] kmem_cache_alloc+0x31/0x18f [ 113.495149] [<ffffffff814012b5>] skb_clone+0x64/0x80 [ 113.495712] [<ffffffff814e6f71>] pfkey_broadcast_one+0x3d/0xff [ 113.496380] [<ffffffff814e7b84>] pfkey_broadcast+0xb5/0x11e [ 113.497024] [<ffffffff814e82d1>] pfkey_register+0x191/0x1b1 [ 113.497653] [<ffffffff814e9770>] pfkey_process+0x162/0x17e [ 113.498274] [<ffffffff814e9895>] pfkey_sendmsg+0x109/0x213 In pfkey_sendmsg the net mutex is taken and then pfkey_broadcast takes the RCU lock. Since pfkey_broadcast takes the RCU lock the allocation argument is pointless since GFP_ATOMIC must be used between the rcu_read_{,un}lock. The one call outside of rcu can be done with GFP_KERNEL. Fixes: 7f6b9dbd5afbd ("af_key: locking change") Signed-off-by: David Ahern <dsa@cumulusnetworks.com> Acked-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/key')
-rw-r--r--net/key/af_key.c46
1 files changed, 23 insertions, 23 deletions
diff --git a/net/key/af_key.c b/net/key/af_key.c
index b397f0aa9005..83a70688784b 100644
--- a/net/key/af_key.c
+++ b/net/key/af_key.c
@@ -219,7 +219,7 @@ static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2,
219#define BROADCAST_ONE 1 219#define BROADCAST_ONE 1
220#define BROADCAST_REGISTERED 2 220#define BROADCAST_REGISTERED 2
221#define BROADCAST_PROMISC_ONLY 4 221#define BROADCAST_PROMISC_ONLY 4
222static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation, 222static int pfkey_broadcast(struct sk_buff *skb,
223 int broadcast_flags, struct sock *one_sk, 223 int broadcast_flags, struct sock *one_sk,
224 struct net *net) 224 struct net *net)
225{ 225{
@@ -244,7 +244,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
244 * socket. 244 * socket.
245 */ 245 */
246 if (pfk->promisc) 246 if (pfk->promisc)
247 pfkey_broadcast_one(skb, &skb2, allocation, sk); 247 pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk);
248 248
249 /* the exact target will be processed later */ 249 /* the exact target will be processed later */
250 if (sk == one_sk) 250 if (sk == one_sk)
@@ -259,7 +259,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
259 continue; 259 continue;
260 } 260 }
261 261
262 err2 = pfkey_broadcast_one(skb, &skb2, allocation, sk); 262 err2 = pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk);
263 263
264 /* Error is cleare after succecful sending to at least one 264 /* Error is cleare after succecful sending to at least one
265 * registered KM */ 265 * registered KM */
@@ -269,7 +269,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
269 rcu_read_unlock(); 269 rcu_read_unlock();
270 270
271 if (one_sk != NULL) 271 if (one_sk != NULL)
272 err = pfkey_broadcast_one(skb, &skb2, allocation, one_sk); 272 err = pfkey_broadcast_one(skb, &skb2, GFP_KERNEL, one_sk);
273 273
274 kfree_skb(skb2); 274 kfree_skb(skb2);
275 kfree_skb(skb); 275 kfree_skb(skb);
@@ -292,7 +292,7 @@ static int pfkey_do_dump(struct pfkey_sock *pfk)
292 hdr = (struct sadb_msg *) pfk->dump.skb->data; 292 hdr = (struct sadb_msg *) pfk->dump.skb->data;
293 hdr->sadb_msg_seq = 0; 293 hdr->sadb_msg_seq = 0;
294 hdr->sadb_msg_errno = rc; 294 hdr->sadb_msg_errno = rc;
295 pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE, 295 pfkey_broadcast(pfk->dump.skb, BROADCAST_ONE,
296 &pfk->sk, sock_net(&pfk->sk)); 296 &pfk->sk, sock_net(&pfk->sk));
297 pfk->dump.skb = NULL; 297 pfk->dump.skb = NULL;
298 } 298 }
@@ -333,7 +333,7 @@ static int pfkey_error(const struct sadb_msg *orig, int err, struct sock *sk)
333 hdr->sadb_msg_len = (sizeof(struct sadb_msg) / 333 hdr->sadb_msg_len = (sizeof(struct sadb_msg) /
334 sizeof(uint64_t)); 334 sizeof(uint64_t));
335 335
336 pfkey_broadcast(skb, GFP_KERNEL, BROADCAST_ONE, sk, sock_net(sk)); 336 pfkey_broadcast(skb, BROADCAST_ONE, sk, sock_net(sk));
337 337
338 return 0; 338 return 0;
339} 339}
@@ -1365,7 +1365,7 @@ static int pfkey_getspi(struct sock *sk, struct sk_buff *skb, const struct sadb_
1365 1365
1366 xfrm_state_put(x); 1366 xfrm_state_put(x);
1367 1367
1368 pfkey_broadcast(resp_skb, GFP_KERNEL, BROADCAST_ONE, sk, net); 1368 pfkey_broadcast(resp_skb, BROADCAST_ONE, sk, net);
1369 1369
1370 return 0; 1370 return 0;
1371} 1371}
@@ -1452,7 +1452,7 @@ static int key_notify_sa(struct xfrm_state *x, const struct km_event *c)
1452 hdr->sadb_msg_seq = c->seq; 1452 hdr->sadb_msg_seq = c->seq;
1453 hdr->sadb_msg_pid = c->portid; 1453 hdr->sadb_msg_pid = c->portid;
1454 1454
1455 pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, xs_net(x)); 1455 pfkey_broadcast(skb, BROADCAST_ALL, NULL, xs_net(x));
1456 1456
1457 return 0; 1457 return 0;
1458} 1458}
@@ -1565,7 +1565,7 @@ static int pfkey_get(struct sock *sk, struct sk_buff *skb, const struct sadb_msg
1565 out_hdr->sadb_msg_reserved = 0; 1565 out_hdr->sadb_msg_reserved = 0;
1566 out_hdr->sadb_msg_seq = hdr->sadb_msg_seq; 1566 out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;
1567 out_hdr->sadb_msg_pid = hdr->sadb_msg_pid; 1567 out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;
1568 pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, sk, sock_net(sk)); 1568 pfkey_broadcast(out_skb, BROADCAST_ONE, sk, sock_net(sk));
1569 1569
1570 return 0; 1570 return 0;
1571} 1571}
@@ -1670,7 +1670,7 @@ static int pfkey_register(struct sock *sk, struct sk_buff *skb, const struct sad
1670 return -ENOBUFS; 1670 return -ENOBUFS;
1671 } 1671 }
1672 1672
1673 pfkey_broadcast(supp_skb, GFP_KERNEL, BROADCAST_REGISTERED, sk, sock_net(sk)); 1673 pfkey_broadcast(supp_skb, BROADCAST_REGISTERED, sk, sock_net(sk));
1674 1674
1675 return 0; 1675 return 0;
1676} 1676}
@@ -1689,7 +1689,7 @@ static int unicast_flush_resp(struct sock *sk, const struct sadb_msg *ihdr)
1689 hdr->sadb_msg_errno = (uint8_t) 0; 1689 hdr->sadb_msg_errno = (uint8_t) 0;
1690 hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); 1690 hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
1691 1691
1692 return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ONE, sk, sock_net(sk)); 1692 return pfkey_broadcast(skb, BROADCAST_ONE, sk, sock_net(sk));
1693} 1693}
1694 1694
1695static int key_notify_sa_flush(const struct km_event *c) 1695static int key_notify_sa_flush(const struct km_event *c)
@@ -1710,7 +1710,7 @@ static int key_notify_sa_flush(const struct km_event *c)
1710 hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); 1710 hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
1711 hdr->sadb_msg_reserved = 0; 1711 hdr->sadb_msg_reserved = 0;
1712 1712
1713 pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net); 1713 pfkey_broadcast(skb, BROADCAST_ALL, NULL, c->net);
1714 1714
1715 return 0; 1715 return 0;
1716} 1716}
@@ -1767,7 +1767,7 @@ static int dump_sa(struct xfrm_state *x, int count, void *ptr)
1767 out_hdr->sadb_msg_pid = pfk->dump.msg_portid; 1767 out_hdr->sadb_msg_pid = pfk->dump.msg_portid;
1768 1768
1769 if (pfk->dump.skb) 1769 if (pfk->dump.skb)
1770 pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE, 1770 pfkey_broadcast(pfk->dump.skb, BROADCAST_ONE,
1771 &pfk->sk, sock_net(&pfk->sk)); 1771 &pfk->sk, sock_net(&pfk->sk));
1772 pfk->dump.skb = out_skb; 1772 pfk->dump.skb = out_skb;
1773 1773
@@ -1847,7 +1847,7 @@ static int pfkey_promisc(struct sock *sk, struct sk_buff *skb, const struct sadb
1847 new_hdr->sadb_msg_errno = 0; 1847 new_hdr->sadb_msg_errno = 0;
1848 } 1848 }
1849 1849
1850 pfkey_broadcast(skb, GFP_KERNEL, BROADCAST_ALL, NULL, sock_net(sk)); 1850 pfkey_broadcast(skb, BROADCAST_ALL, NULL, sock_net(sk));
1851 return 0; 1851 return 0;
1852} 1852}
1853 1853
@@ -2181,7 +2181,7 @@ static int key_notify_policy(struct xfrm_policy *xp, int dir, const struct km_ev
2181 out_hdr->sadb_msg_errno = 0; 2181 out_hdr->sadb_msg_errno = 0;
2182 out_hdr->sadb_msg_seq = c->seq; 2182 out_hdr->sadb_msg_seq = c->seq;
2183 out_hdr->sadb_msg_pid = c->portid; 2183 out_hdr->sadb_msg_pid = c->portid;
2184 pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ALL, NULL, xp_net(xp)); 2184 pfkey_broadcast(out_skb, BROADCAST_ALL, NULL, xp_net(xp));
2185 return 0; 2185 return 0;
2186 2186
2187} 2187}
@@ -2401,7 +2401,7 @@ static int key_pol_get_resp(struct sock *sk, struct xfrm_policy *xp, const struc
2401 out_hdr->sadb_msg_errno = 0; 2401 out_hdr->sadb_msg_errno = 0;
2402 out_hdr->sadb_msg_seq = hdr->sadb_msg_seq; 2402 out_hdr->sadb_msg_seq = hdr->sadb_msg_seq;
2403 out_hdr->sadb_msg_pid = hdr->sadb_msg_pid; 2403 out_hdr->sadb_msg_pid = hdr->sadb_msg_pid;
2404 pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_ONE, sk, xp_net(xp)); 2404 pfkey_broadcast(out_skb, BROADCAST_ONE, sk, xp_net(xp));
2405 err = 0; 2405 err = 0;
2406 2406
2407out: 2407out:
@@ -2655,7 +2655,7 @@ static int dump_sp(struct xfrm_policy *xp, int dir, int count, void *ptr)
2655 out_hdr->sadb_msg_pid = pfk->dump.msg_portid; 2655 out_hdr->sadb_msg_pid = pfk->dump.msg_portid;
2656 2656
2657 if (pfk->dump.skb) 2657 if (pfk->dump.skb)
2658 pfkey_broadcast(pfk->dump.skb, GFP_ATOMIC, BROADCAST_ONE, 2658 pfkey_broadcast(pfk->dump.skb, BROADCAST_ONE,
2659 &pfk->sk, sock_net(&pfk->sk)); 2659 &pfk->sk, sock_net(&pfk->sk));
2660 pfk->dump.skb = out_skb; 2660 pfk->dump.skb = out_skb;
2661 2661
@@ -2708,7 +2708,7 @@ static int key_notify_policy_flush(const struct km_event *c)
2708 hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC; 2708 hdr->sadb_msg_satype = SADB_SATYPE_UNSPEC;
2709 hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t)); 2709 hdr->sadb_msg_len = (sizeof(struct sadb_msg) / sizeof(uint64_t));
2710 hdr->sadb_msg_reserved = 0; 2710 hdr->sadb_msg_reserved = 0;
2711 pfkey_broadcast(skb_out, GFP_ATOMIC, BROADCAST_ALL, NULL, c->net); 2711 pfkey_broadcast(skb_out, BROADCAST_ALL, NULL, c->net);
2712 return 0; 2712 return 0;
2713 2713
2714} 2714}
@@ -2770,7 +2770,7 @@ static int pfkey_process(struct sock *sk, struct sk_buff *skb, const struct sadb
2770 void *ext_hdrs[SADB_EXT_MAX]; 2770 void *ext_hdrs[SADB_EXT_MAX];
2771 int err; 2771 int err;
2772 2772
2773 pfkey_broadcast(skb_clone(skb, GFP_KERNEL), GFP_KERNEL, 2773 pfkey_broadcast(skb_clone(skb, GFP_KERNEL),
2774 BROADCAST_PROMISC_ONLY, NULL, sock_net(sk)); 2774 BROADCAST_PROMISC_ONLY, NULL, sock_net(sk));
2775 2775
2776 memset(ext_hdrs, 0, sizeof(ext_hdrs)); 2776 memset(ext_hdrs, 0, sizeof(ext_hdrs));
@@ -2992,7 +2992,7 @@ static int key_notify_sa_expire(struct xfrm_state *x, const struct km_event *c)
2992 out_hdr->sadb_msg_seq = 0; 2992 out_hdr->sadb_msg_seq = 0;
2993 out_hdr->sadb_msg_pid = 0; 2993 out_hdr->sadb_msg_pid = 0;
2994 2994
2995 pfkey_broadcast(out_skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL, xs_net(x)); 2995 pfkey_broadcast(out_skb, BROADCAST_REGISTERED, NULL, xs_net(x));
2996 return 0; 2996 return 0;
2997} 2997}
2998 2998
@@ -3182,7 +3182,7 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct
3182 xfrm_ctx->ctx_len); 3182 xfrm_ctx->ctx_len);
3183 } 3183 }
3184 3184
3185 return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL, xs_net(x)); 3185 return pfkey_broadcast(skb, BROADCAST_REGISTERED, NULL, xs_net(x));
3186} 3186}
3187 3187
3188static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt, 3188static struct xfrm_policy *pfkey_compile_policy(struct sock *sk, int opt,
@@ -3380,7 +3380,7 @@ static int pfkey_send_new_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr,
3380 n_port->sadb_x_nat_t_port_port = sport; 3380 n_port->sadb_x_nat_t_port_port = sport;
3381 n_port->sadb_x_nat_t_port_reserved = 0; 3381 n_port->sadb_x_nat_t_port_reserved = 0;
3382 3382
3383 return pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_REGISTERED, NULL, xs_net(x)); 3383 return pfkey_broadcast(skb, BROADCAST_REGISTERED, NULL, xs_net(x));
3384} 3384}
3385 3385
3386#ifdef CONFIG_NET_KEY_MIGRATE 3386#ifdef CONFIG_NET_KEY_MIGRATE
@@ -3572,7 +3572,7 @@ static int pfkey_send_migrate(const struct xfrm_selector *sel, u8 dir, u8 type,
3572 } 3572 }
3573 3573
3574 /* broadcast migrate message to sockets */ 3574 /* broadcast migrate message to sockets */
3575 pfkey_broadcast(skb, GFP_ATOMIC, BROADCAST_ALL, NULL, &init_net); 3575 pfkey_broadcast(skb, BROADCAST_ALL, NULL, &init_net);
3576 3576
3577 return 0; 3577 return 0;
3578 3578