Module Name: src Committed By: riastradh Date: Sat Feb 8 13:30:42 UTC 2025
Modified Files: src/share/man/man3: CMSG_DATA.3 Log Message: cmsg(3): Handle as many descriptors as the sender sends in example. Due to a quirk of alignment, sizing the control buffer for CMSG_SPACE(sizeof(int)) does not guarantee at most one file descriptor fits in the buffer -- so if there is a chance the sender may send more than one descriptor, the receiver has to loop over all of them to avoid leaks. Prompted by: PR lib/59054: cmsg(3) uses malloc(3) unnecessarily To generate a diff of this commit: cvs rdiff -u -r1.4 -r1.5 src/share/man/man3/CMSG_DATA.3 Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/share/man/man3/CMSG_DATA.3 diff -u src/share/man/man3/CMSG_DATA.3:1.4 src/share/man/man3/CMSG_DATA.3:1.5 --- src/share/man/man3/CMSG_DATA.3:1.4 Sat Feb 8 13:18:48 2025 +++ src/share/man/man3/CMSG_DATA.3 Sat Feb 8 13:30:42 2025 @@ -1,4 +1,4 @@ -.\" $NetBSD: CMSG_DATA.3,v 1.4 2025/02/08 13:18:48 riastradh Exp $ +.\" $NetBSD: CMSG_DATA.3,v 1.5 2025/02/08 13:30:42 riastradh Exp $ .\" $OpenBSD: CMSG_DATA.3,v 1.5 2008/03/24 16:11:07 deraadt Exp $ .\" Written by Jared Yanovich <jar...@openbsd.org> .\" Public domain, July 3, 2005 @@ -116,7 +116,8 @@ if (sendmsg(s, &msg, 0) == -1) err(1, "sendmsg"); .Ed .Pp -And an example that receives and decomposes the control message: +And an example that receives the control message and handles all the +file descriptors it receives: .Bd -literal -offset indent struct msghdr msg; struct cmsghdr *cmsg; @@ -131,18 +132,39 @@ msg.msg_controllen = sizeof(cmsgbuf.buf) if (recvmsg(s, &msg, 0) == -1) err(1, "recvmsg"); -if ((msg.msg_flags & (MSG_TRUNC|MSG_CTRUNC)) - errx(1, "control message truncated"); +if (msg.msg_flags & MSG_CTRUNC) + warnx("control message truncated"); for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg)) { - if (cmsg->cmsg_len == CMSG_LEN(sizeof(int)) && - cmsg->cmsg_level == SOL_SOCKET && + if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) { - fd = *(int *)CMSG_DATA(cmsg); - /* Do something with the descriptor. */ + int *fdp = (int *)CMSG_DATA(cmsg); + socklen_t nbytes = cmsg->cmsg_len - CMSG_LEN(0); + socklen_t nfds = nbytes/sizeof(fdp[0]); + + assert(nbytes % sizeof(fdp[0]) == 0); + + while (nfds --> 0) { + int fd = *fdp++; + + /* Do something with the descriptor. */ + } } } .Ed +.Pp +Note that even if the receiver +.Em intends +to size its control buffer for +.Em one +file descriptor with +.Li CMSG_SPACE(sizeof(int)) , +this size may be rounded up for alignment to enough space for more than +one file descriptor. +So if the sender may send more than one file descriptor at a time, the +receiver cannot restrict itself to receiving at most one at a time, and +must be prepared to handle all of them \(em otherwise they will simply +leak on the receiver side. .Sh SEE ALSO .Xr recvmsg 2 , .Xr sendmsg 2 ,