Commit 19ad5b89 authored by Herbert Xu's avatar Herbert Xu Committed by Ben Hutchings

ipv6: Remove all uses of LL_ALLOCATED_SPACE

commit a7ae1992 upstream.

ipv6: Remove all uses of LL_ALLOCATED_SPACE

The macro LL_ALLOCATED_SPACE was ill-conceived.  It applies the
alignment to the sum of needed_headroom and needed_tailroom.  As
the amount that is then reserved for head room is needed_headroom
with alignment, this means that the tail room left may be too small.

This patch replaces all uses of LL_ALLOCATED_SPACE in net/ipv6
with the macro LL_RESERVED_SPACE and direct reference to
needed_tailroom.

This also fixes the problem with needed_headroom changing between
allocating the skb and reserving the head room.
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
[bwh: Backported to 3.2: adjust context]
Signed-off-by: default avatarBen Hutchings <ben@decadent.org.uk>
parent b3410f43
...@@ -623,6 +623,7 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) ...@@ -623,6 +623,7 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
struct ipv6hdr *tmp_hdr; struct ipv6hdr *tmp_hdr;
struct frag_hdr *fh; struct frag_hdr *fh;
unsigned int mtu, hlen, left, len; unsigned int mtu, hlen, left, len;
int hroom, troom;
__be32 frag_id = 0; __be32 frag_id = 0;
int ptr, offset = 0, err=0; int ptr, offset = 0, err=0;
u8 *prevhdr, nexthdr = 0; u8 *prevhdr, nexthdr = 0;
...@@ -789,6 +790,8 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) ...@@ -789,6 +790,8 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
*/ */
*prevhdr = NEXTHDR_FRAGMENT; *prevhdr = NEXTHDR_FRAGMENT;
hroom = LL_RESERVED_SPACE(rt->dst.dev);
troom = rt->dst.dev->needed_tailroom;
/* /*
* Keep copying data until we run out. * Keep copying data until we run out.
...@@ -807,7 +810,8 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) ...@@ -807,7 +810,8 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
* Allocate buffer. * Allocate buffer.
*/ */
if ((frag = alloc_skb(len+hlen+sizeof(struct frag_hdr)+LL_ALLOCATED_SPACE(rt->dst.dev), GFP_ATOMIC)) == NULL) { if ((frag = alloc_skb(len + hlen + sizeof(struct frag_hdr) +
hroom + troom, GFP_ATOMIC)) == NULL) {
NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n"); NETDEBUG(KERN_INFO "IPv6: frag: no memory for new fragment!\n");
IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)),
IPSTATS_MIB_FRAGFAILS); IPSTATS_MIB_FRAGFAILS);
...@@ -820,7 +824,7 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) ...@@ -820,7 +824,7 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *))
*/ */
ip6_copy_metadata(frag, skb); ip6_copy_metadata(frag, skb);
skb_reserve(frag, LL_RESERVED_SPACE(rt->dst.dev)); skb_reserve(frag, hroom);
skb_put(frag, len + hlen + sizeof(struct frag_hdr)); skb_put(frag, len + hlen + sizeof(struct frag_hdr));
skb_reset_network_header(frag); skb_reset_network_header(frag);
fh = (struct frag_hdr *)(skb_network_header(frag) + hlen); fh = (struct frag_hdr *)(skb_network_header(frag) + hlen);
......
...@@ -1343,13 +1343,15 @@ static struct sk_buff *mld_newpack(struct inet6_dev *idev, int size) ...@@ -1343,13 +1343,15 @@ static struct sk_buff *mld_newpack(struct inet6_dev *idev, int size)
struct mld2_report *pmr; struct mld2_report *pmr;
struct in6_addr addr_buf; struct in6_addr addr_buf;
const struct in6_addr *saddr; const struct in6_addr *saddr;
int hlen = LL_RESERVED_SPACE(dev);
int tlen = dev->needed_tailroom;
int err; int err;
u8 ra[8] = { IPPROTO_ICMPV6, 0, u8 ra[8] = { IPPROTO_ICMPV6, 0,
IPV6_TLV_ROUTERALERT, 2, 0, 0, IPV6_TLV_ROUTERALERT, 2, 0, 0,
IPV6_TLV_PADN, 0 }; IPV6_TLV_PADN, 0 };
/* we assume size > sizeof(ra) here */ /* we assume size > sizeof(ra) here */
size += LL_ALLOCATED_SPACE(dev); size += hlen + tlen;
/* limit our allocations to order-0 page */ /* limit our allocations to order-0 page */
size = min_t(int, size, SKB_MAX_ORDER(0, 0)); size = min_t(int, size, SKB_MAX_ORDER(0, 0));
skb = sock_alloc_send_skb(sk, size, 1, &err); skb = sock_alloc_send_skb(sk, size, 1, &err);
...@@ -1357,7 +1359,7 @@ static struct sk_buff *mld_newpack(struct inet6_dev *idev, int size) ...@@ -1357,7 +1359,7 @@ static struct sk_buff *mld_newpack(struct inet6_dev *idev, int size)
if (!skb) if (!skb)
return NULL; return NULL;
skb_reserve(skb, LL_RESERVED_SPACE(dev)); skb_reserve(skb, hlen);
if (__ipv6_get_lladdr(idev, &addr_buf, IFA_F_TENTATIVE)) { if (__ipv6_get_lladdr(idev, &addr_buf, IFA_F_TENTATIVE)) {
/* <draft-ietf-magma-mld-source-05.txt>: /* <draft-ietf-magma-mld-source-05.txt>:
...@@ -1725,6 +1727,8 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) ...@@ -1725,6 +1727,8 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
struct mld_msg *hdr; struct mld_msg *hdr;
const struct in6_addr *snd_addr, *saddr; const struct in6_addr *snd_addr, *saddr;
struct in6_addr addr_buf; struct in6_addr addr_buf;
int hlen = LL_RESERVED_SPACE(dev);
int tlen = dev->needed_tailroom;
int err, len, payload_len, full_len; int err, len, payload_len, full_len;
u8 ra[8] = { IPPROTO_ICMPV6, 0, u8 ra[8] = { IPPROTO_ICMPV6, 0,
IPV6_TLV_ROUTERALERT, 2, 0, 0, IPV6_TLV_ROUTERALERT, 2, 0, 0,
...@@ -1746,7 +1750,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) ...@@ -1746,7 +1750,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
IPSTATS_MIB_OUT, full_len); IPSTATS_MIB_OUT, full_len);
rcu_read_unlock(); rcu_read_unlock();
skb = sock_alloc_send_skb(sk, LL_ALLOCATED_SPACE(dev) + full_len, 1, &err); skb = sock_alloc_send_skb(sk, hlen + tlen + full_len, 1, &err);
if (skb == NULL) { if (skb == NULL) {
rcu_read_lock(); rcu_read_lock();
...@@ -1756,7 +1760,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type) ...@@ -1756,7 +1760,7 @@ static void igmp6_send(struct in6_addr *addr, struct net_device *dev, int type)
return; return;
} }
skb_reserve(skb, LL_RESERVED_SPACE(dev)); skb_reserve(skb, hlen);
if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) { if (ipv6_get_lladdr(dev, &addr_buf, IFA_F_TENTATIVE)) {
/* <draft-ietf-magma-mld-source-05.txt>: /* <draft-ietf-magma-mld-source-05.txt>:
......
...@@ -446,6 +446,8 @@ struct sk_buff *ndisc_build_skb(struct net_device *dev, ...@@ -446,6 +446,8 @@ struct sk_buff *ndisc_build_skb(struct net_device *dev,
struct sock *sk = net->ipv6.ndisc_sk; struct sock *sk = net->ipv6.ndisc_sk;
struct sk_buff *skb; struct sk_buff *skb;
struct icmp6hdr *hdr; struct icmp6hdr *hdr;
int hlen = LL_RESERVED_SPACE(dev);
int tlen = dev->needed_tailroom;
int len; int len;
u8 *opt; u8 *opt;
...@@ -457,7 +459,7 @@ struct sk_buff *ndisc_build_skb(struct net_device *dev, ...@@ -457,7 +459,7 @@ struct sk_buff *ndisc_build_skb(struct net_device *dev,
len += ndisc_opt_addr_space(dev); len += ndisc_opt_addr_space(dev);
skb = alloc_skb((MAX_HEADER + sizeof(struct ipv6hdr) + skb = alloc_skb((MAX_HEADER + sizeof(struct ipv6hdr) +
len + LL_ALLOCATED_SPACE(dev)), GFP_ATOMIC); len + hlen + tlen), GFP_ATOMIC);
if (!skb) { if (!skb) {
ND_PRINTK0(KERN_ERR ND_PRINTK0(KERN_ERR
"ICMPv6 ND: %s() failed to allocate an skb.\n", "ICMPv6 ND: %s() failed to allocate an skb.\n",
...@@ -465,7 +467,7 @@ struct sk_buff *ndisc_build_skb(struct net_device *dev, ...@@ -465,7 +467,7 @@ struct sk_buff *ndisc_build_skb(struct net_device *dev,
return NULL; return NULL;
} }
skb_reserve(skb, LL_RESERVED_SPACE(dev)); skb_reserve(skb, hlen);
ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len); ip6_nd_hdr(sk, skb, dev, saddr, daddr, IPPROTO_ICMPV6, len);
skb->transport_header = skb->tail; skb->transport_header = skb->tail;
...@@ -1534,6 +1536,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, ...@@ -1534,6 +1536,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
struct inet6_dev *idev; struct inet6_dev *idev;
struct flowi6 fl6; struct flowi6 fl6;
u8 *opt; u8 *opt;
int hlen, tlen;
int rd_len; int rd_len;
int err; int err;
u8 ha_buf[MAX_ADDR_LEN], *ha = NULL; u8 ha_buf[MAX_ADDR_LEN], *ha = NULL;
...@@ -1591,9 +1594,11 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, ...@@ -1591,9 +1594,11 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
rd_len &= ~0x7; rd_len &= ~0x7;
len += rd_len; len += rd_len;
hlen = LL_RESERVED_SPACE(dev);
tlen = dev->needed_tailroom;
buff = sock_alloc_send_skb(sk, buff = sock_alloc_send_skb(sk,
(MAX_HEADER + sizeof(struct ipv6hdr) + (MAX_HEADER + sizeof(struct ipv6hdr) +
len + LL_ALLOCATED_SPACE(dev)), len + hlen + tlen),
1, &err); 1, &err);
if (buff == NULL) { if (buff == NULL) {
ND_PRINTK0(KERN_ERR ND_PRINTK0(KERN_ERR
...@@ -1602,7 +1607,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh, ...@@ -1602,7 +1607,7 @@ void ndisc_send_redirect(struct sk_buff *skb, struct neighbour *neigh,
goto release; goto release;
} }
skb_reserve(buff, LL_RESERVED_SPACE(dev)); skb_reserve(buff, hlen);
ip6_nd_hdr(sk, buff, dev, &saddr_buf, &ipv6_hdr(skb)->saddr, ip6_nd_hdr(sk, buff, dev, &saddr_buf, &ipv6_hdr(skb)->saddr,
IPPROTO_ICMPV6, len); IPPROTO_ICMPV6, len);
......
...@@ -607,6 +607,8 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, ...@@ -607,6 +607,8 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
struct sk_buff *skb; struct sk_buff *skb;
int err; int err;
struct rt6_info *rt = (struct rt6_info *)*dstp; struct rt6_info *rt = (struct rt6_info *)*dstp;
int hlen = LL_RESERVED_SPACE(rt->dst.dev);
int tlen = rt->dst.dev->needed_tailroom;
if (length > rt->dst.dev->mtu) { if (length > rt->dst.dev->mtu) {
ipv6_local_error(sk, EMSGSIZE, fl6, rt->dst.dev->mtu); ipv6_local_error(sk, EMSGSIZE, fl6, rt->dst.dev->mtu);
...@@ -616,11 +618,11 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, ...@@ -616,11 +618,11 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length,
goto out; goto out;
skb = sock_alloc_send_skb(sk, skb = sock_alloc_send_skb(sk,
length + LL_ALLOCATED_SPACE(rt->dst.dev) + 15, length + hlen + tlen + 15,
flags & MSG_DONTWAIT, &err); flags & MSG_DONTWAIT, &err);
if (skb == NULL) if (skb == NULL)
goto error; goto error;
skb_reserve(skb, LL_RESERVED_SPACE(rt->dst.dev)); skb_reserve(skb, hlen);
skb->priority = sk->sk_priority; skb->priority = sk->sk_priority;
skb->mark = sk->sk_mark; skb->mark = sk->sk_mark;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment