[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: CMSG_SPACE: too clever by half?
> The issue involves the way we arranged for binary compatibility
> across changes in the unix-domain file descriptor and credentials
> passing code. [...]
> I would appreciate others' opinions on this.
Here's scm-rights.h from one of my SCM_RIGHTS-using programs.
I think the comments say it all. They were written based on, IIRC, the
3.1 interface, but based on this thread it sounds as though it's only
gotten worse since then.
/~\ The ASCII Mouse
\ / Ribbon Campaign
X Against HTML mouse%rodents-montreal.org@localhost
/ \ Email! 7D C8 61 52 5D E7 2D 39 4E F1 31 3E E8 B3 27 4B
/* This file is in the public domain. */
* This file exists because the SCM_RIGHTS interface silently changed.
* It used to work the traditional way: pack file descriptors tightly
* as an array of ints immediately after the struct cmsghdr. It was
* changed to use the layout corresponding to the CMSG_* macros, which
* don't exist historically; since the resulting layout is different
* on architectures for which __cmsg_alignbytes is greater than
* sizeof(int)-1, this is rather broken, breaking historically working
* code. (The CMSG_* macros were invented for all the control guff
* IPv6 wants to shovel around. What I don't understand is why they
* were imposed on SCM_RIGHTS messages.) To make things worse, the
* CMSG_* macros are a broken API: they don't even try to support
* control messages that aren't in buffers aligned suitably for a
* struct cmsghdr (in particular, there is no way to find out where
* the data for a message falls relative to the message's beginning
* except by computing the data pointer as a function of the cmsghdr
* pointer). This means you have to either use gcc extensions like
* __alignof__ or you have to do something like the CMSKIP macro
* below - unless you're willing to malloc the buffer (and, strictly,
* even that is not enough, since there is no guarantee that the
* required alignment is that of any object type).
* So we actually use macros CMSPACE, CMLEN, and CMSKIP, which are
* defined either suitably for the historical way (if
* NEW_CMSG_INTERFACE is not defined) or the least ugly way I've found
* for the CMSG_* way (if NEW_CMSG_INTERFACE is defined).
#define CMSPACE(x) (CMSG_SPACE((x)))
#define CMLEN(x) (CMSG_LEN((x)))
* It's gross to have to do this, but it's more or less forced upon us
* by the botched design of the the CMSG_* interface. The interface
* takes first steps towards a completely opaque interface, but
* botches it rather badly, resulting in neither an interface that can
* be used opaquely nor an interface that can be used transparently.
* Since the traditional interface is the transparent style, and the
* opaque style cannot be done without alignment issues (see below),
* this code goes in the transparent direction. The result is not as
* portable as I'd like - it can depend on using a pointer past the
* end of an object, depending on the architecture - but I believe
* it's the least horrible of the available alternatives.
* The interface seems designed to overlay the structs cmsghdr onto the
* control buffer, but that demands the buffer be aligned, without
* providing any way to actually achieve that, which more or less
* compels its allocation with malloc(), that being the only portable
* way to correctly align a buffer whose alignment requirements are
* inacessible. (Using gcc extensions like __aligned__ and
* __alignof__, this can be worked around, but (a) that's gcc-specific
* and rather ugly, (b) it shouldn't be necessary, and (c) it can't be
* done without making assumptions for which there is no basis except
* knowledge of the implementation, like "the alignment necessary is
* the most strict of struct cmsghdr and the types to be stored in the
#define CMSKIP(x) ((char *)CMSG_DATA((x))-(char *)(x))
#define CMSPACE(x) (sizeof(struct cmsghdr)+(x))
#define CMLEN(x) (sizeof(struct cmsghdr)+(x))
#define CMSKIP(x) (sizeof(struct cmsghdr))
Main Index |
Thread Index |