net: core: add READ_ONCE/WRITE_ONCE annotations for sk->sk_bound_dev_if

sock_bindtoindex_locked() needs to use WRITE_ONCE(sk->sk_bound_dev_if, val),
because other cpus/threads might locklessly read this field.

sock_getbindtodevice(), sock_getsockopt() need READ_ONCE()
because they run without socket lock held.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Eric Dumazet 2022-05-13 11:55:44 -07:00 committed by David S. Miller
parent fdb5fd7f73
commit e5fccaa1eb
1 changed files with 7 additions and 4 deletions

View File

@ -635,7 +635,9 @@ static int sock_bindtoindex_locked(struct sock *sk, int ifindex)
if (ifindex < 0)
goto out;
sk->sk_bound_dev_if = ifindex;
/* Paired with all READ_ONCE() done locklessly. */
WRITE_ONCE(sk->sk_bound_dev_if, ifindex);
if (sk->sk_prot->rehash)
sk->sk_prot->rehash(sk);
sk_dst_reset(sk);
@ -713,10 +715,11 @@ static int sock_getbindtodevice(struct sock *sk, char __user *optval,
{
int ret = -ENOPROTOOPT;
#ifdef CONFIG_NETDEVICES
int bound_dev_if = READ_ONCE(sk->sk_bound_dev_if);
struct net *net = sock_net(sk);
char devname[IFNAMSIZ];
if (sk->sk_bound_dev_if == 0) {
if (bound_dev_if == 0) {
len = 0;
goto zero;
}
@ -725,7 +728,7 @@ static int sock_getbindtodevice(struct sock *sk, char __user *optval,
if (len < IFNAMSIZ)
goto out;
ret = netdev_get_name(net, devname, sk->sk_bound_dev_if);
ret = netdev_get_name(net, devname, bound_dev_if);
if (ret)
goto out;
@ -1861,7 +1864,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
break;
case SO_BINDTOIFINDEX:
v.val = sk->sk_bound_dev_if;
v.val = READ_ONCE(sk->sk_bound_dev_if);
break;
case SO_NETNS_COOKIE: