ipv6: Correct comparisons and calculations using skb->tail and skb-transport_header
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>
This commit is contained in:
parent
ced14f6804
commit
29a3cad5c6
@ -115,7 +115,7 @@ EXPORT_SYMBOL(ipv6_skip_exthdr);
|
|||||||
int ipv6_find_tlv(struct sk_buff *skb, int offset, int type)
|
int ipv6_find_tlv(struct sk_buff *skb, int offset, int type)
|
||||||
{
|
{
|
||||||
const unsigned char *nh = skb_network_header(skb);
|
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;
|
struct ipv6_opt_hdr *hdr;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
|
@ -399,7 +399,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info)
|
|||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if ((u8 *)hdr < skb->head ||
|
if ((u8 *)hdr < skb->head ||
|
||||||
(skb->network_header + sizeof(*hdr)) > skb->tail)
|
(skb_network_header(skb) + sizeof(*hdr)) > skb_tail_pointer(skb))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1409,8 +1409,9 @@ static void mld_sendpack(struct sk_buff *skb)
|
|||||||
idev = __in6_dev_get(skb->dev);
|
idev = __in6_dev_get(skb->dev);
|
||||||
IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
|
IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUT, skb->len);
|
||||||
|
|
||||||
payload_len = (skb->tail - skb->network_header) - sizeof(*pip6);
|
payload_len = (skb_tail_pointer(skb) - skb_network_header(skb)) -
|
||||||
mldlen = skb->tail - skb->transport_header;
|
sizeof(*pip6);
|
||||||
|
mldlen = skb_tail_pointer(skb) - skb_transport_header(skb);
|
||||||
pip6->payload_len = htons(payload_len);
|
pip6->payload_len = htons(payload_len);
|
||||||
|
|
||||||
pmr->mld2r_cksum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen,
|
pmr->mld2r_cksum = csum_ipv6_magic(&pip6->saddr, &pip6->daddr, mldlen,
|
||||||
|
@ -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 *exthdr =
|
||||||
(struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
|
(struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
|
||||||
const unsigned char *nh = skb_network_header(skb);
|
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;
|
int found_rhdr = 0;
|
||||||
|
|
||||||
*nexthdr = &ipv6_hdr(skb)->nexthdr;
|
*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 *exthdr =
|
||||||
(struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
|
(struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
|
||||||
const unsigned char *nh = skb_network_header(skb);
|
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;
|
int found_rhdr = 0;
|
||||||
|
|
||||||
*nexthdr = &ipv6_hdr(skb)->nexthdr;
|
*nexthdr = &ipv6_hdr(skb)->nexthdr;
|
||||||
|
@ -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 *saddr = &ipv6_hdr(skb)->saddr;
|
||||||
const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
|
const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
|
||||||
u8 *lladdr = NULL;
|
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));
|
offsetof(struct nd_msg, opt));
|
||||||
struct ndisc_options ndopts;
|
struct ndisc_options ndopts;
|
||||||
struct net_device *dev = skb->dev;
|
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 *saddr = &ipv6_hdr(skb)->saddr;
|
||||||
const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
|
const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr;
|
||||||
u8 *lladdr = NULL;
|
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));
|
offsetof(struct nd_msg, opt));
|
||||||
struct ndisc_options ndopts;
|
struct ndisc_options ndopts;
|
||||||
struct net_device *dev = skb->dev;
|
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);
|
__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)) {
|
if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) {
|
||||||
ND_PRINTK(2, warn, "RA: source address is not link-local\n");
|
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;
|
u8 *hdr;
|
||||||
struct ndisc_options ndopts;
|
struct ndisc_options ndopts;
|
||||||
struct rd_msg *msg = (struct rd_msg *)skb_transport_header(skb);
|
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));
|
offsetof(struct rd_msg, opt));
|
||||||
|
|
||||||
#ifdef CONFIG_IPV6_NDISC_NODETYPE
|
#ifdef CONFIG_IPV6_NDISC_NODETYPE
|
||||||
|
@ -40,7 +40,8 @@ int ip6_find_1stfragopt(struct sk_buff *skb, u8 **nexthdr)
|
|||||||
u16 offset = sizeof(struct ipv6hdr);
|
u16 offset = sizeof(struct ipv6hdr);
|
||||||
struct ipv6_opt_hdr *exthdr =
|
struct ipv6_opt_hdr *exthdr =
|
||||||
(struct ipv6_opt_hdr *)(ipv6_hdr(skb) + 1);
|
(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;
|
int found_rhdr = 0;
|
||||||
*nexthdr = &ipv6_hdr(skb)->nexthdr;
|
*nexthdr = &ipv6_hdr(skb)->nexthdr;
|
||||||
|
|
||||||
|
@ -1132,7 +1132,8 @@ static int rawv6_ioctl(struct sock *sk, int cmd, unsigned long arg)
|
|||||||
spin_lock_bh(&sk->sk_receive_queue.lock);
|
spin_lock_bh(&sk->sk_receive_queue.lock);
|
||||||
skb = skb_peek(&sk->sk_receive_queue);
|
skb = skb_peek(&sk->sk_receive_queue);
|
||||||
if (skb != NULL)
|
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);
|
spin_unlock_bh(&sk->sk_receive_queue.lock);
|
||||||
return put_user(amount, (int __user *)arg);
|
return put_user(amount, (int __user *)arg);
|
||||||
}
|
}
|
||||||
|
@ -1649,7 +1649,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
|
|||||||
int optlen, on_link;
|
int optlen, on_link;
|
||||||
u8 *lladdr;
|
u8 *lladdr;
|
||||||
|
|
||||||
optlen = skb->tail - skb->transport_header;
|
optlen = skb_tail_pointer(skb) - skb_transport_header(skb);
|
||||||
optlen -= sizeof(*msg);
|
optlen -= sizeof(*msg);
|
||||||
|
|
||||||
if (optlen < 0) {
|
if (optlen < 0) {
|
||||||
|
Loading…
Reference in New Issue
Block a user