hc
2024-10-16 50a212ec906f7524620675f0c57357691c26c81f
kernel/net/netlink/af_netlink.c
....@@ -570,7 +570,9 @@
570570 if (nlk_sk(sk)->bound)
571571 goto err;
572572
573
- nlk_sk(sk)->portid = portid;
573
+ /* portid can be read locklessly from netlink_getname(). */
574
+ WRITE_ONCE(nlk_sk(sk)->portid, portid);
575
+
574576 sock_hold(sk);
575577
576578 err = __netlink_insert(table, sk);
....@@ -1079,9 +1081,11 @@
10791081 return -EINVAL;
10801082
10811083 if (addr->sa_family == AF_UNSPEC) {
1082
- sk->sk_state = NETLINK_UNCONNECTED;
1083
- nlk->dst_portid = 0;
1084
- nlk->dst_group = 0;
1084
+ /* paired with READ_ONCE() in netlink_getsockbyportid() */
1085
+ WRITE_ONCE(sk->sk_state, NETLINK_UNCONNECTED);
1086
+ /* dst_portid and dst_group can be read locklessly */
1087
+ WRITE_ONCE(nlk->dst_portid, 0);
1088
+ WRITE_ONCE(nlk->dst_group, 0);
10851089 return 0;
10861090 }
10871091 if (addr->sa_family != AF_NETLINK)
....@@ -1102,9 +1106,11 @@
11021106 err = netlink_autobind(sock);
11031107
11041108 if (err == 0) {
1105
- sk->sk_state = NETLINK_CONNECTED;
1106
- nlk->dst_portid = nladdr->nl_pid;
1107
- nlk->dst_group = ffs(nladdr->nl_groups);
1109
+ /* paired with READ_ONCE() in netlink_getsockbyportid() */
1110
+ WRITE_ONCE(sk->sk_state, NETLINK_CONNECTED);
1111
+ /* dst_portid and dst_group can be read locklessly */
1112
+ WRITE_ONCE(nlk->dst_portid, nladdr->nl_pid);
1113
+ WRITE_ONCE(nlk->dst_group, ffs(nladdr->nl_groups));
11081114 }
11091115
11101116 return err;
....@@ -1121,10 +1127,12 @@
11211127 nladdr->nl_pad = 0;
11221128
11231129 if (peer) {
1124
- nladdr->nl_pid = nlk->dst_portid;
1125
- nladdr->nl_groups = netlink_group_mask(nlk->dst_group);
1130
+ /* Paired with WRITE_ONCE() in netlink_connect() */
1131
+ nladdr->nl_pid = READ_ONCE(nlk->dst_portid);
1132
+ nladdr->nl_groups = netlink_group_mask(READ_ONCE(nlk->dst_group));
11261133 } else {
1127
- nladdr->nl_pid = nlk->portid;
1134
+ /* Paired with WRITE_ONCE() in netlink_insert() */
1135
+ nladdr->nl_pid = READ_ONCE(nlk->portid);
11281136 netlink_lock_table();
11291137 nladdr->nl_groups = nlk->groups ? nlk->groups[0] : 0;
11301138 netlink_unlock_table();
....@@ -1151,8 +1159,9 @@
11511159
11521160 /* Don't bother queuing skb if kernel socket has no input function */
11531161 nlk = nlk_sk(sock);
1154
- if (sock->sk_state == NETLINK_CONNECTED &&
1155
- nlk->dst_portid != nlk_sk(ssk)->portid) {
1162
+ /* dst_portid and sk_state can be changed in netlink_connect() */
1163
+ if (READ_ONCE(sock->sk_state) == NETLINK_CONNECTED &&
1164
+ READ_ONCE(nlk->dst_portid) != nlk_sk(ssk)->portid) {
11561165 sock_put(sock);
11571166 return ERR_PTR(-ECONNREFUSED);
11581167 }
....@@ -1593,6 +1602,7 @@
15931602 int netlink_set_err(struct sock *ssk, u32 portid, u32 group, int code)
15941603 {
15951604 struct netlink_set_err_data info;
1605
+ unsigned long flags;
15961606 struct sock *sk;
15971607 int ret = 0;
15981608
....@@ -1602,12 +1612,12 @@
16021612 /* sk->sk_err wants a positive error value */
16031613 info.code = -code;
16041614
1605
- read_lock(&nl_table_lock);
1615
+ read_lock_irqsave(&nl_table_lock, flags);
16061616
16071617 sk_for_each_bound(sk, &nl_table[ssk->sk_protocol].mc_list)
16081618 ret += do_one_set_err(sk, &info);
16091619
1610
- read_unlock(&nl_table_lock);
1620
+ read_unlock_irqrestore(&nl_table_lock, flags);
16111621 return ret;
16121622 }
16131623 EXPORT_SYMBOL(netlink_set_err);
....@@ -1735,7 +1745,8 @@
17351745 {
17361746 struct sock *sk = sock->sk;
17371747 struct netlink_sock *nlk = nlk_sk(sk);
1738
- int len, val, err;
1748
+ unsigned int flag;
1749
+ int len, val;
17391750
17401751 if (level != SOL_NETLINK)
17411752 return -ENOPROTOOPT;
....@@ -1747,39 +1758,17 @@
17471758
17481759 switch (optname) {
17491760 case NETLINK_PKTINFO:
1750
- if (len < sizeof(int))
1751
- return -EINVAL;
1752
- len = sizeof(int);
1753
- val = nlk->flags & NETLINK_F_RECV_PKTINFO ? 1 : 0;
1754
- if (put_user(len, optlen) ||
1755
- put_user(val, optval))
1756
- return -EFAULT;
1757
- err = 0;
1761
+ flag = NETLINK_F_RECV_PKTINFO;
17581762 break;
17591763 case NETLINK_BROADCAST_ERROR:
1760
- if (len < sizeof(int))
1761
- return -EINVAL;
1762
- len = sizeof(int);
1763
- val = nlk->flags & NETLINK_F_BROADCAST_SEND_ERROR ? 1 : 0;
1764
- if (put_user(len, optlen) ||
1765
- put_user(val, optval))
1766
- return -EFAULT;
1767
- err = 0;
1764
+ flag = NETLINK_F_BROADCAST_SEND_ERROR;
17681765 break;
17691766 case NETLINK_NO_ENOBUFS:
1770
- if (len < sizeof(int))
1771
- return -EINVAL;
1772
- len = sizeof(int);
1773
- val = nlk->flags & NETLINK_F_RECV_NO_ENOBUFS ? 1 : 0;
1774
- if (put_user(len, optlen) ||
1775
- put_user(val, optval))
1776
- return -EFAULT;
1777
- err = 0;
1767
+ flag = NETLINK_F_RECV_NO_ENOBUFS;
17781768 break;
17791769 case NETLINK_LIST_MEMBERSHIPS: {
1780
- int pos, idx, shift;
1770
+ int pos, idx, shift, err = 0;
17811771
1782
- err = 0;
17831772 netlink_lock_table();
17841773 for (pos = 0; pos * 8 < nlk->ngroups; pos += sizeof(u32)) {
17851774 if (len - pos < sizeof(u32))
....@@ -1793,43 +1782,35 @@
17931782 break;
17941783 }
17951784 }
1796
- if (put_user(ALIGN(nlk->ngroups / 8, sizeof(u32)), optlen))
1785
+ if (put_user(ALIGN(BITS_TO_BYTES(nlk->ngroups), sizeof(u32)), optlen))
17971786 err = -EFAULT;
17981787 netlink_unlock_table();
1799
- break;
1788
+ return err;
18001789 }
18011790 case NETLINK_CAP_ACK:
1802
- if (len < sizeof(int))
1803
- return -EINVAL;
1804
- len = sizeof(int);
1805
- val = nlk->flags & NETLINK_F_CAP_ACK ? 1 : 0;
1806
- if (put_user(len, optlen) ||
1807
- put_user(val, optval))
1808
- return -EFAULT;
1809
- err = 0;
1791
+ flag = NETLINK_F_CAP_ACK;
18101792 break;
18111793 case NETLINK_EXT_ACK:
1812
- if (len < sizeof(int))
1813
- return -EINVAL;
1814
- len = sizeof(int);
1815
- val = nlk->flags & NETLINK_F_EXT_ACK ? 1 : 0;
1816
- if (put_user(len, optlen) || put_user(val, optval))
1817
- return -EFAULT;
1818
- err = 0;
1794
+ flag = NETLINK_F_EXT_ACK;
18191795 break;
18201796 case NETLINK_GET_STRICT_CHK:
1821
- if (len < sizeof(int))
1822
- return -EINVAL;
1823
- len = sizeof(int);
1824
- val = nlk->flags & NETLINK_F_STRICT_CHK ? 1 : 0;
1825
- if (put_user(len, optlen) || put_user(val, optval))
1826
- return -EFAULT;
1827
- err = 0;
1797
+ flag = NETLINK_F_STRICT_CHK;
18281798 break;
18291799 default:
1830
- err = -ENOPROTOOPT;
1800
+ return -ENOPROTOOPT;
18311801 }
1832
- return err;
1802
+
1803
+ if (len < sizeof(int))
1804
+ return -EINVAL;
1805
+
1806
+ len = sizeof(int);
1807
+ val = nlk->flags & flag ? 1 : 0;
1808
+
1809
+ if (put_user(len, optlen) ||
1810
+ copy_to_user(optval, &val, len))
1811
+ return -EFAULT;
1812
+
1813
+ return 0;
18331814 }
18341815
18351816 static void netlink_cmsg_recv_pktinfo(struct msghdr *msg, struct sk_buff *skb)
....@@ -1888,8 +1869,9 @@
18881869 goto out;
18891870 netlink_skb_flags |= NETLINK_SKB_DST;
18901871 } else {
1891
- dst_portid = nlk->dst_portid;
1892
- dst_group = nlk->dst_group;
1872
+ /* Paired with WRITE_ONCE() in netlink_connect() */
1873
+ dst_portid = READ_ONCE(nlk->dst_portid);
1874
+ dst_group = READ_ONCE(nlk->dst_group);
18931875 }
18941876
18951877 /* Paired with WRITE_ONCE() in netlink_insert() */
....@@ -2011,7 +1993,7 @@
20111993
20121994 skb_free_datagram(sk, skb);
20131995
2014
- if (nlk->cb_running &&
1996
+ if (READ_ONCE(nlk->cb_running) &&
20151997 atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf / 2) {
20161998 ret = netlink_dump(sk);
20171999 if (ret) {
....@@ -2323,7 +2305,7 @@
23232305 if (cb->done)
23242306 cb->done(cb);
23252307
2326
- nlk->cb_running = false;
2308
+ WRITE_ONCE(nlk->cb_running, false);
23272309 module = cb->module;
23282310 skb = cb->skb;
23292311 mutex_unlock(nlk->cb_mutex);
....@@ -2386,7 +2368,7 @@
23862368 goto error_put;
23872369 }
23882370
2389
- nlk->cb_running = true;
2371
+ WRITE_ONCE(nlk->cb_running, true);
23902372 nlk->dump_done_errno = INT_MAX;
23912373
23922374 mutex_unlock(nlk->cb_mutex);
....@@ -2672,7 +2654,7 @@
26722654 nlk->groups ? (u32)nlk->groups[0] : 0,
26732655 sk_rmem_alloc_get(s),
26742656 sk_wmem_alloc_get(s),
2675
- nlk->cb_running,
2657
+ READ_ONCE(nlk->cb_running),
26762658 refcount_read(&s->sk_refcnt),
26772659 atomic_read(&s->sk_drops),
26782660 sock_i_ino(s)