aboutsummaryrefslogtreecommitdiff
path: root/tests
diff options
context:
space:
mode:
authorGleb Smirnoff <glebius@FreeBSD.org>2022-06-06 17:05:28 +0000
committerGleb Smirnoff <glebius@FreeBSD.org>2022-06-06 17:05:28 +0000
commitd97922c6c63202fc19c22c0f821c951f85fb9840 (patch)
tree764223262636de96412e6096558759299eec9dd5 /tests
parent8d95f500521128c2b40270bdd703a54b56dbccf2 (diff)
downloadsrc-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.c37
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));