inet_request_bound_dev_if() reads sk->sk_bound_dev_if twice while listener socket is not locked. Another cpu could change this field under us.
Showing the changes to include (1 of 1 file). Show all
Unified · Split
| @@ -116,14 +116,15 @@ static inline u32 inet_request_mark(const struct sock *sk, struct sk_buff *skb) · 115 unmodified lines | |||
| 116 | static inline int inet_request_bound_dev_if(const struct sock *sk, | 116 | static inline int inet_request_bound_dev_if(const struct sock *sk, |
| 117 | struct sk_buff *skb) | 117 | struct sk_buff *skb) |
| 118 | { | 118 | { |
| 119 | int bound_dev_if = READ_ONCE(sk->sk_bound_dev_if); | ||
| 119 | #ifdef CONFIG_NET_L3_MASTER_DEV | 120 | #ifdef CONFIG_NET_L3_MASTER_DEV |
| 120 | struct net *net = sock_net(sk); | 121 | struct net *net = sock_net(sk); |
| 121 | 122 | ||
| 122 | if (!sk->sk_bound_dev_if && net->ipv4.sysctl_tcp_l3mdev_accept) | 123 | if (!bound_dev_if && net->ipv4.sysctl_tcp_l3mdev_accept) |
| 123 | return l3mdev_master_ifindex_by_index(net, skb->skb_iif); | 124 | return l3mdev_master_ifindex_by_index(net, skb->skb_iif); |
| 124 | #endif | 125 | #endif |
| 125 | 126 | ||
| 126 | return sk->sk_bound_dev_if; | 127 | return bound_dev_if; |
| 127 | } | 128 | } |
| 128 | 129 | ||
| 129 | static inline int inet_sk_bound_l3mdev(const struct sock *sk) | 130 | static inline int inet_sk_bound_l3mdev(const struct sock *sk) |