diff options
Diffstat (limited to 'net/packet')
-rw-r--r-- | net/packet/af_packet.c | 41 |
1 files changed, 32 insertions, 9 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 91cb1d71f018..b5362e96022b 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -164,7 +164,6 @@ struct packet_mreq_max { | |||
164 | static int packet_set_ring(struct sock *sk, struct tpacket_req *req, | 164 | static int packet_set_ring(struct sock *sk, struct tpacket_req *req, |
165 | int closing, int tx_ring); | 165 | int closing, int tx_ring); |
166 | 166 | ||
167 | #define PGV_FROM_VMALLOC 1 | ||
168 | struct pgv { | 167 | struct pgv { |
169 | char *buffer; | 168 | char *buffer; |
170 | }; | 169 | }; |
@@ -466,7 +465,7 @@ retry: | |||
466 | */ | 465 | */ |
467 | 466 | ||
468 | err = -EMSGSIZE; | 467 | err = -EMSGSIZE; |
469 | if (len > dev->mtu + dev->hard_header_len) | 468 | if (len > dev->mtu + dev->hard_header_len + VLAN_HLEN) |
470 | goto out_unlock; | 469 | goto out_unlock; |
471 | 470 | ||
472 | if (!skb) { | 471 | if (!skb) { |
@@ -497,6 +496,19 @@ retry: | |||
497 | goto retry; | 496 | goto retry; |
498 | } | 497 | } |
499 | 498 | ||
499 | if (len > (dev->mtu + dev->hard_header_len)) { | ||
500 | /* Earlier code assumed this would be a VLAN pkt, | ||
501 | * double-check this now that we have the actual | ||
502 | * packet in hand. | ||
503 | */ | ||
504 | struct ethhdr *ehdr; | ||
505 | skb_reset_mac_header(skb); | ||
506 | ehdr = eth_hdr(skb); | ||
507 | if (ehdr->h_proto != htons(ETH_P_8021Q)) { | ||
508 | err = -EMSGSIZE; | ||
509 | goto out_unlock; | ||
510 | } | ||
511 | } | ||
500 | 512 | ||
501 | skb->protocol = proto; | 513 | skb->protocol = proto; |
502 | skb->dev = dev; | 514 | skb->dev = dev; |
@@ -523,11 +535,11 @@ static inline unsigned int run_filter(const struct sk_buff *skb, | |||
523 | { | 535 | { |
524 | struct sk_filter *filter; | 536 | struct sk_filter *filter; |
525 | 537 | ||
526 | rcu_read_lock_bh(); | 538 | rcu_read_lock(); |
527 | filter = rcu_dereference_bh(sk->sk_filter); | 539 | filter = rcu_dereference(sk->sk_filter); |
528 | if (filter != NULL) | 540 | if (filter != NULL) |
529 | res = sk_run_filter(skb, filter->insns); | 541 | res = sk_run_filter(skb, filter->insns); |
530 | rcu_read_unlock_bh(); | 542 | rcu_read_unlock(); |
531 | 543 | ||
532 | return res; | 544 | return res; |
533 | } | 545 | } |
@@ -954,7 +966,6 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, | |||
954 | 966 | ||
955 | static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | 967 | static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) |
956 | { | 968 | { |
957 | struct socket *sock; | ||
958 | struct sk_buff *skb; | 969 | struct sk_buff *skb; |
959 | struct net_device *dev; | 970 | struct net_device *dev; |
960 | __be16 proto; | 971 | __be16 proto; |
@@ -966,8 +977,6 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | |||
966 | int len_sum = 0; | 977 | int len_sum = 0; |
967 | int status = 0; | 978 | int status = 0; |
968 | 979 | ||
969 | sock = po->sk.sk_socket; | ||
970 | |||
971 | mutex_lock(&po->pg_vec_lock); | 980 | mutex_lock(&po->pg_vec_lock); |
972 | 981 | ||
973 | err = -EBUSY; | 982 | err = -EBUSY; |
@@ -1200,7 +1209,7 @@ static int packet_snd(struct socket *sock, | |||
1200 | } | 1209 | } |
1201 | 1210 | ||
1202 | err = -EMSGSIZE; | 1211 | err = -EMSGSIZE; |
1203 | if (!gso_type && (len > dev->mtu+reserve)) | 1212 | if (!gso_type && (len > dev->mtu + reserve + VLAN_HLEN)) |
1204 | goto out_unlock; | 1213 | goto out_unlock; |
1205 | 1214 | ||
1206 | err = -ENOBUFS; | 1215 | err = -ENOBUFS; |
@@ -1225,6 +1234,20 @@ static int packet_snd(struct socket *sock, | |||
1225 | if (err < 0) | 1234 | if (err < 0) |
1226 | goto out_free; | 1235 | goto out_free; |
1227 | 1236 | ||
1237 | if (!gso_type && (len > dev->mtu + reserve)) { | ||
1238 | /* Earlier code assumed this would be a VLAN pkt, | ||
1239 | * double-check this now that we have the actual | ||
1240 | * packet in hand. | ||
1241 | */ | ||
1242 | struct ethhdr *ehdr; | ||
1243 | skb_reset_mac_header(skb); | ||
1244 | ehdr = eth_hdr(skb); | ||
1245 | if (ehdr->h_proto != htons(ETH_P_8021Q)) { | ||
1246 | err = -EMSGSIZE; | ||
1247 | goto out_free; | ||
1248 | } | ||
1249 | } | ||
1250 | |||
1228 | skb->protocol = proto; | 1251 | skb->protocol = proto; |
1229 | skb->dev = dev; | 1252 | skb->dev = dev; |
1230 | skb->priority = sk->sk_priority; | 1253 | skb->priority = sk->sk_priority; |