diff options
author | Willem de Bruijn <willemb@google.com> | 2017-09-26 12:20:17 -0400 |
---|---|---|
committer | Ben Hutchings <ben@decadent.org.uk> | 2018-01-01 20:51:44 +0000 |
commit | 38b2f505e56f7496a3bddfab910d9001f3c6142b (patch) | |
tree | bc9123b2d47ec0db12796061aefeeec3038e94ac /net/packet | |
parent | 0ad43afc28bab51dcfc002d36afc541b7b32d5b1 (diff) |
packet: only test po->has_vnet_hdr once in packet_snd
commit da7c9561015e93d10fe6aab73e9288e0d09d65a6 upstream.
Packet socket option po->has_vnet_hdr can be updated concurrently with
other operations if no ring is attached.
Do not test the option twice in packet_snd, as the value may change in
between calls. A race on setsockopt disable may cause a packet > mtu
to be sent without having GSO options set.
Fixes: bfd5f4a3d605 ("packet: Add GSO/csum offload support.")
Signed-off-by: Willem de Bruijn <willemb@google.com>
Reviewed-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
[bwh: Backported to 3.16: adjust context]
Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
Diffstat (limited to 'net/packet')
-rw-r--r-- | net/packet/af_packet.c | 4 |
1 files changed, 3 insertions, 1 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index f5bf29c033bd..c7d91a0b51da 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c @@ -2432,6 +2432,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) int offset = 0; int vnet_hdr_len; struct packet_sock *po = pkt_sk(sk); + bool has_vnet_hdr = false; unsigned short gso_type = 0; int hlen, tlen; int extra_len = 0; @@ -2466,6 +2467,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) reserve = dev->hard_header_len; if (po->has_vnet_hdr) { vnet_hdr_len = sizeof(vnet_hdr); + has_vnet_hdr = true; err = -EINVAL; if (len < vnet_hdr_len) @@ -2557,7 +2559,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) skb->priority = sk->sk_priority; skb->mark = sk->sk_mark; - if (po->has_vnet_hdr) { + if (has_vnet_hdr) { if (vnet_hdr.flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { if (!skb_partial_csum_set(skb, vnet_hdr.csum_start, vnet_hdr.csum_offset)) { |