diff options
Diffstat (limited to 'net/packet/af_packet.c')
-rw-r--r-- | net/packet/af_packet.c | 92 |
1 files changed, 47 insertions, 45 deletions
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index af399cac5205..1cf928fb573e 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -1741,6 +1741,20 @@ static void fanout_release(struct sock *sk) | |||
1741 | kfree_rcu(po->rollover, rcu); | 1741 | kfree_rcu(po->rollover, rcu); |
1742 | } | 1742 | } |
1743 | 1743 | ||
1744 | static bool packet_extra_vlan_len_allowed(const struct net_device *dev, | ||
1745 | struct sk_buff *skb) | ||
1746 | { | ||
1747 | /* Earlier code assumed this would be a VLAN pkt, double-check | ||
1748 | * this now that we have the actual packet in hand. We can only | ||
1749 | * do this check on Ethernet devices. | ||
1750 | */ | ||
1751 | if (unlikely(dev->type != ARPHRD_ETHER)) | ||
1752 | return false; | ||
1753 | |||
1754 | skb_reset_mac_header(skb); | ||
1755 | return likely(eth_hdr(skb)->h_proto == htons(ETH_P_8021Q)); | ||
1756 | } | ||
1757 | |||
1744 | static const struct proto_ops packet_ops; | 1758 | static const struct proto_ops packet_ops; |
1745 | 1759 | ||
1746 | static const struct proto_ops packet_ops_spkt; | 1760 | static const struct proto_ops packet_ops_spkt; |
@@ -1902,18 +1916,10 @@ retry: | |||
1902 | goto retry; | 1916 | goto retry; |
1903 | } | 1917 | } |
1904 | 1918 | ||
1905 | if (len > (dev->mtu + dev->hard_header_len + extra_len)) { | 1919 | if (len > (dev->mtu + dev->hard_header_len + extra_len) && |
1906 | /* Earlier code assumed this would be a VLAN pkt, | 1920 | !packet_extra_vlan_len_allowed(dev, skb)) { |
1907 | * double-check this now that we have the actual | 1921 | err = -EMSGSIZE; |
1908 | * packet in hand. | 1922 | goto out_unlock; |
1909 | */ | ||
1910 | struct ethhdr *ehdr; | ||
1911 | skb_reset_mac_header(skb); | ||
1912 | ehdr = eth_hdr(skb); | ||
1913 | if (ehdr->h_proto != htons(ETH_P_8021Q)) { | ||
1914 | err = -EMSGSIZE; | ||
1915 | goto out_unlock; | ||
1916 | } | ||
1917 | } | 1923 | } |
1918 | 1924 | ||
1919 | skb->protocol = proto; | 1925 | skb->protocol = proto; |
@@ -2332,6 +2338,15 @@ static bool ll_header_truncated(const struct net_device *dev, int len) | |||
2332 | return false; | 2338 | return false; |
2333 | } | 2339 | } |
2334 | 2340 | ||
2341 | static void tpacket_set_protocol(const struct net_device *dev, | ||
2342 | struct sk_buff *skb) | ||
2343 | { | ||
2344 | if (dev->type == ARPHRD_ETHER) { | ||
2345 | skb_reset_mac_header(skb); | ||
2346 | skb->protocol = eth_hdr(skb)->h_proto; | ||
2347 | } | ||
2348 | } | ||
2349 | |||
2335 | static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, | 2350 | static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, |
2336 | void *frame, struct net_device *dev, int size_max, | 2351 | void *frame, struct net_device *dev, int size_max, |
2337 | __be16 proto, unsigned char *addr, int hlen) | 2352 | __be16 proto, unsigned char *addr, int hlen) |
@@ -2368,8 +2383,6 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, | |||
2368 | skb_reserve(skb, hlen); | 2383 | skb_reserve(skb, hlen); |
2369 | skb_reset_network_header(skb); | 2384 | skb_reset_network_header(skb); |
2370 | 2385 | ||
2371 | if (!packet_use_direct_xmit(po)) | ||
2372 | skb_probe_transport_header(skb, 0); | ||
2373 | if (unlikely(po->tp_tx_has_off)) { | 2386 | if (unlikely(po->tp_tx_has_off)) { |
2374 | int off_min, off_max, off; | 2387 | int off_min, off_max, off; |
2375 | off_min = po->tp_hdrlen - sizeof(struct sockaddr_ll); | 2388 | off_min = po->tp_hdrlen - sizeof(struct sockaddr_ll); |
@@ -2415,6 +2428,8 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, | |||
2415 | dev->hard_header_len); | 2428 | dev->hard_header_len); |
2416 | if (unlikely(err)) | 2429 | if (unlikely(err)) |
2417 | return err; | 2430 | return err; |
2431 | if (!skb->protocol) | ||
2432 | tpacket_set_protocol(dev, skb); | ||
2418 | 2433 | ||
2419 | data += dev->hard_header_len; | 2434 | data += dev->hard_header_len; |
2420 | to_write -= dev->hard_header_len; | 2435 | to_write -= dev->hard_header_len; |
@@ -2449,6 +2464,8 @@ static int tpacket_fill_skb(struct packet_sock *po, struct sk_buff *skb, | |||
2449 | len = ((to_write > len_max) ? len_max : to_write); | 2464 | len = ((to_write > len_max) ? len_max : to_write); |
2450 | } | 2465 | } |
2451 | 2466 | ||
2467 | skb_probe_transport_header(skb, 0); | ||
2468 | |||
2452 | return tp_len; | 2469 | return tp_len; |
2453 | } | 2470 | } |
2454 | 2471 | ||
@@ -2493,12 +2510,13 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | |||
2493 | if (unlikely(!(dev->flags & IFF_UP))) | 2510 | if (unlikely(!(dev->flags & IFF_UP))) |
2494 | goto out_put; | 2511 | goto out_put; |
2495 | 2512 | ||
2496 | reserve = dev->hard_header_len + VLAN_HLEN; | 2513 | if (po->sk.sk_socket->type == SOCK_RAW) |
2514 | reserve = dev->hard_header_len; | ||
2497 | size_max = po->tx_ring.frame_size | 2515 | size_max = po->tx_ring.frame_size |
2498 | - (po->tp_hdrlen - sizeof(struct sockaddr_ll)); | 2516 | - (po->tp_hdrlen - sizeof(struct sockaddr_ll)); |
2499 | 2517 | ||
2500 | if (size_max > dev->mtu + reserve) | 2518 | if (size_max > dev->mtu + reserve + VLAN_HLEN) |
2501 | size_max = dev->mtu + reserve; | 2519 | size_max = dev->mtu + reserve + VLAN_HLEN; |
2502 | 2520 | ||
2503 | do { | 2521 | do { |
2504 | ph = packet_current_frame(po, &po->tx_ring, | 2522 | ph = packet_current_frame(po, &po->tx_ring, |
@@ -2525,18 +2543,10 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | |||
2525 | tp_len = tpacket_fill_skb(po, skb, ph, dev, size_max, proto, | 2543 | tp_len = tpacket_fill_skb(po, skb, ph, dev, size_max, proto, |
2526 | addr, hlen); | 2544 | addr, hlen); |
2527 | if (likely(tp_len >= 0) && | 2545 | if (likely(tp_len >= 0) && |
2528 | tp_len > dev->mtu + dev->hard_header_len) { | 2546 | tp_len > dev->mtu + reserve && |
2529 | struct ethhdr *ehdr; | 2547 | !packet_extra_vlan_len_allowed(dev, skb)) |
2530 | /* Earlier code assumed this would be a VLAN pkt, | 2548 | tp_len = -EMSGSIZE; |
2531 | * double-check this now that we have the actual | ||
2532 | * packet in hand. | ||
2533 | */ | ||
2534 | 2549 | ||
2535 | skb_reset_mac_header(skb); | ||
2536 | ehdr = eth_hdr(skb); | ||
2537 | if (ehdr->h_proto != htons(ETH_P_8021Q)) | ||
2538 | tp_len = -EMSGSIZE; | ||
2539 | } | ||
2540 | if (unlikely(tp_len < 0)) { | 2550 | if (unlikely(tp_len < 0)) { |
2541 | if (po->tp_loss) { | 2551 | if (po->tp_loss) { |
2542 | __packet_set_status(po, ph, | 2552 | __packet_set_status(po, ph, |
@@ -2765,18 +2775,10 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) | |||
2765 | 2775 | ||
2766 | sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags); | 2776 | sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags); |
2767 | 2777 | ||
2768 | if (!gso_type && (len > dev->mtu + reserve + extra_len)) { | 2778 | if (!gso_type && (len > dev->mtu + reserve + extra_len) && |
2769 | /* Earlier code assumed this would be a VLAN pkt, | 2779 | !packet_extra_vlan_len_allowed(dev, skb)) { |
2770 | * double-check this now that we have the actual | 2780 | err = -EMSGSIZE; |
2771 | * packet in hand. | 2781 | goto out_free; |
2772 | */ | ||
2773 | struct ethhdr *ehdr; | ||
2774 | skb_reset_mac_header(skb); | ||
2775 | ehdr = eth_hdr(skb); | ||
2776 | if (ehdr->h_proto != htons(ETH_P_8021Q)) { | ||
2777 | err = -EMSGSIZE; | ||
2778 | goto out_free; | ||
2779 | } | ||
2780 | } | 2782 | } |
2781 | 2783 | ||
2782 | skb->protocol = proto; | 2784 | skb->protocol = proto; |
@@ -2807,8 +2809,8 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len) | |||
2807 | len += vnet_hdr_len; | 2809 | len += vnet_hdr_len; |
2808 | } | 2810 | } |
2809 | 2811 | ||
2810 | if (!packet_use_direct_xmit(po)) | 2812 | skb_probe_transport_header(skb, reserve); |
2811 | skb_probe_transport_header(skb, reserve); | 2813 | |
2812 | if (unlikely(extra_len == 4)) | 2814 | if (unlikely(extra_len == 4)) |
2813 | skb->no_fcs = 1; | 2815 | skb->no_fcs = 1; |
2814 | 2816 | ||
@@ -4107,7 +4109,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, | |||
4107 | err = -EINVAL; | 4109 | err = -EINVAL; |
4108 | if (unlikely((int)req->tp_block_size <= 0)) | 4110 | if (unlikely((int)req->tp_block_size <= 0)) |
4109 | goto out; | 4111 | goto out; |
4110 | if (unlikely(req->tp_block_size & (PAGE_SIZE - 1))) | 4112 | if (unlikely(!PAGE_ALIGNED(req->tp_block_size))) |
4111 | goto out; | 4113 | goto out; |
4112 | if (po->tp_version >= TPACKET_V3 && | 4114 | if (po->tp_version >= TPACKET_V3 && |
4113 | (int)(req->tp_block_size - | 4115 | (int)(req->tp_block_size - |
@@ -4119,8 +4121,8 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, | |||
4119 | if (unlikely(req->tp_frame_size & (TPACKET_ALIGNMENT - 1))) | 4121 | if (unlikely(req->tp_frame_size & (TPACKET_ALIGNMENT - 1))) |
4120 | goto out; | 4122 | goto out; |
4121 | 4123 | ||
4122 | rb->frames_per_block = req->tp_block_size/req->tp_frame_size; | 4124 | rb->frames_per_block = req->tp_block_size / req->tp_frame_size; |
4123 | if (unlikely(rb->frames_per_block <= 0)) | 4125 | if (unlikely(rb->frames_per_block == 0)) |
4124 | goto out; | 4126 | goto out; |
4125 | if (unlikely((rb->frames_per_block * req->tp_block_nr) != | 4127 | if (unlikely((rb->frames_per_block * req->tp_block_nr) != |
4126 | req->tp_frame_nr)) | 4128 | req->tp_frame_nr)) |