* [PATCH 0/7] Fix fallout from conversion of skb headers to 16bit offsets
@ 2013-05-29 5:27 Simon Horman
2013-05-29 5:27 ` [PATCH 1/7] isdn: Correct comparison of skb->tail and skb-transport_header Simon Horman
` (6 more replies)
0 siblings, 7 replies; 13+ messages in thread
From: Simon Horman @ 2013-05-29 5:27 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Simon Horman
Many apologies for not having the foresight to spot these problems earlier.
These problems relate to comparisons between integer offsets and pointers
that occur when NET_SKBUFF_DATA_USES_OFFSET is not set
These are regressions caused by "net: Use 16bits for *_headers fields of
struct skbuff".
Simon Horman (7):
isdn: Correct comparison of skb->tail and skb-transport_header
cxgb3: Correct comparisons and calculations using skb->tail and
skb-transport_header
net: Correct comparisons and calculations using skb->tail and
skb-transport_header
ipv6: Correct comparisons and calculations using skb->tail and
skb-transport_header
ipv4: Correct comparisons and calculations using skb->tail and
skb-transport_header
sctp: Correct access to skb->{network,transport}_header
net,ipv4,ipv6: Correct assignment of skb->network_header to skb->tail
drivers/isdn/i4l/isdn_net.c | 2 +-
drivers/net/ethernet/chelsio/cxgb3/sge.c | 11 +++++------
include/linux/skbuff.h | 9 +++++++++
include/net/inet_ecn.h | 6 ++++--
net/core/dev.c | 4 ++--
net/core/netpoll.c | 9 ++++++++-
net/core/pktgen.c | 16 ++++++++++++++--
net/ipv4/icmp.c | 3 ++-
net/ipv4/igmp.c | 2 +-
net/ipv4/ipmr.c | 8 +++++++-
net/ipv4/tcp.c | 3 ++-
net/ipv6/exthdrs_core.c | 2 +-
net/ipv6/icmp.c | 2 +-
net/ipv6/mcast.c | 5 +++--
net/ipv6/mip6.c | 6 ++++--
net/ipv6/ndisc.c | 9 +++++----
net/ipv6/output_core.c | 3 ++-
net/ipv6/raw.c | 3 ++-
net/ipv6/route.c | 2 +-
net/sctp/input.c | 2 +-
net/sctp/ipv6.c | 2 +-
21 files changed, 76 insertions(+), 33 deletions(-)
--
1.7.10.4
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH 1/7] isdn: Correct comparison of skb->tail and skb-transport_header
2013-05-29 5:27 [PATCH 0/7] Fix fallout from conversion of skb headers to 16bit offsets Simon Horman
@ 2013-05-29 5:27 ` Simon Horman
2013-05-29 5:27 ` [PATCH 2/7] cxgb3: Correct comparisons and calculations using " Simon Horman
` (5 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Simon Horman @ 2013-05-29 5:27 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Simon Horman
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 the comparison is always between pointers.
Signed-off-by: Simon Horman <horms@verge.net.au>
---
drivers/isdn/i4l/isdn_net.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/isdn/i4l/isdn_net.c b/drivers/isdn/i4l/isdn_net.c
index 88d657d..8b98d53 100644
--- a/drivers/isdn/i4l/isdn_net.c
+++ b/drivers/isdn/i4l/isdn_net.c
@@ -885,7 +885,7 @@ isdn_net_log_skb(struct sk_buff *skb, isdn_net_local *lp)
addinfo[0] = '\0';
/* This check stolen from 2.1.72 dev_queue_xmit_nit() */
- if (p < skb->data || skb->network_header >= skb->tail) {
+ if (p < skb->data || skb_network_header(skb) >= skb_tail_pointer(skb)) {
/* fall back to old isdn_net_log_packet method() */
char *buf = skb->data;
--
1.7.10.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 2/7] cxgb3: Correct comparisons and calculations using skb->tail and skb-transport_header
2013-05-29 5:27 [PATCH 0/7] Fix fallout from conversion of skb headers to 16bit offsets Simon Horman
2013-05-29 5:27 ` [PATCH 1/7] isdn: Correct comparison of skb->tail and skb-transport_header Simon Horman
@ 2013-05-29 5:27 ` Simon Horman
2013-05-29 5:27 ` [PATCH 3/7] net: " Simon Horman
` (4 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Simon Horman @ 2013-05-29 5:27 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Simon Horman
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>
---
drivers/net/ethernet/chelsio/cxgb3/sge.c | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/chelsio/cxgb3/sge.c b/drivers/net/ethernet/chelsio/cxgb3/sge.c
index 2fd773e..46d1efc 100644
--- a/drivers/net/ethernet/chelsio/cxgb3/sge.c
+++ b/drivers/net/ethernet/chelsio/cxgb3/sge.c
@@ -1584,9 +1584,8 @@ static void deferred_unmap_destructor(struct sk_buff *skb)
p = dui->addr;
if (skb->tail - skb->transport_header)
- pci_unmap_single(dui->pdev, *p++,
- skb->tail - skb->transport_header,
- PCI_DMA_TODEVICE);
+ pci_unmap_single(dui->pdev, *p++, skb_tail_pointer(skb) -
+ skb_transport_header(skb), PCI_DMA_TODEVICE);
si = skb_shinfo(skb);
for (i = 0; i < si->nr_frags; i++)
@@ -1647,8 +1646,8 @@ static void write_ofld_wr(struct adapter *adap, struct sk_buff *skb,
flits = skb_transport_offset(skb) / 8;
sgp = ndesc == 1 ? (struct sg_ent *)&d->flit[flits] : sgl;
sgl_flits = write_sgl(skb, sgp, skb_transport_header(skb),
- skb->tail - skb->transport_header,
- addr);
+ skb_tail_pointer(skb) -
+ skb_transport_header(skb), addr);
if (need_skb_unmap()) {
setup_deferred_unmapping(skb, adap->pdev, sgp, sgl_flits);
skb->destructor = deferred_unmap_destructor;
@@ -1674,7 +1673,7 @@ static inline unsigned int calc_tx_descs_ofld(const struct sk_buff *skb)
flits = skb_transport_offset(skb) / 8; /* headers */
cnt = skb_shinfo(skb)->nr_frags;
- if (skb->tail != skb->transport_header)
+ if (skb_tail_pointer(skb) != skb_transport_header(skb))
cnt++;
return flits_to_desc(flits + sgl_len(cnt));
}
--
1.7.10.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 3/7] net: Correct comparisons and calculations using skb->tail and skb-transport_header
2013-05-29 5:27 [PATCH 0/7] Fix fallout from conversion of skb headers to 16bit offsets Simon Horman
2013-05-29 5:27 ` [PATCH 1/7] isdn: Correct comparison of skb->tail and skb-transport_header Simon Horman
2013-05-29 5:27 ` [PATCH 2/7] cxgb3: Correct comparisons and calculations using " Simon Horman
@ 2013-05-29 5:27 ` Simon Horman
2013-05-29 5:27 ` [PATCH 4/7] ipv6: " Simon Horman
` (3 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Simon Horman @ 2013-05-29 5:27 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Simon Horman
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>
---
include/net/inet_ecn.h | 6 ++++--
net/core/dev.c | 4 ++--
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/include/net/inet_ecn.h b/include/net/inet_ecn.h
index aab7375..3bd2279 100644
--- a/include/net/inet_ecn.h
+++ b/include/net/inet_ecn.h
@@ -134,12 +134,14 @@ static inline int INET_ECN_set_ce(struct sk_buff *skb)
{
switch (skb->protocol) {
case cpu_to_be16(ETH_P_IP):
- if (skb->network_header + sizeof(struct iphdr) <= skb->tail)
+ if (skb_network_header(skb) + sizeof(struct iphdr) <=
+ skb_tail_pointer(skb))
return IP_ECN_set_ce(ip_hdr(skb));
break;
case cpu_to_be16(ETH_P_IPV6):
- if (skb->network_header + sizeof(struct ipv6hdr) <= skb->tail)
+ if (skb_network_header(skb) + sizeof(struct ipv6hdr) <=
+ skb_tail_pointer(skb))
return IP6_ECN_set_ce(ipv6_hdr(skb));
break;
}
diff --git a/net/core/dev.c b/net/core/dev.c
index 6eb621c..f5c9aa3 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1730,7 +1730,7 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev)
skb_reset_mac_header(skb2);
if (skb_network_header(skb2) < skb2->data ||
- skb2->network_header > skb2->tail) {
+ skb_network_header(skb2) > skb_tail_pointer(skb2)) {
net_crit_ratelimited("protocol %04x is buggy, dev %s\n",
ntohs(skb2->protocol),
dev->name);
@@ -3898,7 +3898,7 @@ static void skb_gro_reset_offset(struct sk_buff *skb)
NAPI_GRO_CB(skb)->frag0 = NULL;
NAPI_GRO_CB(skb)->frag0_len = 0;
- if (skb->mac_header == skb->tail &&
+ if (skb_mac_header(skb) == skb_tail_pointer(skb) &&
pinfo->nr_frags &&
!PageHighMem(skb_frag_page(frag0))) {
NAPI_GRO_CB(skb)->frag0 = skb_frag_address(frag0);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 4/7] ipv6: Correct comparisons and calculations using skb->tail and skb-transport_header
2013-05-29 5:27 [PATCH 0/7] Fix fallout from conversion of skb headers to 16bit offsets Simon Horman
` (2 preceding siblings ...)
2013-05-29 5:27 ` [PATCH 3/7] net: " Simon Horman
@ 2013-05-29 5:27 ` Simon Horman
2013-05-29 5:27 ` [PATCH 5/7] ipv4: " Simon Horman
` (2 subsequent siblings)
6 siblings, 0 replies; 13+ messages in thread
From: Simon Horman @ 2013-05-29 5:27 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Simon Horman
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>
---
net/ipv6/exthdrs_core.c | 2 +-
net/ipv6/icmp.c | 2 +-
net/ipv6/mcast.c | 5 +++--
net/ipv6/mip6.c | 6 ++++--
net/ipv6/ndisc.c | 9 +++++----
net/ipv6/output_core.c | 3 ++-
net/ipv6/raw.c | 3 ++-
net/ipv6/route.c | 2 +-
8 files changed, 19 insertions(+), 13 deletions(-)
diff --git a/net/ipv6/exthdrs_core.c b/net/ipv6/exthdrs_core.c
index c5e83fa..140748d 100644
--- a/net/ipv6/exthdrs_core.c
+++ b/net/ipv6/exthdrs_core.c
@@ -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;
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 1d2902e..4b4890b 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -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;
/*
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index bfa6cc3..72c8bfe 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -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,
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c
index 0f9bdc5..9ac01dc 100644
--- a/net/ipv6/mip6.c
+++ b/net/ipv6/mip6.c
@@ -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;
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index a096269..781dd3c 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -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
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c
index c2e73e6..ab92a36 100644
--- a/net/ipv6/output_core.c
+++ b/net/ipv6/output_core.c
@@ -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;
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index eedff8c..4f8886a 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -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);
}
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 194c3cd..2b87418 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -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) {
--
1.7.10.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 5/7] ipv4: Correct comparisons and calculations using skb->tail and skb-transport_header
2013-05-29 5:27 [PATCH 0/7] Fix fallout from conversion of skb headers to 16bit offsets Simon Horman
` (3 preceding siblings ...)
2013-05-29 5:27 ` [PATCH 4/7] ipv6: " Simon Horman
@ 2013-05-29 5:27 ` Simon Horman
2013-05-29 5:27 ` [PATCH 6/7] sctp: Correct access to skb->{network,transport}_header Simon Horman
2013-05-29 5:27 ` [PATCH 7/7] net,ipv4,ipv6: Correct assignment of skb->network_header to skb->tail Simon Horman
6 siblings, 0 replies; 13+ messages in thread
From: Simon Horman @ 2013-05-29 5:27 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Simon Horman
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>
---
net/ipv4/icmp.c | 3 ++-
net/ipv4/igmp.c | 2 +-
net/ipv4/tcp.c | 3 ++-
3 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 562efd9..5d0d379 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -503,7 +503,8 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info)
iph = ip_hdr(skb_in);
if ((u8 *)iph < skb_in->head ||
- (skb_in->network_header + sizeof(*iph)) > skb_in->tail)
+ (skb_network_header(skb_in) + sizeof(*iph)) >
+ skb_tail_pointer(skb_in))
goto out;
/*
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index d8c2327..450f625 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -363,7 +363,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size)
static int igmpv3_sendpack(struct sk_buff *skb)
{
struct igmphdr *pig = igmp_hdr(skb);
- const int igmplen = skb->tail - skb->transport_header;
+ const int igmplen = skb_tail_pointer(skb) - skb_transport_header(skb);
pig->csum = ip_compute_csum(igmp_hdr(skb), igmplen);
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index ba4186e..1f58594 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2989,7 +2989,8 @@ struct sk_buff *tcp_tso_segment(struct sk_buff *skb,
swap(gso_skb->truesize, skb->truesize);
}
- delta = htonl(oldlen + (skb->tail - skb->transport_header) +
+ delta = htonl(oldlen + (skb_tail_pointer(skb) -
+ skb_transport_header(skb)) +
skb->data_len);
th->check = ~csum_fold((__force __wsum)((__force u32)th->check +
(__force u32)delta));
--
1.7.10.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 6/7] sctp: Correct access to skb->{network,transport}_header
2013-05-29 5:27 [PATCH 0/7] Fix fallout from conversion of skb headers to 16bit offsets Simon Horman
` (4 preceding siblings ...)
2013-05-29 5:27 ` [PATCH 5/7] ipv4: " Simon Horman
@ 2013-05-29 5:27 ` Simon Horman
2013-05-29 19:31 ` Ben Hutchings
2013-05-29 5:27 ` [PATCH 7/7] net,ipv4,ipv6: Correct assignment of skb->network_header to skb->tail Simon Horman
6 siblings, 1 reply; 13+ messages in thread
From: Simon Horman @ 2013-05-29 5:27 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Simon Horman
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 sk_buff_data_t will be a pointer, however,
skb->{network,transport}_header is now __u16.
Signed-off-by: Simon Horman <horms@verge.net.au>
---
net/sctp/input.c | 2 +-
net/sctp/ipv6.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 4b2c831..e328fe8 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -589,7 +589,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
struct sctp_association *asoc = NULL;
struct sctp_transport *transport;
struct inet_sock *inet;
- sk_buff_data_t saveip, savesctp;
+ __be16 saveip, savesctp;
int err;
struct net *net = dev_net(skb->dev);
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index 391a245..8ee553b 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -153,7 +153,7 @@ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
struct sctp_association *asoc;
struct sctp_transport *transport;
struct ipv6_pinfo *np;
- sk_buff_data_t saveip, savesctp;
+ __be16 saveip, savesctp;
int err;
struct net *net = dev_net(skb->dev);
--
1.7.10.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH 7/7] net,ipv4,ipv6: Correct assignment of skb->network_header to skb->tail
2013-05-29 5:27 [PATCH 0/7] Fix fallout from conversion of skb headers to 16bit offsets Simon Horman
` (5 preceding siblings ...)
2013-05-29 5:27 ` [PATCH 6/7] sctp: Correct access to skb->{network,transport}_header Simon Horman
@ 2013-05-29 5:27 ` Simon Horman
2013-05-29 5:35 ` Eric Dumazet
6 siblings, 1 reply; 13+ messages in thread
From: Simon Horman @ 2013-05-29 5:27 UTC (permalink / raw)
To: David Miller; +Cc: netdev, Simon Horman
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>
---
include/linux/skbuff.h | 9 +++++++++
net/core/netpoll.c | 9 ++++++++-
net/core/pktgen.c | 16 ++++++++++++++--
net/ipv4/ipmr.c | 8 +++++++-
4 files changed, 38 insertions(+), 4 deletions(-)
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 8f2b830..26ed287 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -1391,6 +1391,11 @@ static inline void skb_set_tail_pointer(struct sk_buff *skb, const int offset)
skb_reset_tail_pointer(skb);
skb->tail += offset;
}
+
+static inline __u64 skb_tail_offset(const struct sk_buff *skb)
+{
+ return skb->tail;
+}
#else /* NET_SKBUFF_DATA_USES_OFFSET */
static inline unsigned char *skb_tail_pointer(const struct sk_buff *skb)
{
@@ -1407,6 +1412,10 @@ static inline void skb_set_tail_pointer(struct sk_buff *skb, const int offset)
skb->tail = skb->data + offset;
}
+static inline __u64 skb_tail_offset(const struct sk_buff *skb)
+{
+ return skb->tail - skb->head;
+}
#endif /* NET_SKBUFF_DATA_USES_OFFSET */
/*
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 37deedd..d4da003 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
spin_lock_irqsave(&npinfo->rx_lock, flags);
list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) {
+ __u64 tail_offset;
+
if (!ipv6_addr_equal(daddr, &np->local_ip.in6))
continue;
@@ -700,7 +702,12 @@ static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo
hdr->saddr = *saddr;
hdr->daddr = *daddr;
- send_skb->transport_header = send_skb->tail;
+ tail_offset = skb_tail_offset(skb);
+ if (tail_offset > 0xffff) {
+ kfree_skb(send_skb);
+ continue;
+ }
+ skb_set_network_header(send_skb, tail_offset);
skb_put(send_skb, size);
icmp6h = (struct icmp6hdr *)skb_transport_header(skb);
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 795498f..f2923ae 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,
__be16 *svlan_tci = NULL; /* Encapsulates priority and SVLAN ID */
__be16 *svlan_encapsulated_proto = NULL; /* packet type ID field (or len) for SVLAN tag */
u16 queue_map;
+ __u64 tail_offset;
if (pkt_dev->nr_labels)
protocol = htons(ETH_P_MPLS_UC);
@@ -2708,7 +2709,12 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
*vlan_encapsulated_proto = htons(ETH_P_IP);
}
- skb->network_header = skb->tail;
+ tail_offset = skb_tail_offset(skb);
+ if (tail_offset > 0xffff) {
+ kfree_skb(skb);
+ return NULL;
+ }
+ skb_set_network_header(skb, tail_offset);
skb->transport_header = skb->network_header + sizeof(struct iphdr);
skb_put(skb, sizeof(struct iphdr) + sizeof(struct udphdr));
skb_set_queue_mapping(skb, queue_map);
@@ -2775,6 +2781,7 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
__be16 *svlan_tci = NULL; /* Encapsulates priority and SVLAN ID */
__be16 *svlan_encapsulated_proto = NULL; /* packet type ID field (or len) for SVLAN tag */
u16 queue_map;
+ __u64 tail_offset;
if (pkt_dev->nr_labels)
protocol = htons(ETH_P_MPLS_UC);
@@ -2822,7 +2829,12 @@ static struct sk_buff *fill_packet_ipv6(struct net_device *odev,
*vlan_encapsulated_proto = htons(ETH_P_IPV6);
}
- skb->network_header = skb->tail;
+ tail_offset = skb_tail_offset(skb);
+ if (tail_offset > 0xffff) {
+ kfree_skb(skb);
+ return NULL;
+ }
+ skb_set_network_header(skb, tail_offset);
skb->transport_header = skb->network_header + sizeof(struct ipv6hdr);
skb_put(skb, sizeof(struct ipv6hdr) + sizeof(struct udphdr));
skb_set_queue_mapping(skb, queue_map);
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index f975399..d5b8b4b 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -945,6 +945,7 @@ static int ipmr_cache_report(struct mr_table *mrt,
struct igmpmsg *msg;
struct sock *mroute_sk;
int ret;
+ __be64 tail_offset;
#ifdef CONFIG_IP_PIMSM
if (assert == IGMPMSG_WHOLEPKT)
@@ -980,7 +981,12 @@ static int ipmr_cache_report(struct mr_table *mrt,
/* Copy the IP header */
- skb->network_header = skb->tail;
+ tail_offset = skb_tail_offset(skb);
+ if (tail_offset > 0xffff) {
+ kfree_skb(skb);
+ return -EINVAL;
+ }
+ skb_set_network_header(skb, tail_offset);
skb_put(skb, ihl);
skb_copy_to_linear_data(skb, pkt->data, ihl);
ip_hdr(skb)->protocol = 0; /* Flag to the kernel this is a route add */
--
1.7.10.4
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH 7/7] net,ipv4,ipv6: Correct assignment of skb->network_header to skb->tail
2013-05-29 5:27 ` [PATCH 7/7] net,ipv4,ipv6: Correct assignment of skb->network_header to skb->tail Simon Horman
@ 2013-05-29 5:35 ` Eric Dumazet
2013-05-29 5:44 ` David Miller
0 siblings, 1 reply; 13+ messages in thread
From: Eric Dumazet @ 2013-05-29 5:35 UTC (permalink / raw)
To: Simon Horman; +Cc: David Miller, netdev
On Wed, 2013-05-29 at 14:27 +0900, Simon Horman wrote:
> 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>
> ---
> include/linux/skbuff.h | 9 +++++++++
> net/core/netpoll.c | 9 ++++++++-
> net/core/pktgen.c | 16 ++++++++++++++--
> net/ipv4/ipmr.c | 8 +++++++-
> 4 files changed, 38 insertions(+), 4 deletions(-)
>
> diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
> index 8f2b830..26ed287 100644
> --- a/include/linux/skbuff.h
> +++ b/include/linux/skbuff.h
> @@ -1391,6 +1391,11 @@ static inline void skb_set_tail_pointer(struct sk_buff *skb, const int offset)
> skb_reset_tail_pointer(skb);
> skb->tail += offset;
> }
> +
> +static inline __u64 skb_tail_offset(const struct sk_buff *skb)
> +{
> + return skb->tail;
> +}
> #else /* NET_SKBUFF_DATA_USES_OFFSET */
> static inline unsigned char *skb_tail_pointer(const struct sk_buff *skb)
> {
> @@ -1407,6 +1412,10 @@ static inline void skb_set_tail_pointer(struct sk_buff *skb, const int offset)
> skb->tail = skb->data + offset;
> }
>
> +static inline __u64 skb_tail_offset(const struct sk_buff *skb)
> +{
> + return skb->tail - skb->head;
> +}
> #endif /* NET_SKBUFF_DATA_USES_OFFSET */
>
Are you sure __u64 is needed on 32bit arches ?
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 7/7] net,ipv4,ipv6: Correct assignment of skb->network_header to skb->tail
2013-05-29 5:35 ` Eric Dumazet
@ 2013-05-29 5:44 ` David Miller
2013-05-29 6:01 ` Simon Horman
0 siblings, 1 reply; 13+ messages in thread
From: David Miller @ 2013-05-29 5:44 UTC (permalink / raw)
To: eric.dumazet; +Cc: horms, netdev
From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Tue, 28 May 2013 22:35:51 -0700
> Are you sure __u64 is needed on 32bit arches ?
It should be "unsigned long" or similar.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 7/7] net,ipv4,ipv6: Correct assignment of skb->network_header to skb->tail
2013-05-29 5:44 ` David Miller
@ 2013-05-29 6:01 ` Simon Horman
0 siblings, 0 replies; 13+ messages in thread
From: Simon Horman @ 2013-05-29 6:01 UTC (permalink / raw)
To: David Miller; +Cc: eric.dumazet, netdev
On Tue, May 28, 2013 at 10:44:33PM -0700, David Miller wrote:
> From: Eric Dumazet <eric.dumazet@gmail.com>
> Date: Tue, 28 May 2013 22:35:51 -0700
>
> > Are you sure __u64 is needed on 32bit arches ?
>
> It should be "unsigned long" or similar.
Thanks, I will fix that and re-post.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 6/7] sctp: Correct access to skb->{network,transport}_header
2013-05-29 5:27 ` [PATCH 6/7] sctp: Correct access to skb->{network,transport}_header Simon Horman
@ 2013-05-29 19:31 ` Ben Hutchings
2013-05-31 6:21 ` Simon Horman
0 siblings, 1 reply; 13+ messages in thread
From: Ben Hutchings @ 2013-05-29 19:31 UTC (permalink / raw)
To: Simon Horman; +Cc: David Miller, netdev
On Wed, 2013-05-29 at 14:27 +0900, Simon Horman wrote:
> This corrects an regression introduced by "net: Use 16bits for *_headers
> fields of struct skbuff" when NET_SKBUFF_DATA_USES_OFFSET is not set.
So how about adding 'typedef u16 sk_buff_data_t;'?
> In
> that case sk_buff_data_t will be a pointer, however,
> skb->{network,transport}_header is now __u16.
>
> Signed-off-by: Simon Horman <horms@verge.net.au>
> ---
> net/sctp/input.c | 2 +-
> net/sctp/ipv6.c | 2 +-
> 2 files changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/net/sctp/input.c b/net/sctp/input.c
> index 4b2c831..e328fe8 100644
> --- a/net/sctp/input.c
> +++ b/net/sctp/input.c
> @@ -589,7 +589,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
> struct sctp_association *asoc = NULL;
> struct sctp_transport *transport;
> struct inet_sock *inet;
> - sk_buff_data_t saveip, savesctp;
> + __be16 saveip, savesctp;
[...]
__be16??
Ben.
--
Ben Hutchings, Staff Engineer, Solarflare
Not speaking for my employer; that's the marketing department's job.
They asked us to note that Solarflare product names are trademarked.
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH 6/7] sctp: Correct access to skb->{network,transport}_header
2013-05-29 19:31 ` Ben Hutchings
@ 2013-05-31 6:21 ` Simon Horman
0 siblings, 0 replies; 13+ messages in thread
From: Simon Horman @ 2013-05-31 6:21 UTC (permalink / raw)
To: Ben Hutchings; +Cc: David Miller, netdev
On Wed, May 29, 2013 at 08:31:12PM +0100, Ben Hutchings wrote:
> On Wed, 2013-05-29 at 14:27 +0900, Simon Horman wrote:
> > This corrects an regression introduced by "net: Use 16bits for *_headers
> > fields of struct skbuff" when NET_SKBUFF_DATA_USES_OFFSET is not set.
>
> So how about adding 'typedef u16 sk_buff_data_t;'?
>
> > In
> > that case sk_buff_data_t will be a pointer, however,
> > skb->{network,transport}_header is now __u16.
> >
> > Signed-off-by: Simon Horman <horms@verge.net.au>
> > ---
> > net/sctp/input.c | 2 +-
> > net/sctp/ipv6.c | 2 +-
> > 2 files changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/net/sctp/input.c b/net/sctp/input.c
> > index 4b2c831..e328fe8 100644
> > --- a/net/sctp/input.c
> > +++ b/net/sctp/input.c
> > @@ -589,7 +589,7 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info)
> > struct sctp_association *asoc = NULL;
> > struct sctp_transport *transport;
> > struct inet_sock *inet;
> > - sk_buff_data_t saveip, savesctp;
> > + __be16 saveip, savesctp;
> [...]
>
> __be16??
Ooops. I will fix that.
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2013-05-31 6:29 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-29 5:27 [PATCH 0/7] Fix fallout from conversion of skb headers to 16bit offsets Simon Horman
2013-05-29 5:27 ` [PATCH 1/7] isdn: Correct comparison of skb->tail and skb-transport_header Simon Horman
2013-05-29 5:27 ` [PATCH 2/7] cxgb3: Correct comparisons and calculations using " Simon Horman
2013-05-29 5:27 ` [PATCH 3/7] net: " Simon Horman
2013-05-29 5:27 ` [PATCH 4/7] ipv6: " Simon Horman
2013-05-29 5:27 ` [PATCH 5/7] ipv4: " Simon Horman
2013-05-29 5:27 ` [PATCH 6/7] sctp: Correct access to skb->{network,transport}_header Simon Horman
2013-05-29 19:31 ` Ben Hutchings
2013-05-31 6:21 ` Simon Horman
2013-05-29 5:27 ` [PATCH 7/7] net,ipv4,ipv6: Correct assignment of skb->network_header to skb->tail Simon Horman
2013-05-29 5:35 ` Eric Dumazet
2013-05-29 5:44 ` David Miller
2013-05-29 6:01 ` Simon Horman
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.