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)
#endif
diff --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)
return -EINVAL;
}
- x->props.header_len = sizeof(struct ipv6_destopt_hdr) +
- calc_padlen(sizeof(struct ipv6_destopt_hdr), 6) +
- sizeof(struct ipv6_destopt_hao);
+ x->props.header_len = IPV6_OPT_HDRLEN +
+ calc_padlen(IPV6_OPT_HDRLEN, 8, 6) + /* 8n + 6 */
+ sizeof(struct ipv6_destopt_hao);
BUG_TRAP(x->props.header_len == 24);
return 0;
--
YOSHIFUJI Hideaki @ USAGI Project <yoshfuji@linux-ipv6.org>
GPG-FP : 9022 65EB 1ECF 3AD1 0BDF 80D8 4807 F894 E062 0EEA
--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
| Martin Bligh | Re: Unified tracing buffer |
| Ingo Molnar | [announce] "kill the Big Kernel Lock (BKL)" tree |
| Con Kolivas | [PATCH] [RFC] sched: accurate user accounting |
| Bart Van Assche | Integration of SCST in the mainstream Linux kernel |
| Krzysztof Oledzki | Error: an inet prefix is expected rather than "0/0". |
| Wenji Wu | A Linux TCP SACK Question |
| Ramachandra K | [PATCH 11/13] QLogic VNIC: Driver utility file - implements various utility macros |
| Jay Cliburn | Re: atl1 64-bit => 32-bit DMA borkage (reproducible, bisected) |
git: | |
| Andrew Morton | Untracked working tree files |
| Pierre Habouzit | Re: libgit2 - a true git library |
| Nicolas Vilz 'niv' | git + ssh + key authentication feature-request |
| Martin Langhoff | Re: pack operation is thrashing my server |
| Steve B | SSH brute force attacks no longer being caught by PF rule |
| GVG GVG | ssh_exchange_identification: Connection closed by remote host |
| rancor | How to copy/pipe console buffert to file? |
| Richard Stallman | Real men don't attack straw men |
| Question on swap as ramdisk partition | 18 minutes ago | Linux kernel |
| Netfilter kernel module | 10 hours ago | Linux kernel |
| serial driver xmit problem | 13 hours ago | Linux kernel |
| Why Windows is better than Linux | 13 hours ago | Linux general |
| How can I see my kernel messages in vt12? | 20 hours ago | Linux kernel |
| Grub | 1 day ago | Linux general |
| vmalloc_fault handling in x86_64 | 1 day ago | Linux kernel |
| epoll_wait()ing on epoll FD | 1 day ago | Linux kernel |
| Framebuffer in x86_64 causes problems to multiseat | 1 day ago | Linux kernel |
| Difference between 2.4 and 2.6 regarding thread creation | 2 days ago | Linux general |
