mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 04:18:39 +08:00
inet: implement lockless getsockopt(IP_MULTICAST_IF)
Add missing annotations to inet->mc_index and inet->mc_addr to fix data-races. getsockopt(IP_MULTICAST_IF) can be lockless. setsockopt() side is left for later. Signed-off-by: Eric Dumazet <edumazet@google.com> Reviewed-by: David Ahern <dsahern@kernel.org> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
c4480eb550
commit
0271592522
@ -39,9 +39,9 @@ int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len
|
||||
saddr = inet->inet_saddr;
|
||||
if (ipv4_is_multicast(usin->sin_addr.s_addr)) {
|
||||
if (!oif || netif_index_is_l3_master(sock_net(sk), oif))
|
||||
oif = inet->mc_index;
|
||||
oif = READ_ONCE(inet->mc_index);
|
||||
if (!saddr)
|
||||
saddr = inet->mc_addr;
|
||||
saddr = READ_ONCE(inet->mc_addr);
|
||||
} else if (!oif) {
|
||||
oif = READ_ONCE(inet->uc_index);
|
||||
}
|
||||
|
@ -1168,8 +1168,8 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
|
||||
|
||||
if (!mreq.imr_ifindex) {
|
||||
if (mreq.imr_address.s_addr == htonl(INADDR_ANY)) {
|
||||
inet->mc_index = 0;
|
||||
inet->mc_addr = 0;
|
||||
WRITE_ONCE(inet->mc_index, 0);
|
||||
WRITE_ONCE(inet->mc_addr, 0);
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
@ -1194,8 +1194,8 @@ int do_ip_setsockopt(struct sock *sk, int level, int optname,
|
||||
midx != sk->sk_bound_dev_if)
|
||||
break;
|
||||
|
||||
inet->mc_index = mreq.imr_ifindex;
|
||||
inet->mc_addr = mreq.imr_address.s_addr;
|
||||
WRITE_ONCE(inet->mc_index, mreq.imr_ifindex);
|
||||
WRITE_ONCE(inet->mc_addr, mreq.imr_address.s_addr);
|
||||
err = 0;
|
||||
break;
|
||||
}
|
||||
@ -1673,19 +1673,11 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
|
||||
case IP_UNICAST_IF:
|
||||
val = (__force int)htonl((__u32) READ_ONCE(inet->uc_index));
|
||||
goto copyval;
|
||||
}
|
||||
|
||||
if (needs_rtnl)
|
||||
rtnl_lock();
|
||||
sockopt_lock_sock(sk);
|
||||
|
||||
switch (optname) {
|
||||
case IP_MULTICAST_IF:
|
||||
{
|
||||
struct in_addr addr;
|
||||
len = min_t(unsigned int, len, sizeof(struct in_addr));
|
||||
addr.s_addr = inet->mc_addr;
|
||||
sockopt_release_sock(sk);
|
||||
addr.s_addr = READ_ONCE(inet->mc_addr);
|
||||
|
||||
if (copy_to_sockptr(optlen, &len, sizeof(int)))
|
||||
return -EFAULT;
|
||||
@ -1693,6 +1685,13 @@ int do_ip_getsockopt(struct sock *sk, int level, int optname,
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (needs_rtnl)
|
||||
rtnl_lock();
|
||||
sockopt_lock_sock(sk);
|
||||
|
||||
switch (optname) {
|
||||
case IP_MSFILTER:
|
||||
{
|
||||
struct ip_msfilter msf;
|
||||
|
@ -773,9 +773,9 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
||||
|
||||
if (ipv4_is_multicast(daddr)) {
|
||||
if (!ipc.oif || netif_index_is_l3_master(sock_net(sk), ipc.oif))
|
||||
ipc.oif = inet->mc_index;
|
||||
ipc.oif = READ_ONCE(inet->mc_index);
|
||||
if (!saddr)
|
||||
saddr = inet->mc_addr;
|
||||
saddr = READ_ONCE(inet->mc_addr);
|
||||
} else if (!ipc.oif)
|
||||
ipc.oif = READ_ONCE(inet->uc_index);
|
||||
|
||||
|
@ -579,9 +579,9 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
||||
uc_index = READ_ONCE(inet->uc_index);
|
||||
if (ipv4_is_multicast(daddr)) {
|
||||
if (!ipc.oif || netif_index_is_l3_master(sock_net(sk), ipc.oif))
|
||||
ipc.oif = inet->mc_index;
|
||||
ipc.oif = READ_ONCE(inet->mc_index);
|
||||
if (!saddr)
|
||||
saddr = inet->mc_addr;
|
||||
saddr = READ_ONCE(inet->mc_addr);
|
||||
} else if (!ipc.oif) {
|
||||
ipc.oif = uc_index;
|
||||
} else if (ipv4_is_lbcast(daddr) && uc_index) {
|
||||
|
@ -1177,9 +1177,9 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
|
||||
uc_index = READ_ONCE(inet->uc_index);
|
||||
if (ipv4_is_multicast(daddr)) {
|
||||
if (!ipc.oif || netif_index_is_l3_master(sock_net(sk), ipc.oif))
|
||||
ipc.oif = inet->mc_index;
|
||||
ipc.oif = READ_ONCE(inet->mc_index);
|
||||
if (!saddr)
|
||||
saddr = inet->mc_addr;
|
||||
saddr = READ_ONCE(inet->mc_addr);
|
||||
connected = 0;
|
||||
} else if (!ipc.oif) {
|
||||
ipc.oif = uc_index;
|
||||
|
Loading…
Reference in New Issue
Block a user