summaryrefslogtreecommitdiff
path: root/net/packet
diff options
context:
space:
mode:
authorWillem de Bruijn <willemb@google.com>2017-09-26 12:20:17 -0400
committerBen Hutchings <ben@decadent.org.uk>2018-01-01 20:51:44 +0000
commit38b2f505e56f7496a3bddfab910d9001f3c6142b (patch)
treebc9123b2d47ec0db12796061aefeeec3038e94ac /net/packet
parent0ad43afc28bab51dcfc002d36afc541b7b32d5b1 (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.c4
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)) {