ipv6: Correct comparisons and calculations using skb->tail and skb-transport_header
authorSimon Horman <horms@verge.net.au>
Tue, 28 May 2013 20:34:26 +0000 (20:34 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 29 May 2013 06:49:07 +0000 (23:49 -0700)
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 whereas skb->transport_header
will be an offset from head. This is corrected by using wrappers that
ensure that comparisons and calculations are always made using pointers.

Signed-off-by: Simon Horman <horms@verge.net.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv6/exthdrs_core.c
net/ipv6/icmp.c
net/ipv6/mcast.c
net/ipv6/mip6.c
net/ipv6/ndisc.c
net/ipv6/output_core.c
net/ipv6/raw.c
net/ipv6/route.c

index c5e83fae4df423ccbe02bed8bf31ffd415014ad2..140748debc4ade194e5e179636e94264da7e65a1 100644 (file)
@@ -115,7 +115,7 @@ EXPORT_SYMBOL(ipv6_skip_exthdr);
 int ipv6_find_tlv(struct sk_buff *skb, int offset, int type)
 {
        const unsigned char *nh = skb_network_header(skb);
-       int packet_len = skb->tail - skb->network_header;
+       int packet_len = skb_tail_pointer(skb) - skb_network_header(skb);
        struct ipv6_opt_hdr *hdr;
        int len;
 
index 1d2902e617866eee6553ff1197ee464d745886ef..4b4890bbe16d9ccd9b694acd5771d16914a4ab66 100644 (file)
@@ -399,7 +399,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
        int err = 0;
 
        if ((u8 *)hdr < skb->head ||
-           (skb->network_header + sizeof(*hdr)) > skb->tail)
+           (skb_network_header(skb) + sizeof(*hdr)) > skb_tail_pointer(skb))
                return;
 
        /*
index bfa6cc36ef2ab33e6e2894e03bb07c50f56a5804..72c8bfe06bb4afa547db787756d974998f93d86f 100644 (file)
@@ -1409,8 +1409,9 @@ static void mld_sendpack(struct sk_buff *skb)
        idev = __in6_dev_get(skb->dev);
        IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
 
-       payload_len = (skb->tail - skb->network_header) - sizeof(*pip6);
-       mldlen = skb->tail - skb->transport_header;
+       payload_len = (skb_tail_pointer(skb) - skb_network_header(skb)) -
+               sizeof(*pip6);
+       mldlen = skb_tail_pointer(skb) - skb_transport_header(skb);
        pip6->payload_len = htons(payload_len);
 
        pmr->mld2r_cksum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen,
index 0f9bdc5ee9f38c70f1c4c265e8ebe43467d6b59a..9ac01dc9402e9337d4b27952127d229acbb6e062 100644 (file)
@@ -268,7 +268,8 @@ static int mip6_destopt_offset(struct xfrm_state *x, struct sk_buff *skb,
        struct ipv6_opt_hdr *exthdr =
                                   (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
        const unsigned char *nh = skb_network_header(skb);
-       unsigned int packet_len = skb->tail - skb->network_header;
+       unsigned int packet_len = skb_tail_pointer(skb) -
+               skb_network_header(skb);
        int found_rhdr = 0;
 
        *nexthdr = &ipv6_hdr(skb)->nexthdr;
@@ -404,7 +405,8 @@ static int mip6_rthdr_offset(struct xfrm_state *x, struct sk_buff *skb,
        struct ipv6_opt_hdr *exthdr =
                                   (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
        const unsigned char *nh = skb_network_header(skb);
-       unsigned int packet_len = skb->tail - skb->network_header;
+       unsigned int packet_len = skb_tail_pointer(skb) -
+               skb_network_header(skb);
        int found_rhdr = 0;
 
        *nexthdr = &ipv6_hdr(skb)->nexthdr;
index a0962697a25743559b105c33a1114a2d2fdfda5e..781dd3c99680704d382ce093b2c5e32b86d95d89 100644 (file)
@@ -693,7 +693,7 @@ static void ndisc_recv_ns(struct sk_buff *skb)
        const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr;
        const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
        u8 *lladdr = NULL;
-       u32 ndoptlen = skb->tail - (skb->transport_header +
+       u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) +
                                    offsetof(struct nd_msg, opt));
        struct ndisc_options ndopts;
        struct net_device *dev = skb->dev;
@@ -853,7 +853,7 @@ static void ndisc_recv_na(struct sk_buff *skb)
        const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr;
        const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
        u8 *lladdr = NULL;
-       u32 ndoptlen = skb->tail - (skb->transport_header +
+       u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) +
                                    offsetof(struct nd_msg, opt));
        struct ndisc_options ndopts;
        struct net_device *dev = skb->dev;
@@ -1069,7 +1069,8 @@ static void ndisc_router_discovery(struct sk_buff *skb)
 
        __u8 * opt = (__u8 *)(ra_msg + 1);
 
-       optlen = (skb->tail - skb->transport_header) - sizeof(struct ra_msg);
+       optlen = (skb_tail_pointer(skb) - skb_transport_header(skb)) -
+               sizeof(struct ra_msg);
 
        if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) {
                ND_PRINTK(2, warn, "RA: source address is not link-local\n");
@@ -1346,7 +1347,7 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
        u8 *hdr;
        struct ndisc_options ndopts;
        struct rd_msg *msg = (struct rd_msg *)skb_transport_header(skb);
-       u32 ndoptlen = skb->tail - (skb->transport_header +
+       u32 ndoptlen = skb_tail_pointer(skb) - (skb_transport_header(skb) +
                                    offsetof(struct rd_msg, opt));
 
 #ifdef CONFIG_IPV6_NDISC_NODETYPE
index c2e73e647e440745acd32dcaa1564031f4323e38..ab92a3673fbbddd9f3d32b69730c3b1b61fbcbde 100644 (file)
@@ -40,7 +40,8 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
        u16 offset = sizeof(struct ipv6hdr);
        struct ipv6_opt_hdr *exthdr =
                                (struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
-       unsigned int packet_len = skb->tail - skb->network_header;
+       unsigned int packet_len = skb_tail_pointer(skb) -
+               skb_network_header(skb);
        int found_rhdr = 0;
        *nexthdr = &ipv6_hdr(skb)->nexthdr;
 
index eedff8ccded507cc977bd073dbbf334b2624033b..4f8886aa8429b3e8b10656c4b85448ed83d24f36 100644 (file)
@@ -1132,7 +1132,8 @@ static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg)
                spin_lock_bh(&sk->sk_receive_queue.lock);
                skb = skb_peek(&sk->sk_receive_queue);
                if (skb != NULL)
-                       amount = skb->tail - skb->transport_header;
+                       amount = skb_tail_pointer(skb) -
+                               skb_transport_header(skb);
                spin_unlock_bh(&sk->sk_receive_queue.lock);
                return put_user(amount, (int __user *)arg);
        }
index 194c3cde15365f84d360408e1489ff4714159a6e..2b874185ebb2bb114a2a567fd99790a2bf7aff0e 100644 (file)
@@ -1649,7 +1649,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
        int optlen, on_link;
        u8 *lladdr;
 
-       optlen = skb->tail - skb->transport_header;
+       optlen = skb_tail_pointer(skb) - skb_transport_header(skb);
        optlen -= sizeof(*msg);
 
        if (optlen < 0) {