aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorSimon Horman <horms@verge.net.au>2013-05-28 16:34:29 -0400
committerDavid S. Miller <davem@davemloft.net>2013-05-29 02:49:07 -0400
commit7cc461900549fc480eb133948649a1edb7eaaa6f (patch)
tree32782f0156c0eb27b2b188d7882e9c2e77d7c8c5 /net/core
parent158874cac61245b84e939c92c53db7000122b7b0 (diff)
net, ipv4, ipv6: Correct assignment of skb->network_header to skb->tail
This corrects an regression introduced by "net: Use 16bits for *_headers fields of struct skbuff" when NET_SKBUFF_DATA_USES_OFFSET is not set. In that case skb->tail will be a pointer however skb->network_header is now an offset. This patch corrects the problem by adding a wrapper to return skb tail as an offset regardless of the value of NET_SKBUFF_DATA_USES_OFFSET. It seems that skb->tail that this offset may be more than 64k and some care has been taken to treat such cases as an error. Signed-off-by: Simon Horman <horms@verge.net.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/netpoll.c9
-rw-r--r--net/core/pktgen.c16
2 files changed, 22 insertions, 3 deletions
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 37deedd48bcc..688517c7ff17 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -676,6 +676,8 @@ static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo
676 676
677 spin_lock_irqsave(&npinfo->rx_lock, flags); 677 spin_lock_irqsave(&npinfo->rx_lock, flags);
678 list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) { 678 list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) {
679 unsigned long tail_offset;
680
679 if (!ipv6_addr_equal(daddr, &np->local_ip.in6)) 681 if (!ipv6_addr_equal(daddr, &np->local_ip.in6))
680 continue; 682 continue;
681 683
@@ -700,7 +702,12 @@ static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo
700 hdr->saddr = *saddr; 702 hdr->saddr = *saddr;
701 hdr->daddr = *daddr; 703 hdr->daddr = *daddr;
702 704
703 send_skb->transport_header = send_skb->tail; 705 tail_offset = skb_tail_offset(skb);
706 if (tail_offset > 0xffff) {
707 kfree_skb(send_skb);
708 continue;
709 }
710 skb_set_network_header(send_skb, tail_offset);
704 skb_put(send_skb, size); 711 skb_put(send_skb, size);
705 712
706 icmp6h = (struct icmp6hdr *)skb_transport_header(skb); 713 icmp6h = (struct icmp6hdr *)skb_transport_header(skb);
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 795498fd4587..d2ede89662be 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -2642,6 +2642,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
2642 __be16 *svlan_tci = NULL; /* Encapsulates priority and SVLAN ID */ 2642 __be16 *svlan_tci = NULL; /* Encapsulates priority and SVLAN ID */
2643 __be16 *svlan_encapsulated_proto = NULL; /* packet type ID field (or len) for SVLAN tag */ 2643 __be16 *svlan_encapsulated_proto = NULL; /* packet type ID field (or len) for SVLAN tag */
2644 u16 queue_map; 2644 u16 queue_map;
2645 unsigned long tail_offset;
2645 2646
2646 if (pkt_dev->nr_labels) 2647 if (pkt_dev->nr_labels)
2647 protocol = htons(ETH_P_MPLS_UC); 2648 protocol = htons(ETH_P_MPLS_UC);
@@ -2708,7 +2709,12 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
2708 *vlan_encapsulated_proto = htons(ETH_P_IP); 2709 *vlan_encapsulated_proto = htons(ETH_P_IP);
2709 } 2710 }
2710 2711
2711 skb->network_header = skb->tail; 2712 tail_offset = skb_tail_offset(skb);
2713 if (tail_offset > 0xffff) {
2714 kfree_skb(skb);
2715 return NULL;
2716 }
2717 skb_set_network_header(skb, tail_offset);
2712 skb->transport_header = skb->network_header + sizeof(struct iphdr); 2718 skb->transport_header = skb->network_header + sizeof(struct iphdr);
2713 skb_put(skb, sizeof(struct iphdr) + sizeof(struct udphdr)); 2719 skb_put(skb, sizeof(struct iphdr) + sizeof(struct udphdr));
2714 skb_set_queue_mapping(skb, queue_map); 2720 skb_set_queue_mapping(skb, queue_map);
@@ -2775,6 +2781,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
2775 __be16 *svlan_tci = NULL; /* Encapsulates priority and SVLAN ID */ 2781 __be16 *svlan_tci = NULL; /* Encapsulates priority and SVLAN ID */
2776 __be16 *svlan_encapsulated_proto = NULL; /* packet type ID field (or len) for SVLAN tag */ 2782 __be16 *svlan_encapsulated_proto = NULL; /* packet type ID field (or len) for SVLAN tag */
2777 u16 queue_map; 2783 u16 queue_map;
2784 unsigned long tail_offset;
2778 2785
2779 if (pkt_dev->nr_labels) 2786 if (pkt_dev->nr_labels)
2780 protocol = htons(ETH_P_MPLS_UC); 2787 protocol = htons(ETH_P_MPLS_UC);
@@ -2822,7 +2829,12 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
2822 *vlan_encapsulated_proto = htons(ETH_P_IPV6); 2829 *vlan_encapsulated_proto = htons(ETH_P_IPV6);
2823 } 2830 }
2824 2831
2825 skb->network_header = skb->tail; 2832 tail_offset = skb_tail_offset(skb);
2833 if (tail_offset > 0xffff) {
2834 kfree_skb(skb);
2835 return NULL;
2836 }
2837 skb_set_network_header(skb, tail_offset);
2826 skb->transport_header = skb->network_header + sizeof(struct ipv6hdr); 2838 skb->transport_header = skb->network_header + sizeof(struct ipv6hdr);
2827 skb_put(skb, sizeof(struct ipv6hdr) + sizeof(struct udphdr)); 2839 skb_put(skb, sizeof(struct ipv6hdr) + sizeof(struct udphdr));
2828 skb_set_queue_mapping(skb, queue_map); 2840 skb_set_queue_mapping(skb, queue_map);