We cannot rely on sizeof(struct ipv6_opt_hdr) when we are handling
wire format, because it may not be 2 but 4 on some architectures.
On such a architecture, the result can be different from what we
actually expect.Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
--
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 4aaefc3..cf57155 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -52,6 +52,8 @@ struct ipv6_opt_hdr {
__u8 hdrlen;
/*
* TLV encoded option data follows.
+ *
+ * NOTE: Be aware of arch-dependent alignment requirements!
*/
};@@ -59,6 +61,9 @@ struct ipv6_opt_hdr {
#define ipv6_hopopt_hdr ipv6_opt_hdr#ifdef __KERNEL__
+/* sizeof(struct ipv6_opt_hdr) might not be 2 */
+#define IPV6_OPT_HDRLEN 2
+
#define ipv6_optlen(p) (((p)->hdrlen+1) << 3)
#endifdiff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c
index cd8a5bd..b3d13fb 100644
--- a/net/ipv6/mip6.c
+++ b/net/ipv6/mip6.c
@@ -34,9 +34,13 @@
#include <net/xfrm.h>
#include <net/mip6.h>-static inline unsigned int calc_padlen(unsigned int len, unsigned int n)
+static inline unsigned int calc_padlen(unsigned int offset,
+ unsigned int m, unsigned int n)
{
- return (n - len + 16) & 0x7;
+ offset %= m;
+ if (offset > n)
+ offset += m;
+ return (n - offset);
}static inline void *mip6_padn(__u8 *data, __u8 padlen)
@@ -160,8 +164,9 @@ static int mip6_destopt_output(struct xfrm_state *x, struct sk_buff *skb)
dstopt = (struct ipv6_destopt_hdr *)skb_transport_header(skb);
dstopt->nexthdr = nexthdr;- hao = mip6_padn((char *)(dstopt + 1),
- calc_padlen(sizeof(*dstopt), 6));
+ /* Note: sizeof(*dstopt) might not be 2. */
+ hao = mip6_padn(((u8 *)dstopt) + IPV6_OPT_HDRLEN,
+ calc_padlen(IPV6_OPT_HDRLEN, 8, 6)); /* 8n + 6 */hao->type = IPV6_TLV_HAO;
hao->length = sizeof(*hao) - 2;
@@ -314,9 +319,9 @@ static int mip6_destopt_init_state(struct xfrm_state *x)
retur...
From: YOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@linux-ipv6.org>
Please just mark the structure with "packed" attribute.
It is appropriate in this case, and there should be no cost
because members are 8-byte quantities.Otherwise, mistakes are likely to be added in the future.
It is very reasonable to expect the structure size for
a networking header to match correctly.--
Sure!
--yoshfuji
--
Here it is:
From: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
Date: Mon, 14 Apr 2008 14:47:47 +0900
Subject: [PATCH net-2.6] [IPV6]: IPv6 extension header structures need to be packed.struct ipv6_opt_hdr is the common structure for IPv6 extension
headers, and it is common to increment the pointer to get
the real content. On the other hand, since the structure
consists only of 1-byte next-header field and 1-byte length
field, size of that structure depends on architecture; 2 or 4.
Add "packed" attribute to get 2.Signed-off-by: YOSHIFUJI Hideaki <yoshfuji@linux-ipv6.org>
---
include/linux/ipv6.h | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h
index 4aaefc3..134c8e5 100644
--- a/include/linux/ipv6.h
+++ b/include/linux/ipv6.h
@@ -53,7 +53,7 @@ struct ipv6_opt_hdr {
/*
* TLV encoded option data follows.
*/
-};
+} __attribute__ ((packed)); /* required for some archs */#define ipv6_destopt_hdr ipv6_opt_hdr
#define ipv6_hopopt_hdr ipv6_opt_hdr
--
1.4.4.4--
YOSHIFUJI Hideaki @ USAGI Project <yoshfuji@linux-ipv6.org>
GPG-FP : 9022 65EB 1ECF 3AD1 0BDF 80D8 4807 F894 E062 0EEA
--
From: YOSHIFUJI Hideaki / 吉藤英明 <yoshfuji@linux-ipv6.org>
Applied to net-2.6, thank you.
--
| Paul Jackson | Re: cpuset-remove-sched-domain-hooks-from-cpusets |
| James Bottomley | Re: Announce: Linux-next (Or Andrew's dream :-)) |
| David Miller | Slow DOWN, please!!! |
| Masami Hiramatsu | Re: [RFC PATCH v4] Unified trace buffer |
git: | |
| Gerrit Renker | [PATCH 27/37] dccp: Integration of dynamic feature activation - part 2 (server side) |
| Parag Warudkar | Re: 2.6.29-rc3: tg3 dead after resume |
| Jarek Poplawski | [PATCH] pkt_sched: Destroy gen estimators under rtnl_lock(). |
