Subject: Re: sysctl function and ROUNDUP kernel bug
To: None <Chris_G_Demetriou@niagara.nectar.cs.cmu.edu>
From: David Waitzman <djw@bbnplanet.com>
List: port-alpha
Date: 01/30/1996 21:05:36
> > I am trying to port gated to netbsd/alpha (sys.951220) and am having
> > problems with reading the interface list using the sysctl function on
> > variable CTL_NET, PF_ROUTE, 0, 0, NET_RT_IFLIST. Dereferencing longs
> > in the middle of the returned data causes bus errors. It appears that
> > the longs are embedded in structures that are on 4 byte but not 8 byte
> > alignment.
>
> could you provide some sample code that demonstrates this? I'd like
> to replicate the problem before i fix it. 8-)
The only source I have is actually gated, version gated-R3_6Alpha_1
(though the bus error is in file src/krt_ifread_kinfo.c), and it would
be painful to extract the relevant code. I could send you the gated
configuration file, but I suspect that installing and compiling gated
might be too heavyweight. Please let me know what to provide.
> > Can anyone suggest if changing ROUNDUP is the right thing to do?
>
> It might be; i'm running a test kernel with that change, now...
> It seems to work OK, but i dunno if i have any code that actually
> tests that code path.
Further testing shows that I did not solve the problem just by changing
ROUNDUP. The problem still occured. The misaligned sysctl data is
being put together in file net/rtsock.c function rt_msg2() handling
the cases:
case RTM_DELADDR:
case RTM_NEWADDR:
len = sizeof(struct ifa_msghdr);
break;
Struct ifa_msghdr is 20 bytes long. rt_msg2() puts one into a data stream,
followed by some sockaddrs (whose length is passed through ROUNDUP). The
sockaddrs do not start on a 8 byte boundary-- that is my bus error.
For reference, here is struct isa_msghdr (with three lines I added):
/*
* Message format for use in obtaining information about interface addresses
* from sysctl and the routing socket.
*/
struct ifa_msghdr {
u_short ifam_msglen; /* to skip over non-understood messages */
u_char ifam_version; /* future binary compatability */
u_char ifam_type; /* message type */
int ifam_addrs; /* like rtm_addrs */
int ifam_flags; /* value of ifa_flags */
u_short ifam_index; /* index for associated ifp */
int ifam_metric; /* value of ifa_metric */
#ifdef __alpha__ /*ADDED*/
int :32; /* padding for 8 byte alignment */ /*ADDED*/
#endif /* __alpha__ */ /*ADDED*/
};
If a user program were to allocate a struct ifa_msghdr (the original
version, not my version) inside a larger struct then the compiler would
add 4 bytes of padding:
struct outside {
struct ifa_msghdr xx;
/* four pad bytes added */
long aligned_right;
};
But the kernel code in rtsock.c is doing the equivalent of:
struct ifa_msghdr xx;
long a_long;
char *cp = malloc(...);
bcopy(&xx, cp, sizeof(xx));
cp += sizeof(xx);
bcopy(&a_long, cp, sizeof(long));
Gated assumes that the long is aligned properly when it reads it.
Should it be?
As I showed in my version of struct ifa_msghdr, I put in 4 bytes of
padding on alpha for forced alignment. I think that this is a bad hack.
Should a compiler do this automatically, e.g. pad *all* structures to 8
byte alignment? I think that the answer to that is "No".
The reason I am giving so much detail in this email is that I think
that this is a general 64 bit code issue which may affect other
programs.
-david