NetBSD-Users archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: aligning control message ancillary data



In article <20080619033059.A1DA198075%pluto.mumble.net@localhost>,
Taylor R Campbell  <campbell%mumble.net@localhost> wrote:
>After some further thought and discussion on other forums, I think
>that I have worked out what the right usage is here.  OpenBSD has a
>man page for CMSG_DATA & friends, which on OpenBSD-current (but not
>4.3) shows what the OpenBSD folks believe to be, and what I agree is,
>the correct idiom.  It would be very helpful, I think, if NetBSD had a
>similar man page.  Here is what I ought to have written in my first
>message as the `correct' idiom (although it won't work on NetBSD
>currently; see below for the two reasons):
>
>   struct msghdr msg;
>   struct cmsghdr *cmsg_ptr;
>   union {
>     struct cmsghdr align_me_please;
>     char data [CMSG_SPACE (sizeof (int))];
>   } control;
>
>   msg.msg_control = (void *) &control;
>   msg.msg_controllen = sizeof (control);
>   /* ... */
>   cmsg_ptr = CMSG_FIRSTHDR (&msg);
>   cmsg_ptr->cmsg_len = CMSG_LEN (sizeof (int));
>
>NetBSD's CMSG_SPACE does not expand to a constant expression (nor does
>CMSG_LEN).  While one can allocate objects on the stack with
>non-constant sizes, using C99 or alloca(3), this is very sketchy.
>Hence monitor_fdpass.c does not do this.  Instead...it picks a random
>number that is hoped large enough for most people, and checks that it
>is actually large enough at run-time.  I have to wonder whether this
>is really better than just dynamically allocating the control buffer.
>Some (e.g., Theo) suggest that CMSG_SPACE and CMSG_LEN are wrong to
>expand to non-constant expressions.
>
>The other issue with the above code is that currently the NetBSD
>kernel requires that the msg_controllen field of a msghdr be equal to
>the cmsg_len field of the sole cmsghdr in the control buffer for
>SCM_RIGHTS-type control messages.  Thus if CMSG_SPACE (sizeof (int))
>is not equal to CMSG_LEN (sizeof (int)) because of wider alignment
>than what one finds on the i386, and you run the above code on NetBSD,
>sendmsg will yield EINVAL.  This, I believe, is wrong, and caused by
>the following fragment from unp_internalize in kern/uipc_usrreq.c
>starting on line 1292:
>
>   /* Sanity check the control message header. */
>   if (cm->msg_type != SCM_RIGHTS || cm->msg_level != SOL_SOCKET ||
>       cm->msg_len != control->m_len)  /* <- This is the problem. */
>     return (EINVAL);
>
>The OpenBSD developers who thoroughly scrutinized this several months
>ago believe the kernel should check whether CMSG_ALIGN (cm->msg_len)
>is inequal to control->m_len.  But doing this might break a bunch of
>existing code that used the incorrect yet working idiom.  So in both
>FreeBSD as of many years ago, and in OpenBSD-current as of a few
>months ago, the analogous code checks whether cm->msg_len is simply
>greater than control->m_len, which is clearly an error.


Thanks for looking into this, I have addressed all the issues I think
(on head).

christos




Home | Main Index | Thread Index | Old Index