cmsg.3: Explain zero-initialization requirement for CMSG_NXTHDR()

When initializing a new buffer (e.g., that will be sent with
sendmsg(2)), that buffer must first be zero-initialized to
ensure the correct operation of CMSG_NXTHDR().

Verified by experiment, and also by inspection of the glibc
source code:

  _EXTERN_INLINE struct cmsghdr *
  __NTH (__cmsg_nxthdr (struct msghdr *__mhdr, struct cmsghdr *__cmsg))
  {
    if ((size_t) __cmsg->cmsg_len < sizeof (struct cmsghdr))
      /* The kernel header does this so there may be a reason.  */
      return (struct cmsghdr *) 0;

[1] __cmsg = (struct cmsghdr *) ((unsigned char *) __cmsg
                                   + CMSG_ALIGN (__cmsg->cmsg_len));
    if ((unsigned char *) (__cmsg + 1) > ((unsigned char *) __mhdr->msg_control
                                          + __mhdr->msg_controllen)
[2]     || ((unsigned char *) __cmsg + CMSG_ALIGN (__cmsg->cmsg_len)  // <---
            > ((unsigned char *) __mhdr->msg_control + __mhdr->msg_controllen)))
      /* No more entries.  */
      return (struct cmsghdr *) 0;
    return __cmsg;
  }

At point [1], __cmsg has been updated to point to the next
cmsghdr. The subsequent check at [2] relies on 'cmsg_len'
in the next cmsghdr having some "sensible" value (e.g., 0).
See also https://stackoverflow.com/questions/27601849/cmsg-nxthdr-returns-null-even-though-there-are-more-cmsghdr-objects

Signed-off-by: Michael Kerrisk <mtk.manpages@gmail.com>
This commit is contained in:
Michael Kerrisk 2018-07-08 20:32:15 +02:00
parent c87721467e
commit ca16e00db8
1 changed files with 8 additions and 0 deletions

View File

@ -85,6 +85,14 @@ returns the next valid
after the passed
.IR cmsghdr .
It returns NULL when there isn't enough space left in the buffer.
.IP
When initializing a buffer that will contain a series of
.I cmsghdr
structures (e.g., to be sent with
.BR sendmsg (2)),
that buffer should first be zero-initialized
to ensure the correct operation of
.BR CMSG_NXTHDR ().
.IP *
.BR CMSG_ALIGN (),
given a length, returns it including the required alignment.