Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 29a3cad5 authored by Simon Horman's avatar Simon Horman Committed by David S. Miller
Browse files

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: default avatarSimon Horman <horms@verge.net.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent ced14f68
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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;

+1 −1
Original line number Diff line number Diff line
@@ -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;

	/*
+3 −2
Original line number Diff line number Diff line
@@ -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,
+4 −2
Original line number Diff line number Diff line
@@ -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;
+5 −4
Original line number Diff line number Diff line
@@ -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
Loading