Date: Sun, 3 Oct 2021 09:35:47 -0400 From: Rich Felker <dalias@...c.org> To: "J. Hanne" <musl@...hanne.name> Cc: musl@...ts.openwall.com Subject: Re: CMSG_LEN macro On Sun, Oct 03, 2021 at 10:14:59AM +0200, J. Hanne wrote: > Hi, > > thanks for your thoughts. The NLMSG macros also already gave me > similar headache some time ago. I personally find both APIs > counter-intuitive because they use the term "ALIGN", when they mean > "PAD", so that the *following* item is aligned. > > I would suggest the following patch now: > > Do not use CMSG_ALIGN on struct cmsghdr, because: > - This has no effect on any architecture anyway, because sizeof(struct cmsghdr) == 16 on all archs > - Using it contradicts with CMSG_DATA, which does NOT apply any padding after struct cmsghdr > - This is consistent with the NLMSG_* macros > --- > diff -uNr a/include/sys/socket.h b/include/sys/socket.h > --- a/include/sys/socket.h 2021-01-15 03:26:00.000000000 +0100 > +++ b/include/sys/socket.h 2021-10-03 09:49:35.000000000 +0200 > @@ -358,8 +358,8 @@ > #define CMSG_FIRSTHDR(mhdr) ((size_t) (mhdr)->msg_controllen >= sizeof (struct cmsghdr) ? (struct cmsghdr *) (mhdr)->msg_control : (struct cmsghdr *) 0) > > #define CMSG_ALIGN(len) (((len) + sizeof (size_t) - 1) & (size_t) ~(sizeof (size_t) - 1)) Aside: this should be cleaned up too. It has a truely no-op cast (the type is the same as the type of the expression) and gratuitously uses ~(x-1) instead of -x. But this could be a separate change. (Note: implicit in my claim here is an assumption that size_t has rank not less than that of int, but this is assumed everywhere and is a condition on any ABI we would ever plausibly support.) > -#define CMSG_SPACE(len) (CMSG_ALIGN (len) + CMSG_ALIGN (sizeof (struct cmsghdr))) > -#define CMSG_LEN(len) (CMSG_ALIGN (sizeof (struct cmsghdr)) + (len)) > +#define CMSG_SPACE(len) (CMSG_ALIGN (len) + sizeof (struct cmsghdr)) > +#define CMSG_LEN(len) (sizeof (struct cmsghdr) + (len)) Looks ok I think. > #define SCM_RIGHTS 0x01 > #define SCM_CREDENTIALS 0x02 > -- > > By the way, the question which led me to all this stuff is: How do I > get the payload length of a received cmsg. Neither the man page nor > an Internet search gave me any satisfactory answer. So my best guess > was "do some arithmetic with CMSG_LEN": > payloadlen = cmsghdr->cmsg_len - CMSG_LEN(0); > However, when double-checking with musl source code, the CMSG_ALIGN > on struct cmsghdr made me doubt my approach. Now, I will stick to it > - as long as nobody else has a better idea? I would probably compute the address of the end of the cmsg and subtract CMSG_DATA -- something like: (unsigned char *)cmsg + cmsg->cmsg_len - CMSG_DATA(cmsg) treating the length as untrusted if appropriate. This might be better rearranged (so there's no question of overflow if cmsg_len is invalid) as: cmsg->cmsg_len - (CMSG_DATA(cmsg) - (unsigned char *)cmsg) This avoids relying on a nonportable CMSG_LEN macro or assumptions about it. Rich
Powered by blists - more mailing lists
Confused about mailing lists and their use? Read about mailing lists on Wikipedia and check out these guidelines on proper formatting of your messages.