Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'l2tp-races'

Cong Wang says:

====================
l2tp: fix race conditions in l2tp_tunnel_register()

This patchset contains two patches, the first one is a preparation for
the second one which is the actual fix. Please find more details in
each patch description.

I have ran the l2tp test (https://github.com/katalix/l2tp-ktest),
all test cases are passed.

v3: preserve EEXIST errno for user-space
v2: move IDR allocation to l2tp_tunnel_register()
====================

Signed-off-by: David S. Miller <davem@davemloft.net>

+52 -53
+52 -53
net/l2tp/l2tp_core.c
··· 104 104 /* per-net private data for this module */ 105 105 static unsigned int l2tp_net_id; 106 106 struct l2tp_net { 107 - struct list_head l2tp_tunnel_list; 108 - /* Lock for write access to l2tp_tunnel_list */ 109 - spinlock_t l2tp_tunnel_list_lock; 107 + /* Lock for write access to l2tp_tunnel_idr */ 108 + spinlock_t l2tp_tunnel_idr_lock; 109 + struct idr l2tp_tunnel_idr; 110 110 struct hlist_head l2tp_session_hlist[L2TP_HASH_SIZE_2]; 111 111 /* Lock for write access to l2tp_session_hlist */ 112 112 spinlock_t l2tp_session_hlist_lock; ··· 208 208 struct l2tp_tunnel *tunnel; 209 209 210 210 rcu_read_lock_bh(); 211 - list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) { 212 - if (tunnel->tunnel_id == tunnel_id && 213 - refcount_inc_not_zero(&tunnel->ref_count)) { 214 - rcu_read_unlock_bh(); 215 - 216 - return tunnel; 217 - } 211 + tunnel = idr_find(&pn->l2tp_tunnel_idr, tunnel_id); 212 + if (tunnel && refcount_inc_not_zero(&tunnel->ref_count)) { 213 + rcu_read_unlock_bh(); 214 + return tunnel; 218 215 } 219 216 rcu_read_unlock_bh(); 220 217 ··· 221 224 222 225 struct l2tp_tunnel *l2tp_tunnel_get_nth(const struct net *net, int nth) 223 226 { 224 - const struct l2tp_net *pn = l2tp_pernet(net); 227 + struct l2tp_net *pn = l2tp_pernet(net); 228 + unsigned long tunnel_id, tmp; 225 229 struct l2tp_tunnel *tunnel; 226 230 int count = 0; 227 231 228 232 rcu_read_lock_bh(); 229 - list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) { 230 - if (++count > nth && 233 + idr_for_each_entry_ul(&pn->l2tp_tunnel_idr, tunnel, tmp, tunnel_id) { 234 + if (tunnel && ++count > nth && 231 235 refcount_inc_not_zero(&tunnel->ref_count)) { 232 236 rcu_read_unlock_bh(); 233 237 return tunnel; ··· 1041 1043 IPCB(skb)->flags &= ~(IPSKB_XFRM_TUNNEL_SIZE | IPSKB_XFRM_TRANSFORMED | IPSKB_REROUTED); 1042 1044 nf_reset_ct(skb); 1043 1045 1044 - bh_lock_sock(sk); 1046 + bh_lock_sock_nested(sk); 1045 1047 if (sock_owned_by_user(sk)) { 1046 1048 kfree_skb(skb); 1047 1049 ret = NET_XMIT_DROP; ··· 1225 1227 l2tp_tunnel_delete(tunnel); 1226 1228 } 1227 1229 1230 + static void l2tp_tunnel_remove(struct net *net, struct l2tp_tunnel *tunnel) 1231 + { 1232 + struct l2tp_net *pn = l2tp_pernet(net); 1233 + 1234 + spin_lock_bh(&pn->l2tp_tunnel_idr_lock); 1235 + idr_remove(&pn->l2tp_tunnel_idr, tunnel->tunnel_id); 1236 + spin_unlock_bh(&pn->l2tp_tunnel_idr_lock); 1237 + } 1238 + 1228 1239 /* Workqueue tunnel deletion function */ 1229 1240 static void l2tp_tunnel_del_work(struct work_struct *work) 1230 1241 { ··· 1241 1234 del_work); 1242 1235 struct sock *sk = tunnel->sock; 1243 1236 struct socket *sock = sk->sk_socket; 1244 - struct l2tp_net *pn; 1245 1237 1246 1238 l2tp_tunnel_closeall(tunnel); 1247 1239 ··· 1254 1248 } 1255 1249 } 1256 1250 1257 - /* Remove the tunnel struct from the tunnel list */ 1258 - pn = l2tp_pernet(tunnel->l2tp_net); 1259 - spin_lock_bh(&pn->l2tp_tunnel_list_lock); 1260 - list_del_rcu(&tunnel->list); 1261 - spin_unlock_bh(&pn->l2tp_tunnel_list_lock); 1262 - 1251 + l2tp_tunnel_remove(tunnel->l2tp_net, tunnel); 1263 1252 /* drop initial ref */ 1264 1253 l2tp_tunnel_dec_refcount(tunnel); 1265 1254 ··· 1385 1384 return err; 1386 1385 } 1387 1386 1388 - static struct lock_class_key l2tp_socket_class; 1389 - 1390 1387 int l2tp_tunnel_create(int fd, int version, u32 tunnel_id, u32 peer_tunnel_id, 1391 1388 struct l2tp_tunnel_cfg *cfg, struct l2tp_tunnel **tunnelp) 1392 1389 { ··· 1454 1455 int l2tp_tunnel_register(struct l2tp_tunnel *tunnel, struct net *net, 1455 1456 struct l2tp_tunnel_cfg *cfg) 1456 1457 { 1457 - struct l2tp_tunnel *tunnel_walk; 1458 - struct l2tp_net *pn; 1458 + struct l2tp_net *pn = l2tp_pernet(net); 1459 + u32 tunnel_id = tunnel->tunnel_id; 1459 1460 struct socket *sock; 1460 1461 struct sock *sk; 1461 1462 int ret; 1463 + 1464 + spin_lock_bh(&pn->l2tp_tunnel_idr_lock); 1465 + ret = idr_alloc_u32(&pn->l2tp_tunnel_idr, NULL, &tunnel_id, tunnel_id, 1466 + GFP_ATOMIC); 1467 + spin_unlock_bh(&pn->l2tp_tunnel_idr_lock); 1468 + if (ret) 1469 + return ret == -ENOSPC ? -EEXIST : ret; 1462 1470 1463 1471 if (tunnel->fd < 0) { 1464 1472 ret = l2tp_tunnel_sock_create(net, tunnel->tunnel_id, ··· 1480 1474 } 1481 1475 1482 1476 sk = sock->sk; 1477 + lock_sock(sk); 1483 1478 write_lock_bh(&sk->sk_callback_lock); 1484 1479 ret = l2tp_validate_socket(sk, net, tunnel->encap); 1485 - if (ret < 0) 1480 + if (ret < 0) { 1481 + release_sock(sk); 1486 1482 goto err_inval_sock; 1483 + } 1487 1484 rcu_assign_sk_user_data(sk, tunnel); 1488 1485 write_unlock_bh(&sk->sk_callback_lock); 1489 - 1490 - tunnel->l2tp_net = net; 1491 - pn = l2tp_pernet(net); 1492 - 1493 - sock_hold(sk); 1494 - tunnel->sock = sk; 1495 - 1496 - spin_lock_bh(&pn->l2tp_tunnel_list_lock); 1497 - list_for_each_entry(tunnel_walk, &pn->l2tp_tunnel_list, list) { 1498 - if (tunnel_walk->tunnel_id == tunnel->tunnel_id) { 1499 - spin_unlock_bh(&pn->l2tp_tunnel_list_lock); 1500 - sock_put(sk); 1501 - ret = -EEXIST; 1502 - goto err_sock; 1503 - } 1504 - } 1505 - list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list); 1506 - spin_unlock_bh(&pn->l2tp_tunnel_list_lock); 1507 1486 1508 1487 if (tunnel->encap == L2TP_ENCAPTYPE_UDP) { 1509 1488 struct udp_tunnel_sock_cfg udp_cfg = { ··· 1503 1512 1504 1513 tunnel->old_sk_destruct = sk->sk_destruct; 1505 1514 sk->sk_destruct = &l2tp_tunnel_destruct; 1506 - lockdep_set_class_and_name(&sk->sk_lock.slock, &l2tp_socket_class, 1507 - "l2tp_sock"); 1508 1515 sk->sk_allocation = GFP_ATOMIC; 1516 + release_sock(sk); 1517 + 1518 + sock_hold(sk); 1519 + tunnel->sock = sk; 1520 + tunnel->l2tp_net = net; 1521 + 1522 + spin_lock_bh(&pn->l2tp_tunnel_idr_lock); 1523 + idr_replace(&pn->l2tp_tunnel_idr, tunnel, tunnel->tunnel_id); 1524 + spin_unlock_bh(&pn->l2tp_tunnel_idr_lock); 1509 1525 1510 1526 trace_register_tunnel(tunnel); 1511 1527 ··· 1521 1523 1522 1524 return 0; 1523 1525 1524 - err_sock: 1525 - write_lock_bh(&sk->sk_callback_lock); 1526 - rcu_assign_sk_user_data(sk, NULL); 1527 1526 err_inval_sock: 1528 1527 write_unlock_bh(&sk->sk_callback_lock); 1529 1528 ··· 1529 1534 else 1530 1535 sockfd_put(sock); 1531 1536 err: 1537 + l2tp_tunnel_remove(net, tunnel); 1532 1538 return ret; 1533 1539 } 1534 1540 EXPORT_SYMBOL_GPL(l2tp_tunnel_register); ··· 1643 1647 struct l2tp_net *pn = net_generic(net, l2tp_net_id); 1644 1648 int hash; 1645 1649 1646 - INIT_LIST_HEAD(&pn->l2tp_tunnel_list); 1647 - spin_lock_init(&pn->l2tp_tunnel_list_lock); 1650 + idr_init(&pn->l2tp_tunnel_idr); 1651 + spin_lock_init(&pn->l2tp_tunnel_idr_lock); 1648 1652 1649 1653 for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++) 1650 1654 INIT_HLIST_HEAD(&pn->l2tp_session_hlist[hash]); ··· 1658 1662 { 1659 1663 struct l2tp_net *pn = l2tp_pernet(net); 1660 1664 struct l2tp_tunnel *tunnel = NULL; 1665 + unsigned long tunnel_id, tmp; 1661 1666 int hash; 1662 1667 1663 1668 rcu_read_lock_bh(); 1664 - list_for_each_entry_rcu(tunnel, &pn->l2tp_tunnel_list, list) { 1665 - l2tp_tunnel_delete(tunnel); 1669 + idr_for_each_entry_ul(&pn->l2tp_tunnel_idr, tunnel, tmp, tunnel_id) { 1670 + if (tunnel) 1671 + l2tp_tunnel_delete(tunnel); 1666 1672 } 1667 1673 rcu_read_unlock_bh(); 1668 1674 ··· 1674 1676 1675 1677 for (hash = 0; hash < L2TP_HASH_SIZE_2; hash++) 1676 1678 WARN_ON_ONCE(!hlist_empty(&pn->l2tp_session_hlist[hash])); 1679 + idr_destroy(&pn->l2tp_tunnel_idr); 1677 1680 } 1678 1681 1679 1682 static struct pernet_operations l2tp_net_ops = {