Subject: Re: ancillary data alignment and binary backward compatibility
To: None <itojun@iijlab.net>
From: Chris G. Demetriou <cgd@netbsd.org>
List: tech-net
Date: 03/27/2000 23:47:55
.... i've been ... busy.  (and continue to be busy... 8-)

itojun@iijlab.net writes:
> >> 	So, at least need to bump from 3 to ALIGNBYTES.
> >> 	- How to bump
> >> 	- how to determine ALIGNBYTES (statically by header of hw.alignbytes
> >> 	  sysctl MIB)
> >> 		current tree uses hw.alignbytes
> >> 	is still not 100% decided...
> >ALIGNBYTES is something that can't change for a given MACHINE_ARCH (or
> >shouldn't, unless there's a big flag day for that port).
> >There's no reason to do this using a sysctl.  it just adds overhead.
> 
> 	I thought again about it, and I think I'm really stuck.
> 	What level of binary backward compatibility do we need to provide
> 	in such situation?

What do you mean by 'need'?  NetBSD takes some amount of pride in the
fact that binaries from one release tend to work on the next without
modification.

It's kinda annoying, and losing, to throw backward compatibility away
because, in a nutshell, you don't want to write a bit more code to
handle the backward-compat case.

> 	Note that we have similar issue in routing socket data alignment.
> 	(see macro ROUNDUP in sys/net/rtsock.c)

Yeah.



> ways to cope with ancillary data alignment:
> (1) Rewrite data stream in socke tdata buffer to change ancillary data
>     alignment.  This must rewrite those in sys_sendmsg(), sendit(), or
>     somewhere similar.  We can't do it in, for example, sys/netinet6/*.

indeed, compat code already has to do this type of thing (or at least,
has to if it wants to handle compatibility with the native control
message format).

(see osf1_cvt.c, for instance, for a case where this isn't handled,
and therefore an error is returned.)

> (2) Make userland code adapt to the kernel alignment constraint
>     (ALIGNBYTES_KERNEL).  This is the code in the tree.

This is losing, as noted previously:

	* it breaks binary compatiblity.

	* it turns a compile-time test into a run-time test
	  (and an expensive one at that -- function call and all!)
	  for no good reason (since the value is actually constant).


> (3) cmsg_{level,type} are typed as "int".  they can be of different size
>     for compat_netbsd32 situation.  We may need to modify data stream in
>     socket for this, like (1).

This is broken, obviously.


> problem with (1) and (3):
> Even though (1) and (3) suggest rewrite of datastream in socket data buffer,
> it is not very trivial.  We are not very sure if data stream in "control"
> data stream is formatted/aligned properly to meet ALIGNBYTES_KERNEL, or
> userland alignment.  What kind of error should we raise?  What kind of
> behavior we should present if control data stream is truncated/insufficient?
> What happens if they gets out of sync?

Another possibility: don't rewrite, format more carefully.

reading:

	* use structs safely (i.e. copy to temporary buffer, use there).
	* use alignment specified by which kind of call it is (compat,
	  native, etc., passed in as an alignment arg).
	* return EINVAL or appropriate error code.

writing:

	* instead of aligning to some native alignment, do it based on
	  a supplied alignment.
	* use structs safely (i.e. use temp, copy into final location.)

There's actually something to be said for having the caller supply the
copin and copy out functions, too ... that might make emulations'
functions more sane to implement (but needs more investigation before
it should be done).

also: you have absolutely no guarantee that the userland program isn't
provide an absolutely bogus set of anc. data NOW!  i.e. you have to do
all of the parsing/sanity checking/etc., now anyway, which should
cause EINVAL if appropriate.  it should work equally well with just a
changed alignment constraint.  (if that's not done currently, well,
that's a bug, and probably a path to crash or hurt the system.)


> - It is trivial to support binaries with ALIGNBYTES_KERNEL (= userland
>   and the kernel agrees about ancillary data alignment).

i'd actually say it's equally easy to support any alignment.


> - For supporting old binaries (binaries with sizeof(long) - 1),
>   we need to do (1) with syscall renumbering, for data alignment.
>   With old syscall # we'd rewrite alignment from/to sizeof(long) - 1
>   to/from ALIGNBYTES_KERNEL.

sure.  or, don't 'rewrite' alignment, just pack and unpack using the
appropriate alignment.

i'm thinking something like:

_CMSG_ALIGN(l,a) ->	(((n) + (a)) & ~(a))

then define _ macros based on that, which use _CMSG_ALIGN rather than
some other alignment fn, and all take an explicit alignment value when
appropriate.

in the kernel, use them with the appropriate alignment argument, based
on the syscall being implemented (i.e. the current one w/
MACHINE_ARCH's necessary alignment for all data, the backward-compat
one with alignment of 4 bytes, etc).


for user-land, define them such that the alignment value is the one
for necessary alignment of all data....



that make sense?  (i know exactly what i'm thinking, but really don't
have much time...  8-)



cgd
-- 
Chris Demetriou - cgd@netbsd.org - http://www.netbsd.org/People/Pages/cgd.html
Disclaimer: Not speaking for NetBSD, just expressing my own opinion.