diff options
author | Gleb Smirnoff <glebius@FreeBSD.org> | 2022-06-06 17:05:28 +0000 |
---|---|---|
committer | Gleb Smirnoff <glebius@FreeBSD.org> | 2022-06-06 17:05:28 +0000 |
commit | d97922c6c63202fc19c22c0f821c951f85fb9840 (patch) | |
tree | 764223262636de96412e6096558759299eec9dd5 /tests | |
parent | 8d95f500521128c2b40270bdd703a54b56dbccf2 (diff) | |
download | src-d97922c6c63202fc19c22c0f821c951f85fb9840.tar.gz src-d97922c6c63202fc19c22c0f821c951f85fb9840.zip |
unix/*: rewrite unp_internalize() cmsg parsing cycle
Make it a complex, but a single for(;;) statement. The previous cycle
with some loop logic in the beginning and some loop logic at the end
was confusing. Both me and markj@ were misleaded to a conclusion that
some checks are unnecessary, while they actually were necessary.
While here, handle an edge case found by Mark, when on 64-bit platform
an incorrect message from userland would underflow length counter, but
return without any error. Provide a test case for such message.
Reviewed by: markj
Differential revision: https://reviews.freebsd.org/D35375
Diffstat (limited to 'tests')
-rw-r--r-- | tests/sys/kern/unix_passfd_test.c | 37 |
1 files changed, 28 insertions, 9 deletions
diff --git a/tests/sys/kern/unix_passfd_test.c b/tests/sys/kern/unix_passfd_test.c index 91030d84872b..fe46d815c6a1 100644 --- a/tests/sys/kern/unix_passfd_test.c +++ b/tests/sys/kern/unix_passfd_test.c @@ -744,14 +744,14 @@ ATF_TC_BODY(copyout_rights_error, tc) } /* - * Verify that we can handle empty rights messages. Try sending two SCM_RIGHTS - * messages with a single call, one empty and one containing a single FD. + * Verify that we can handle empty rights messages. */ ATF_TC_WITHOUT_HEAD(empty_rights_message); ATF_TC_BODY(empty_rights_message, tc) { struct iovec iov; struct msghdr msghdr; + struct cmsghdr cmsg; char *cm, message[CMSG_SPACE(0) + CMSG_SPACE(sizeof(int))]; ssize_t len; int error, fd[2], putfd; @@ -759,21 +759,40 @@ ATF_TC_BODY(empty_rights_message, tc) domainsocketpair(fd); devnull(&putfd); + memset(&msghdr, 0, sizeof(msghdr)); + iov.iov_base = NULL; + iov.iov_len = 0; + msghdr.msg_iov = &iov; + msghdr.msg_iovlen = 1; + + /* + * Try sending incorrect empty message. On 64-bit platforms, where + * CMSG_SPACE(0) > sizeof(struct cmsghdr), this will exercise + * an edge case. + */ + cmsg = (struct cmsghdr ){ + .cmsg_len = sizeof(struct cmsghdr), /* not CMSG_LEN(0)! */ + .cmsg_level = SOL_SOCKET, + .cmsg_type = SCM_RIGHTS, + }; + msghdr.msg_control = &cmsg; + msghdr.msg_controllen = CMSG_SPACE(0); + + len = sendmsg(fd[0], &msghdr, 0); + if (CMSG_LEN(0) != sizeof(struct cmsghdr)) + ATF_REQUIRE(len == -1 && errno == EINVAL); + else + ATF_REQUIRE(len == 0); + /* - * First, try sending an empty message followed by a non-empty message. + * Try sending an empty message followed by a non-empty message. */ cm = message; putfds(cm, -1, 0); cm += CMSG_SPACE(0); putfds(cm, putfd, 1); - - memset(&msghdr, 0, sizeof(msghdr)); - iov.iov_base = NULL; - iov.iov_len = 0; msghdr.msg_control = message; msghdr.msg_controllen = sizeof(message); - msghdr.msg_iov = &iov; - msghdr.msg_iovlen = 1; len = sendmsg(fd[0], &msghdr, 0); ATF_REQUIRE_MSG(len == 0, "sendmsg failed: %s", strerror(errno)); |