Subject: Re: alignment crash in v6 ipfilter when receiving on gif
To: Martin Husemann <martin@duskware.de>
From: Greg Troxel <gdt@ir.bbn.com>
List: port-sparc64
Date: 07/10/2007 12:47:55
I think Martin is right that i6addr_t must be aligned to 64 bits and
thus the compiler assumes it is after a cast and is correct to coalesce
two 32-bit compares to a 64-bit compare.

I took the patch from Geoff's mail and re-applied it by hand since the
diff was munged by the archives.  This is against the current contents
of netbsd-4.

With the patch, I can traceroute from and through my sparc64 router.

Should I commit this to -current and then request a pullup after a week?
The patch applies with only a bit of fuzz/offset, so pretty clearly the
same issue would be present there.

Thanks for the help.


Index: sys/dist/ipf/netinet/fil.c
===================================================================
RCS file: /cvsroot/src/sys/dist/ipf/netinet/fil.c,v
retrieving revision 1.28.2.4
diff -u -p -r1.28.2.4 fil.c
--- sys/dist/ipf/netinet/fil.c	8 Jun 2007 09:20:06 -0000	1.28.2.4
+++ sys/dist/ipf/netinet/fil.c	10 Jul 2007 16:46:17 -0000
@@ -726,6 +726,7 @@ fr_info_t *fin;
 
 	if (fin->fin_dlen > 1) {
 		ip6_t *ip6;
+		struct in6_addr ip6_src;
 
 		icmp6 = fin->fin_dp;
 
@@ -757,8 +758,15 @@ fr_info_t *fin;
 			 * not correct.
 			 */
 			ip6 = (ip6_t *)((char *)icmp6 + ICMPERR_ICMPHLEN);
+			/*
+			 * There is no guarantee that ip6 is aligned to 64 bits,
+			 * and gcc uses 64-bit loads because ip6_t contains
+			 * pointers and thus must be 64-bit aligned.
+			 */
+			memcpy(&ip6_src, &ip6->ip6_src,
+			       sizeof(struct in6_addr));
 			if (IP6_NEQ(&fin->fin_fi.fi_dst,
-				    (i6addr_t *)&ip6->ip6_src))
+				    &ip6_src))
 				fin->fin_flx |= FI_BAD;
 
 			minicmpsz = ICMP6ERR_IPICMPHLEN - sizeof(ip6_t);