sctp_rcv() reads sk->sk_bound_dev_if twice while the socket is not locked. Another cpu could change this field under us.
Unified · Split
| @@ -92,6 +92,7 @@ int sctp_rcv(struct sk_buff *skb) · 91 unmodified lines | |||
| 92 | struct sctp_chunk *chunk; | 92 | struct sctp_chunk *chunk; |
| 93 | union sctp_addr src; | 93 | union sctp_addr src; |
| 94 | union sctp_addr dest; | 94 | union sctp_addr dest; |
| 95 | int bound_dev_if; | ||
| 95 | int family; | 96 | int family; |
| 96 | struct sctp_af *af; | 97 | struct sctp_af *af; |
| 97 | struct net *net = dev_net(skb->dev); | 98 | struct net *net = dev_net(skb->dev); |
| @@ -169,7 +170,8 @@ int sctp_rcv(struct sk_buff *skb) · 71 unmodified lines | |||
| 169 | * If a frame arrives on an interface and the receiving socket is | 170 | * If a frame arrives on an interface and the receiving socket is |
| 170 | * bound to another interface, via SO_BINDTODEVICE, treat it as OOTB | 171 | * bound to another interface, via SO_BINDTODEVICE, treat it as OOTB |
| 171 | */ | 172 | */ |
| 172 | if (sk->sk_bound_dev_if && (sk->sk_bound_dev_if != af->skb_iif(skb))) { | 173 | bound_dev_if = READ_ONCE(sk->sk_bound_dev_if); |
| 174 | if (bound_dev_if && (bound_dev_if != af->skb_iif(skb))) { | ||
| 173 | if (transport) { | 175 | if (transport) { |
| 174 | sctp_transport_put(transport); | 176 | sctp_transport_put(transport); |
| 175 | asoc = NULL; | 177 | asoc = NULL; |