Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F166513651
D45686.id140087.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
70 KB
Referenced Files
None
Subscribers
None
D45686.id140087.diff
View Options
diff --git a/include/ssp/Makefile b/include/ssp/Makefile
--- a/include/ssp/Makefile
+++ b/include/ssp/Makefile
@@ -1,5 +1,5 @@
-INCS= poll.h random.h ssp.h stdio.h stdlib.h string.h strings.h uio.h unistd.h
-INCS+= wchar.h
+INCS= poll.h random.h socket.h ssp.h stdio.h stdlib.h string.h strings.h
+INCS+= uio.h unistd.h wchar.h
INCSDIR= ${INCLUDEDIR}/ssp
.include <bsd.prog.mk>
diff --git a/include/ssp/socket.h b/include/ssp/socket.h
new file mode 100644
--- /dev/null
+++ b/include/ssp/socket.h
@@ -0,0 +1,123 @@
+/*-
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024, Klara, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef _SSP_SOCKET_H_
+#define _SSP_SOCKET_H_
+
+#include <ssp/ssp.h>
+
+#if __SSP_FORTIFY_LEVEL > 0
+
+#include <sys/_null.h>
+
+__BEGIN_DECLS
+
+__ssp_inline void
+__ssp_check_msghdr(struct msghdr *hdr)
+{
+
+ if (__ssp_bos(hdr->msg_name) < hdr->msg_namelen)
+ __chk_fail();
+
+ __ssp_check_iovec(hdr->msg_iov, hdr->msg_iovlen);
+
+ if (__ssp_bos(hdr->msg_control) < hdr->msg_controllen)
+ __chk_fail();
+}
+
+__ssp_redirect_raw_impl(int, getpeername, getpeername,
+ (int fdes, struct sockaddr *__restrict name, socklen_t *__restrict namelen))
+{
+ size_t namesz = __ssp_bos(name);
+
+ if (namesz != (size_t)-1 && namesz < *namelen)
+ __chk_fail();
+
+ return (__ssp_real(getpeername)(fdes, name, namelen));
+}
+
+__ssp_redirect_raw_impl(int, getsockname, getsockname,
+ (int fdes, struct sockaddr *__restrict name,
+ socklen_t *__restrict namelen))
+{
+ size_t namesz = __ssp_bos(name);
+
+ if (namesz != (size_t)-1 && namesz < *namelen)
+ __chk_fail();
+
+ return (__ssp_real(getsockname)(fdes, name, namelen));
+}
+
+__ssp_redirect(ssize_t, recv, (int __sock, void *__buf, size_t __len,
+ int __flags), (__sock, __buf, __len, __flags));
+
+__ssp_redirect_raw_impl(ssize_t, recvfrom, recvfrom,
+ (int s, void *buf, size_t len, int flags,
+ struct sockaddr *__restrict from,
+ socklen_t *__restrict fromlen))
+{
+
+ if (__ssp_bos(buf) < len)
+ __chk_fail();
+ if (from != NULL && __ssp_bos(from) < *fromlen)
+ __chk_fail();
+
+ return (__ssp_real(recvfrom)(s, buf, len, flags, from, fromlen));
+}
+
+__ssp_redirect_raw_impl(ssize_t, recvmsg, recvmsg,
+ (int s, struct msghdr *hdr, int flags))
+{
+
+ __ssp_check_msghdr(hdr);
+ return (__ssp_real(recvmsg)(s, hdr, flags));
+}
+
+#if __BSD_VISIBLE
+struct timespec;
+
+__ssp_redirect_raw_impl(ssize_t, recvmmsg, recvmmsg,
+ (int s, struct mmsghdr *__restrict hdrvec, size_t vlen, int flags,
+ const struct timespec *__restrict timeout))
+{
+ const size_t vecsz = __ssp_bos(hdrvec);
+
+ if (vecsz != (size_t)-1 && vecsz / sizeof(*hdrvec) < vlen)
+ __chk_fail();
+
+ for (size_t i = 0; i < vlen; i++) {
+ __ssp_check_msghdr(&hdrvec[i].msg_hdr);
+ }
+
+ return (__ssp_real(recvmmsg)(s, hdrvec, vlen, flags, timeout));
+}
+#endif
+
+__END_DECLS
+
+#endif /* __SSP_FORTIFY_LEVEL > 0 */
+#endif /* _SSP_SOCKET_H_ */
diff --git a/lib/libc/sys/recv.c b/lib/libc/sys/recv.c
--- a/lib/libc/sys/recv.c
+++ b/lib/libc/sys/recv.c
@@ -31,12 +31,13 @@
#include <sys/types.h>
#include <sys/socket.h>
+#include <ssp/ssp.h>
#include "libc_private.h"
#include <stddef.h>
ssize_t
-recv(int s, void *buf, size_t len, int flags)
+__ssp_real(recv)(int s, void *buf, size_t len, int flags)
{
/*
* POSIX says recv() shall be a cancellation point, so call the
diff --git a/lib/libc/sys/recvfrom.c b/lib/libc/sys/recvfrom.c
--- a/lib/libc/sys/recvfrom.c
+++ b/lib/libc/sys/recvfrom.c
@@ -32,13 +32,14 @@
#include <sys/types.h>
#include <sys/syscall.h>
#include <sys/socket.h>
+#include <ssp/ssp.h>
#include "libc_private.h"
__weak_reference(__sys_recvfrom, __recvfrom);
#pragma weak recvfrom
ssize_t
-recvfrom(int s, void *buf, size_t len, int flags,
+__ssp_real(recvfrom)(int s, void *buf, size_t len, int flags,
struct sockaddr * __restrict from, socklen_t * __restrict fromlen)
{
return (INTERPOS_SYS(recvfrom, s, buf, len, flags, from, fromlen));
diff --git a/lib/libc/sys/recvmsg.c b/lib/libc/sys/recvmsg.c
--- a/lib/libc/sys/recvmsg.c
+++ b/lib/libc/sys/recvmsg.c
@@ -32,13 +32,14 @@
#include <sys/types.h>
#include <sys/syscall.h>
#include <sys/socket.h>
+#include <ssp/ssp.h>
#include "libc_private.h"
__weak_reference(__sys_recvmsg, __recvmsg);
#pragma weak recvmsg
ssize_t
-recvmsg(int s, struct msghdr *msg, int flags)
+__ssp_real(recvmsg)(int s, struct msghdr *msg, int flags)
{
return (INTERPOS_SYS(recvmsg, s, msg, flags));
}
diff --git a/lib/libc/tests/secure/Makefile b/lib/libc/tests/secure/Makefile
--- a/lib/libc/tests/secure/Makefile
+++ b/lib/libc/tests/secure/Makefile
@@ -6,6 +6,7 @@
# sys/ headers
FORTIFY_TCATS+= random
FORTIFY_TCATS+= select
+FORTIFY_TCATS+= socket
FORTIFY_TCATS+= uio
# non-sys/ headers
diff --git a/lib/libc/tests/secure/fortify_poll_test.c b/lib/libc/tests/secure/fortify_poll_test.c
--- a/lib/libc/tests/secure/fortify_poll_test.c
+++ b/lib/libc/tests/secure/fortify_poll_test.c
@@ -7,6 +7,7 @@
#include <sys/random.h>
#include <sys/resource.h>
#include <sys/select.h>
+#include <sys/socket.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/wait.h>
@@ -65,6 +66,50 @@
return (linkname);
}
+/*
+ * For our purposes, first descriptor will be the reader; we'll send both
+ * raw data and a control message over it so that the result can be used for
+ * any of our recv*() tests.
+ */
+static void __unused
+new_socket(int sock[2])
+{
+ unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 };
+ static char sockbuf[256];
+ ssize_t rv;
+ size_t total = 0;
+ struct msghdr hdr = { 0 };
+ struct cmsghdr *cmsg;
+ int error, fd;
+
+ error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
+ ATF_REQUIRE(error == 0);
+
+ while (total != sizeof(sockbuf)) {
+ rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0);
+
+ ATF_REQUIRE_MSG(rv > 0,
+ "expected bytes sent, got %zd with %zu left (size %zu, total %zu)",
+ rv, sizeof(sockbuf) - total, sizeof(sockbuf), total);
+ ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf),
+ "%zd exceeds total %zu", rv, sizeof(sockbuf));
+ total += rv;
+ }
+
+ hdr.msg_control = ctrl;
+ hdr.msg_controllen = sizeof(ctrl);
+
+ cmsg = CMSG_FIRSTHDR(&hdr);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+ fd = STDIN_FILENO;
+ memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
+
+ error = sendmsg(sock[1], &hdr, 0);
+ ATF_REQUIRE(error != -1);
+}
+
/*
* Constructs a tmpfile that we can use for testing read(2) and friends.
*/
diff --git a/lib/libc/tests/secure/fortify_random_test.c b/lib/libc/tests/secure/fortify_random_test.c
--- a/lib/libc/tests/secure/fortify_random_test.c
+++ b/lib/libc/tests/secure/fortify_random_test.c
@@ -7,6 +7,7 @@
#include <sys/random.h>
#include <sys/resource.h>
#include <sys/select.h>
+#include <sys/socket.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/wait.h>
@@ -65,6 +66,50 @@
return (linkname);
}
+/*
+ * For our purposes, first descriptor will be the reader; we'll send both
+ * raw data and a control message over it so that the result can be used for
+ * any of our recv*() tests.
+ */
+static void __unused
+new_socket(int sock[2])
+{
+ unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 };
+ static char sockbuf[256];
+ ssize_t rv;
+ size_t total = 0;
+ struct msghdr hdr = { 0 };
+ struct cmsghdr *cmsg;
+ int error, fd;
+
+ error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
+ ATF_REQUIRE(error == 0);
+
+ while (total != sizeof(sockbuf)) {
+ rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0);
+
+ ATF_REQUIRE_MSG(rv > 0,
+ "expected bytes sent, got %zd with %zu left (size %zu, total %zu)",
+ rv, sizeof(sockbuf) - total, sizeof(sockbuf), total);
+ ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf),
+ "%zd exceeds total %zu", rv, sizeof(sockbuf));
+ total += rv;
+ }
+
+ hdr.msg_control = ctrl;
+ hdr.msg_controllen = sizeof(ctrl);
+
+ cmsg = CMSG_FIRSTHDR(&hdr);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+ fd = STDIN_FILENO;
+ memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
+
+ error = sendmsg(sock[1], &hdr, 0);
+ ATF_REQUIRE(error != -1);
+}
+
/*
* Constructs a tmpfile that we can use for testing read(2) and friends.
*/
diff --git a/lib/libc/tests/secure/fortify_select_test.c b/lib/libc/tests/secure/fortify_select_test.c
--- a/lib/libc/tests/secure/fortify_select_test.c
+++ b/lib/libc/tests/secure/fortify_select_test.c
@@ -7,6 +7,7 @@
#include <sys/random.h>
#include <sys/resource.h>
#include <sys/select.h>
+#include <sys/socket.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/wait.h>
@@ -65,6 +66,50 @@
return (linkname);
}
+/*
+ * For our purposes, first descriptor will be the reader; we'll send both
+ * raw data and a control message over it so that the result can be used for
+ * any of our recv*() tests.
+ */
+static void __unused
+new_socket(int sock[2])
+{
+ unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 };
+ static char sockbuf[256];
+ ssize_t rv;
+ size_t total = 0;
+ struct msghdr hdr = { 0 };
+ struct cmsghdr *cmsg;
+ int error, fd;
+
+ error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
+ ATF_REQUIRE(error == 0);
+
+ while (total != sizeof(sockbuf)) {
+ rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0);
+
+ ATF_REQUIRE_MSG(rv > 0,
+ "expected bytes sent, got %zd with %zu left (size %zu, total %zu)",
+ rv, sizeof(sockbuf) - total, sizeof(sockbuf), total);
+ ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf),
+ "%zd exceeds total %zu", rv, sizeof(sockbuf));
+ total += rv;
+ }
+
+ hdr.msg_control = ctrl;
+ hdr.msg_controllen = sizeof(ctrl);
+
+ cmsg = CMSG_FIRSTHDR(&hdr);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+ fd = STDIN_FILENO;
+ memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
+
+ error = sendmsg(sock[1], &hdr, 0);
+ ATF_REQUIRE(error != -1);
+}
+
/*
* Constructs a tmpfile that we can use for testing read(2) and friends.
*/
diff --git a/lib/libc/tests/secure/fortify_socket_test.c b/lib/libc/tests/secure/fortify_socket_test.c
new file mode 100644
--- /dev/null
+++ b/lib/libc/tests/secure/fortify_socket_test.c
@@ -0,0 +1,1697 @@
+/* @generated by generate-fortify_test.lua */
+
+#define _FORTIFY_SOURCE 2
+#define TMPFILE_SIZE (1024 * 32)
+
+#include <sys/param.h>
+#include <sys/random.h>
+#include <sys/resource.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <sys/wait.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <poll.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+#include <unistd.h>
+#include <wchar.h>
+#include <atf-c.h>
+
+static FILE * __unused
+new_fp(size_t __len)
+{
+ static char fpbuf[LINE_MAX];
+ FILE *fp;
+
+ ATF_REQUIRE(__len <= sizeof(fpbuf));
+
+ memset(fpbuf, 'A', sizeof(fpbuf) - 1);
+ fpbuf[sizeof(fpbuf) - 1] = '\0';
+
+ fp = fmemopen(fpbuf, sizeof(fpbuf), "rb");
+ ATF_REQUIRE(fp != NULL);
+
+ return (fp);
+}
+
+/*
+ * Create a new symlink to use for readlink(2) style tests, we'll just use a
+ * random target name to have something interesting to look at.
+ */
+static const char * __unused
+new_link(size_t __len)
+{
+ static const char linkname[] = "link";
+ char target[MAXNAMLEN];
+ int error;
+
+ ATF_REQUIRE(__len <= sizeof(target));
+
+ arc4random_buf(target, sizeof(target));
+
+ error = unlink(linkname);
+ ATF_REQUIRE(error == 0 || errno == ENOENT);
+
+ error = symlink(target, linkname);
+ ATF_REQUIRE(error == 0);
+
+ return (linkname);
+}
+
+/*
+ * For our purposes, first descriptor will be the reader; we'll send both
+ * raw data and a control message over it so that the result can be used for
+ * any of our recv*() tests.
+ */
+static void __unused
+new_socket(int sock[2])
+{
+ unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 };
+ static char sockbuf[256];
+ ssize_t rv;
+ size_t total = 0;
+ struct msghdr hdr = { 0 };
+ struct cmsghdr *cmsg;
+ int error, fd;
+
+ error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
+ ATF_REQUIRE(error == 0);
+
+ while (total != sizeof(sockbuf)) {
+ rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0);
+
+ ATF_REQUIRE_MSG(rv > 0,
+ "expected bytes sent, got %zd with %zu left (size %zu, total %zu)",
+ rv, sizeof(sockbuf) - total, sizeof(sockbuf), total);
+ ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf),
+ "%zd exceeds total %zu", rv, sizeof(sockbuf));
+ total += rv;
+ }
+
+ hdr.msg_control = ctrl;
+ hdr.msg_controllen = sizeof(ctrl);
+
+ cmsg = CMSG_FIRSTHDR(&hdr);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+ fd = STDIN_FILENO;
+ memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
+
+ error = sendmsg(sock[1], &hdr, 0);
+ ATF_REQUIRE(error != -1);
+}
+
+/*
+ * Constructs a tmpfile that we can use for testing read(2) and friends.
+ */
+static int __unused
+new_tmpfile(void)
+{
+ char buf[1024];
+ ssize_t rv;
+ size_t written;
+ int fd;
+
+ fd = open("tmpfile", O_RDWR | O_CREAT | O_TRUNC, 0644);
+ ATF_REQUIRE(fd >= 0);
+
+ written = 0;
+ while (written < TMPFILE_SIZE) {
+ rv = write(fd, buf, sizeof(buf));
+ ATF_REQUIRE(rv > 0);
+
+ written += rv;
+ }
+
+ lseek(fd, 0, SEEK_SET);
+ return (fd);
+}
+
+static void
+disable_coredumps(void)
+{
+ struct rlimit rl = { 0 };
+
+ setrlimit(RLIMIT_CORE, &rl);
+}
+
+/*
+ * Replaces stdin with a file that we can actually read from, for tests where
+ * we want a FILE * or fd that we can get data from.
+ */
+static void __unused
+replace_stdin(void)
+{
+ int fd;
+
+ fd = new_tmpfile();
+
+ (void)dup2(fd, STDIN_FILENO);
+ if (fd != STDIN_FILENO)
+ close(fd);
+}
+
+ATF_TC_WITHOUT_HEAD(getpeername_before_end);
+ATF_TC_BODY(getpeername_before_end, tc)
+{
+#define BUF &__stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct sockaddr __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(__stack.__buf);
+ const size_t __len = sizeof(struct sockaddr) - 1;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ socklen_t socklen;
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+ socklen = __len;
+
+ getpeername(sock[0], &__stack.__buf, &socklen);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(getpeername_end);
+ATF_TC_BODY(getpeername_end, tc)
+{
+#define BUF &__stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct sockaddr __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(__stack.__buf);
+ const size_t __len = sizeof(struct sockaddr);
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ socklen_t socklen;
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+ socklen = __len;
+
+ getpeername(sock[0], &__stack.__buf, &socklen);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(getpeername_heap_before_end);
+ATF_TC_BODY(getpeername_heap_before_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct sockaddr * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1);
+ const size_t __len = sizeof(struct sockaddr) - 1;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ socklen_t socklen;
+ __stack.__buf = malloc(__bufsz);
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+ socklen = __len;
+
+ getpeername(sock[0], __stack.__buf, &socklen);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(getpeername_heap_end);
+ATF_TC_BODY(getpeername_heap_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct sockaddr * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1);
+ const size_t __len = sizeof(struct sockaddr);
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ socklen_t socklen;
+ __stack.__buf = malloc(__bufsz);
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+ socklen = __len;
+
+ getpeername(sock[0], __stack.__buf, &socklen);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(getpeername_heap_after_end);
+ATF_TC_BODY(getpeername_heap_after_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct sockaddr * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1);
+ const size_t __len = sizeof(struct sockaddr) + 1;
+ const size_t __idx __unused = __len - 1;
+ pid_t __child;
+ int __status;
+ int sock[2] = { -1, -1 };
+ socklen_t socklen;
+ __child = fork();
+ ATF_REQUIRE(__child >= 0);
+ if (__child > 0)
+ goto monitor;
+
+ /* Child */
+ disable_coredumps();
+ __stack.__buf = malloc(__bufsz);
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+ socklen = __len;
+
+ getpeername(sock[0], __stack.__buf, &socklen);
+ _exit(1); /* Should have aborted. */
+
+monitor:
+ while (waitpid(__child, &__status, 0) != __child) {
+ ATF_REQUIRE_EQ(EINTR, errno);
+ }
+
+ ATF_REQUIRE_MSG(WIFSIGNALED(__status), "not signaled, status %x", __status);
+ ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(getsockname_before_end);
+ATF_TC_BODY(getsockname_before_end, tc)
+{
+#define BUF &__stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct sockaddr __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(__stack.__buf);
+ const size_t __len = sizeof(struct sockaddr) - 1;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ socklen_t socklen;
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+ socklen = __len;
+
+ getsockname(sock[0], &__stack.__buf, &socklen);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(getsockname_end);
+ATF_TC_BODY(getsockname_end, tc)
+{
+#define BUF &__stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct sockaddr __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(__stack.__buf);
+ const size_t __len = sizeof(struct sockaddr);
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ socklen_t socklen;
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+ socklen = __len;
+
+ getsockname(sock[0], &__stack.__buf, &socklen);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(getsockname_heap_before_end);
+ATF_TC_BODY(getsockname_heap_before_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct sockaddr * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1);
+ const size_t __len = sizeof(struct sockaddr) - 1;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ socklen_t socklen;
+ __stack.__buf = malloc(__bufsz);
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+ socklen = __len;
+
+ getsockname(sock[0], __stack.__buf, &socklen);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(getsockname_heap_end);
+ATF_TC_BODY(getsockname_heap_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct sockaddr * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1);
+ const size_t __len = sizeof(struct sockaddr);
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ socklen_t socklen;
+ __stack.__buf = malloc(__bufsz);
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+ socklen = __len;
+
+ getsockname(sock[0], __stack.__buf, &socklen);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(getsockname_heap_after_end);
+ATF_TC_BODY(getsockname_heap_after_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct sockaddr * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1);
+ const size_t __len = sizeof(struct sockaddr) + 1;
+ const size_t __idx __unused = __len - 1;
+ pid_t __child;
+ int __status;
+ int sock[2] = { -1, -1 };
+ socklen_t socklen;
+ __child = fork();
+ ATF_REQUIRE(__child >= 0);
+ if (__child > 0)
+ goto monitor;
+
+ /* Child */
+ disable_coredumps();
+ __stack.__buf = malloc(__bufsz);
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+ socklen = __len;
+
+ getsockname(sock[0], __stack.__buf, &socklen);
+ _exit(1); /* Should have aborted. */
+
+monitor:
+ while (waitpid(__child, &__status, 0) != __child) {
+ ATF_REQUIRE_EQ(EINTR, errno);
+ }
+
+ ATF_REQUIRE_MSG(WIFSIGNALED(__status), "not signaled, status %x", __status);
+ ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recv_before_end);
+ATF_TC_BODY(recv_before_end, tc)
+{
+#define BUF &__stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char __buf[42];
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(__stack.__buf);
+ const size_t __len = 42 - 1;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+
+ recv(sock[0], __stack.__buf, __len, 0);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recv_end);
+ATF_TC_BODY(recv_end, tc)
+{
+#define BUF &__stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char __buf[42];
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(__stack.__buf);
+ const size_t __len = 42;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+
+ recv(sock[0], __stack.__buf, __len, 0);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recv_heap_before_end);
+ATF_TC_BODY(recv_heap_before_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
+ const size_t __len = 42 - 1;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+
+ __stack.__buf = malloc(__bufsz);
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+
+ recv(sock[0], __stack.__buf, __len, 0);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recv_heap_end);
+ATF_TC_BODY(recv_heap_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
+ const size_t __len = 42;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+
+ __stack.__buf = malloc(__bufsz);
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+
+ recv(sock[0], __stack.__buf, __len, 0);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recv_heap_after_end);
+ATF_TC_BODY(recv_heap_after_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
+ const size_t __len = 42 + 1;
+ const size_t __idx __unused = __len - 1;
+ pid_t __child;
+ int __status;
+ int sock[2] = { -1, -1 };
+
+ __child = fork();
+ ATF_REQUIRE(__child >= 0);
+ if (__child > 0)
+ goto monitor;
+
+ /* Child */
+ disable_coredumps();
+ __stack.__buf = malloc(__bufsz);
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+
+ recv(sock[0], __stack.__buf, __len, 0);
+ _exit(1); /* Should have aborted. */
+
+monitor:
+ while (waitpid(__child, &__status, 0) != __child) {
+ ATF_REQUIRE_EQ(EINTR, errno);
+ }
+
+ ATF_REQUIRE_MSG(WIFSIGNALED(__status), "not signaled, status %x", __status);
+ ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvfrom_before_end);
+ATF_TC_BODY(recvfrom_before_end, tc)
+{
+#define BUF &__stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char __buf[42];
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(__stack.__buf);
+ const size_t __len = 42 - 1;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+
+ recvfrom(sock[0], __stack.__buf, __len, 0, NULL, NULL);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvfrom_end);
+ATF_TC_BODY(recvfrom_end, tc)
+{
+#define BUF &__stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char __buf[42];
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(__stack.__buf);
+ const size_t __len = 42;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+
+ recvfrom(sock[0], __stack.__buf, __len, 0, NULL, NULL);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvfrom_heap_before_end);
+ATF_TC_BODY(recvfrom_heap_before_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
+ const size_t __len = 42 - 1;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+
+ __stack.__buf = malloc(__bufsz);
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+
+ recvfrom(sock[0], __stack.__buf, __len, 0, NULL, NULL);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvfrom_heap_end);
+ATF_TC_BODY(recvfrom_heap_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
+ const size_t __len = 42;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+
+ __stack.__buf = malloc(__bufsz);
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+
+ recvfrom(sock[0], __stack.__buf, __len, 0, NULL, NULL);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvfrom_heap_after_end);
+ATF_TC_BODY(recvfrom_heap_after_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
+ const size_t __len = 42 + 1;
+ const size_t __idx __unused = __len - 1;
+ pid_t __child;
+ int __status;
+ int sock[2] = { -1, -1 };
+
+ __child = fork();
+ ATF_REQUIRE(__child >= 0);
+ if (__child > 0)
+ goto monitor;
+
+ /* Child */
+ disable_coredumps();
+ __stack.__buf = malloc(__bufsz);
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+
+ recvfrom(sock[0], __stack.__buf, __len, 0, NULL, NULL);
+ _exit(1); /* Should have aborted. */
+
+monitor:
+ while (waitpid(__child, &__status, 0) != __child) {
+ ATF_REQUIRE_EQ(EINTR, errno);
+ }
+
+ ATF_REQUIRE_MSG(WIFSIGNALED(__status), "not signaled, status %x", __status);
+ ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvfrom_sockaddr_before_end);
+ATF_TC_BODY(recvfrom_sockaddr_before_end, tc)
+{
+#define BUF &__stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct sockaddr __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(__stack.__buf);
+ const size_t __len = sizeof(struct sockaddr) - 1;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ char data[16];
+ socklen_t socklen;
+
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+ socklen = __len;
+
+ recvfrom(sock[0], data, sizeof(data), 0, &__stack.__buf, &socklen);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvfrom_sockaddr_end);
+ATF_TC_BODY(recvfrom_sockaddr_end, tc)
+{
+#define BUF &__stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct sockaddr __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(__stack.__buf);
+ const size_t __len = sizeof(struct sockaddr);
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ char data[16];
+ socklen_t socklen;
+
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+ socklen = __len;
+
+ recvfrom(sock[0], data, sizeof(data), 0, &__stack.__buf, &socklen);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvfrom_sockaddr_heap_before_end);
+ATF_TC_BODY(recvfrom_sockaddr_heap_before_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct sockaddr * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1);
+ const size_t __len = sizeof(struct sockaddr) - 1;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ char data[16];
+ socklen_t socklen;
+
+ __stack.__buf = malloc(__bufsz);
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+ socklen = __len;
+
+ recvfrom(sock[0], data, sizeof(data), 0, __stack.__buf, &socklen);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvfrom_sockaddr_heap_end);
+ATF_TC_BODY(recvfrom_sockaddr_heap_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct sockaddr * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1);
+ const size_t __len = sizeof(struct sockaddr);
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ char data[16];
+ socklen_t socklen;
+
+ __stack.__buf = malloc(__bufsz);
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+ socklen = __len;
+
+ recvfrom(sock[0], data, sizeof(data), 0, __stack.__buf, &socklen);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvfrom_sockaddr_heap_after_end);
+ATF_TC_BODY(recvfrom_sockaddr_heap_after_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct sockaddr * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1);
+ const size_t __len = sizeof(struct sockaddr) + 1;
+ const size_t __idx __unused = __len - 1;
+ pid_t __child;
+ int __status;
+ int sock[2] = { -1, -1 };
+ char data[16];
+ socklen_t socklen;
+
+ __child = fork();
+ ATF_REQUIRE(__child >= 0);
+ if (__child > 0)
+ goto monitor;
+
+ /* Child */
+ disable_coredumps();
+ __stack.__buf = malloc(__bufsz);
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+ socklen = __len;
+
+ recvfrom(sock[0], data, sizeof(data), 0, __stack.__buf, &socklen);
+ _exit(1); /* Should have aborted. */
+
+monitor:
+ while (waitpid(__child, &__status, 0) != __child) {
+ ATF_REQUIRE_EQ(EINTR, errno);
+ }
+
+ ATF_REQUIRE_MSG(WIFSIGNALED(__status), "not signaled, status %x", __status);
+ ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmsg_msg_name_before_end);
+ATF_TC_BODY(recvmsg_msg_name_before_end, tc)
+{
+#define BUF &__stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct sockaddr __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(__stack.__buf);
+ const size_t __len = sizeof(struct sockaddr) - 1;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ struct msghdr msg;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_name = BUF;
+ msg.msg_namelen = __len;
+
+ recvmsg(sock[0], &msg, 0);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmsg_msg_name_end);
+ATF_TC_BODY(recvmsg_msg_name_end, tc)
+{
+#define BUF &__stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct sockaddr __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(__stack.__buf);
+ const size_t __len = sizeof(struct sockaddr);
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ struct msghdr msg;
+
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_name = BUF;
+ msg.msg_namelen = __len;
+
+ recvmsg(sock[0], &msg, 0);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmsg_msg_name_heap_before_end);
+ATF_TC_BODY(recvmsg_msg_name_heap_before_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct sockaddr * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1);
+ const size_t __len = sizeof(struct sockaddr) - 1;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ struct msghdr msg;
+
+ __stack.__buf = malloc(__bufsz);
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_name = BUF;
+ msg.msg_namelen = __len;
+
+ recvmsg(sock[0], &msg, 0);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmsg_msg_name_heap_end);
+ATF_TC_BODY(recvmsg_msg_name_heap_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct sockaddr * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1);
+ const size_t __len = sizeof(struct sockaddr);
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ struct msghdr msg;
+
+ __stack.__buf = malloc(__bufsz);
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_name = BUF;
+ msg.msg_namelen = __len;
+
+ recvmsg(sock[0], &msg, 0);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmsg_msg_name_heap_after_end);
+ATF_TC_BODY(recvmsg_msg_name_heap_after_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct sockaddr * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (1);
+ const size_t __len = sizeof(struct sockaddr) + 1;
+ const size_t __idx __unused = __len - 1;
+ pid_t __child;
+ int __status;
+ int sock[2] = { -1, -1 };
+ struct msghdr msg;
+
+ __child = fork();
+ ATF_REQUIRE(__child >= 0);
+ if (__child > 0)
+ goto monitor;
+
+ /* Child */
+ disable_coredumps();
+ __stack.__buf = malloc(__bufsz);
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_name = BUF;
+ msg.msg_namelen = __len;
+
+ recvmsg(sock[0], &msg, 0);
+ _exit(1); /* Should have aborted. */
+
+monitor:
+ while (waitpid(__child, &__status, 0) != __child) {
+ ATF_REQUIRE_EQ(EINTR, errno);
+ }
+
+ ATF_REQUIRE_MSG(WIFSIGNALED(__status), "not signaled, status %x", __status);
+ ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmsg_msg_iov_before_end);
+ATF_TC_BODY(recvmsg_msg_iov_before_end, tc)
+{
+#define BUF &__stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char __buf[42];
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(__stack.__buf);
+ const size_t __len = 42 - 1;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ struct msghdr msg;
+ struct iovec iov[2];
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&iov[0], 0, sizeof(iov));
+
+ /*
+ * We position the buffer second just so that we can confirm that the
+ * fortification bits are traversing the iovec correctly.
+ */
+ iov[1].iov_base = BUF;
+ iov[1].iov_len = __len;
+
+ msg.msg_iov = &iov[0];
+ msg.msg_iovlen = nitems(iov);
+
+ recvmsg(sock[0], &msg, 0);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmsg_msg_iov_end);
+ATF_TC_BODY(recvmsg_msg_iov_end, tc)
+{
+#define BUF &__stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char __buf[42];
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(__stack.__buf);
+ const size_t __len = 42;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ struct msghdr msg;
+ struct iovec iov[2];
+
+ memset(&msg, 0, sizeof(msg));
+ memset(&iov[0], 0, sizeof(iov));
+
+ /*
+ * We position the buffer second just so that we can confirm that the
+ * fortification bits are traversing the iovec correctly.
+ */
+ iov[1].iov_base = BUF;
+ iov[1].iov_len = __len;
+
+ msg.msg_iov = &iov[0];
+ msg.msg_iovlen = nitems(iov);
+
+ recvmsg(sock[0], &msg, 0);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmsg_msg_iov_heap_before_end);
+ATF_TC_BODY(recvmsg_msg_iov_heap_before_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
+ const size_t __len = 42 - 1;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ struct msghdr msg;
+ struct iovec iov[2];
+
+ __stack.__buf = malloc(__bufsz);
+ memset(&msg, 0, sizeof(msg));
+ memset(&iov[0], 0, sizeof(iov));
+
+ /*
+ * We position the buffer second just so that we can confirm that the
+ * fortification bits are traversing the iovec correctly.
+ */
+ iov[1].iov_base = BUF;
+ iov[1].iov_len = __len;
+
+ msg.msg_iov = &iov[0];
+ msg.msg_iovlen = nitems(iov);
+
+ recvmsg(sock[0], &msg, 0);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmsg_msg_iov_heap_end);
+ATF_TC_BODY(recvmsg_msg_iov_heap_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
+ const size_t __len = 42;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ struct msghdr msg;
+ struct iovec iov[2];
+
+ __stack.__buf = malloc(__bufsz);
+ memset(&msg, 0, sizeof(msg));
+ memset(&iov[0], 0, sizeof(iov));
+
+ /*
+ * We position the buffer second just so that we can confirm that the
+ * fortification bits are traversing the iovec correctly.
+ */
+ iov[1].iov_base = BUF;
+ iov[1].iov_len = __len;
+
+ msg.msg_iov = &iov[0];
+ msg.msg_iovlen = nitems(iov);
+
+ recvmsg(sock[0], &msg, 0);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmsg_msg_iov_heap_after_end);
+ATF_TC_BODY(recvmsg_msg_iov_heap_after_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
+ const size_t __len = 42 + 1;
+ const size_t __idx __unused = __len - 1;
+ pid_t __child;
+ int __status;
+ int sock[2] = { -1, -1 };
+ struct msghdr msg;
+ struct iovec iov[2];
+
+ __child = fork();
+ ATF_REQUIRE(__child >= 0);
+ if (__child > 0)
+ goto monitor;
+
+ /* Child */
+ disable_coredumps();
+ __stack.__buf = malloc(__bufsz);
+ memset(&msg, 0, sizeof(msg));
+ memset(&iov[0], 0, sizeof(iov));
+
+ /*
+ * We position the buffer second just so that we can confirm that the
+ * fortification bits are traversing the iovec correctly.
+ */
+ iov[1].iov_base = BUF;
+ iov[1].iov_len = __len;
+
+ msg.msg_iov = &iov[0];
+ msg.msg_iovlen = nitems(iov);
+
+ recvmsg(sock[0], &msg, 0);
+ _exit(1); /* Should have aborted. */
+
+monitor:
+ while (waitpid(__child, &__status, 0) != __child) {
+ ATF_REQUIRE_EQ(EINTR, errno);
+ }
+
+ ATF_REQUIRE_MSG(WIFSIGNALED(__status), "not signaled, status %x", __status);
+ ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmsg_msg_control_before_end);
+ATF_TC_BODY(recvmsg_msg_control_before_end, tc)
+{
+#define BUF &__stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char __buf[CMSG_SPACE(sizeof(int))];
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(__stack.__buf);
+ const size_t __len = CMSG_SPACE(sizeof(int)) - 1;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ struct msghdr msg;
+
+ memset(&msg, 0, sizeof(msg));
+
+ msg.msg_control = BUF;
+ msg.msg_controllen = __len;
+
+ recvmsg(sock[0], &msg, 0);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmsg_msg_control_end);
+ATF_TC_BODY(recvmsg_msg_control_end, tc)
+{
+#define BUF &__stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char __buf[CMSG_SPACE(sizeof(int))];
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(__stack.__buf);
+ const size_t __len = CMSG_SPACE(sizeof(int));
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ struct msghdr msg;
+
+ memset(&msg, 0, sizeof(msg));
+
+ msg.msg_control = BUF;
+ msg.msg_controllen = __len;
+
+ recvmsg(sock[0], &msg, 0);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmsg_msg_control_heap_before_end);
+ATF_TC_BODY(recvmsg_msg_control_heap_before_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (CMSG_SPACE(sizeof(int)));
+ const size_t __len = CMSG_SPACE(sizeof(int)) - 1;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ struct msghdr msg;
+
+ __stack.__buf = malloc(__bufsz);
+ memset(&msg, 0, sizeof(msg));
+
+ msg.msg_control = BUF;
+ msg.msg_controllen = __len;
+
+ recvmsg(sock[0], &msg, 0);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmsg_msg_control_heap_end);
+ATF_TC_BODY(recvmsg_msg_control_heap_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (CMSG_SPACE(sizeof(int)));
+ const size_t __len = CMSG_SPACE(sizeof(int));
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ struct msghdr msg;
+
+ __stack.__buf = malloc(__bufsz);
+ memset(&msg, 0, sizeof(msg));
+
+ msg.msg_control = BUF;
+ msg.msg_controllen = __len;
+
+ recvmsg(sock[0], &msg, 0);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmsg_msg_control_heap_after_end);
+ATF_TC_BODY(recvmsg_msg_control_heap_after_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (CMSG_SPACE(sizeof(int)));
+ const size_t __len = CMSG_SPACE(sizeof(int)) + 1;
+ const size_t __idx __unused = __len - 1;
+ pid_t __child;
+ int __status;
+ int sock[2] = { -1, -1 };
+ struct msghdr msg;
+
+ __child = fork();
+ ATF_REQUIRE(__child >= 0);
+ if (__child > 0)
+ goto monitor;
+
+ /* Child */
+ disable_coredumps();
+ __stack.__buf = malloc(__bufsz);
+ memset(&msg, 0, sizeof(msg));
+
+ msg.msg_control = BUF;
+ msg.msg_controllen = __len;
+
+ recvmsg(sock[0], &msg, 0);
+ _exit(1); /* Should have aborted. */
+
+monitor:
+ while (waitpid(__child, &__status, 0) != __child) {
+ ATF_REQUIRE_EQ(EINTR, errno);
+ }
+
+ ATF_REQUIRE_MSG(WIFSIGNALED(__status), "not signaled, status %x", __status);
+ ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmmsg_msgvec_before_end);
+ATF_TC_BODY(recvmmsg_msgvec_before_end, tc)
+{
+#define BUF &__stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct mmsghdr __buf[2];
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(__stack.__buf);
+ const size_t __len = 2 - 1;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+
+ recvmmsg(sock[0], __stack.__buf, __len, 0, NULL);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmmsg_msgvec_end);
+ATF_TC_BODY(recvmmsg_msgvec_end, tc)
+{
+#define BUF &__stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct mmsghdr __buf[2];
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(__stack.__buf);
+ const size_t __len = 2;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+
+ recvmmsg(sock[0], __stack.__buf, __len, 0, NULL);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmmsg_msgvec_after_end);
+ATF_TC_BODY(recvmmsg_msgvec_after_end, tc)
+{
+#define BUF &__stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct mmsghdr __buf[2];
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(__stack.__buf);
+ const size_t __len = 2 + 1;
+ const size_t __idx __unused = __len - 1;
+ pid_t __child;
+ int __status;
+ int sock[2] = { -1, -1 };
+
+ __child = fork();
+ ATF_REQUIRE(__child >= 0);
+ if (__child > 0)
+ goto monitor;
+
+ /* Child */
+ disable_coredumps();
+ recvmmsg(sock[0], __stack.__buf, __len, 0, NULL);
+ _exit(1); /* Should have aborted. */
+
+monitor:
+ while (waitpid(__child, &__status, 0) != __child) {
+ ATF_REQUIRE_EQ(EINTR, errno);
+ }
+
+ ATF_REQUIRE_MSG(WIFSIGNALED(__status), "not signaled, status %x", __status);
+ ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmmsg_msgvec_heap_before_end);
+ATF_TC_BODY(recvmmsg_msgvec_heap_before_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct mmsghdr * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (2);
+ const size_t __len = 2 - 1;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+
+ __stack.__buf = malloc(__bufsz);
+
+ recvmmsg(sock[0], __stack.__buf, __len, 0, NULL);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmmsg_msgvec_heap_end);
+ATF_TC_BODY(recvmmsg_msgvec_heap_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct mmsghdr * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (2);
+ const size_t __len = 2;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+
+ __stack.__buf = malloc(__bufsz);
+
+ recvmmsg(sock[0], __stack.__buf, __len, 0, NULL);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmmsg_msgvec_heap_after_end);
+ATF_TC_BODY(recvmmsg_msgvec_heap_after_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ struct mmsghdr * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (2);
+ const size_t __len = 2 + 1;
+ const size_t __idx __unused = __len - 1;
+ pid_t __child;
+ int __status;
+ int sock[2] = { -1, -1 };
+
+ __child = fork();
+ ATF_REQUIRE(__child >= 0);
+ if (__child > 0)
+ goto monitor;
+
+ /* Child */
+ disable_coredumps();
+ __stack.__buf = malloc(__bufsz);
+
+ recvmmsg(sock[0], __stack.__buf, __len, 0, NULL);
+ _exit(1); /* Should have aborted. */
+
+monitor:
+ while (waitpid(__child, &__status, 0) != __child) {
+ ATF_REQUIRE_EQ(EINTR, errno);
+ }
+
+ ATF_REQUIRE_MSG(WIFSIGNALED(__status), "not signaled, status %x", __status);
+ ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmmsg_msghdr_before_end);
+ATF_TC_BODY(recvmmsg_msghdr_before_end, tc)
+{
+#define BUF &__stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char __buf[42];
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(__stack.__buf);
+ const size_t __len = 42 - 1;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ struct mmsghdr msgvec[2];
+
+ memset(&msgvec[0], 0, sizeof(msgvec));
+
+ /*
+ * Same as above, make sure fortification isn't ignoring n > 1 elements
+ * of the msgvec.
+ */
+ msgvec[1].msg_hdr.msg_control = BUF;
+ msgvec[1].msg_hdr.msg_controllen = __len;
+
+ recvmmsg(sock[0], &msgvec[0], nitems(msgvec), 0, NULL);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmmsg_msghdr_end);
+ATF_TC_BODY(recvmmsg_msghdr_end, tc)
+{
+#define BUF &__stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char __buf[42];
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(__stack.__buf);
+ const size_t __len = 42;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ struct mmsghdr msgvec[2];
+
+ memset(&msgvec[0], 0, sizeof(msgvec));
+
+ /*
+ * Same as above, make sure fortification isn't ignoring n > 1 elements
+ * of the msgvec.
+ */
+ msgvec[1].msg_hdr.msg_control = BUF;
+ msgvec[1].msg_hdr.msg_controllen = __len;
+
+ recvmmsg(sock[0], &msgvec[0], nitems(msgvec), 0, NULL);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmmsg_msghdr_heap_before_end);
+ATF_TC_BODY(recvmmsg_msghdr_heap_before_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
+ const size_t __len = 42 - 1;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ struct mmsghdr msgvec[2];
+
+ __stack.__buf = malloc(__bufsz);
+ memset(&msgvec[0], 0, sizeof(msgvec));
+
+ /*
+ * Same as above, make sure fortification isn't ignoring n > 1 elements
+ * of the msgvec.
+ */
+ msgvec[1].msg_hdr.msg_control = BUF;
+ msgvec[1].msg_hdr.msg_controllen = __len;
+
+ recvmmsg(sock[0], &msgvec[0], nitems(msgvec), 0, NULL);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmmsg_msghdr_heap_end);
+ATF_TC_BODY(recvmmsg_msghdr_heap_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
+ const size_t __len = 42;
+ const size_t __idx __unused = __len - 1;
+ int sock[2] = { -1, -1 };
+ struct mmsghdr msgvec[2];
+
+ __stack.__buf = malloc(__bufsz);
+ memset(&msgvec[0], 0, sizeof(msgvec));
+
+ /*
+ * Same as above, make sure fortification isn't ignoring n > 1 elements
+ * of the msgvec.
+ */
+ msgvec[1].msg_hdr.msg_control = BUF;
+ msgvec[1].msg_hdr.msg_controllen = __len;
+
+ recvmmsg(sock[0], &msgvec[0], nitems(msgvec), 0, NULL);
+#undef BUF
+
+}
+
+ATF_TC_WITHOUT_HEAD(recvmmsg_msghdr_heap_after_end);
+ATF_TC_BODY(recvmmsg_msghdr_heap_after_end, tc)
+{
+#define BUF __stack.__buf
+ struct {
+ uint8_t padding_l;
+ unsigned char * __buf;
+ uint8_t padding_r;
+ } __stack;
+ const size_t __bufsz __unused = sizeof(*__stack.__buf) * (42);
+ const size_t __len = 42 + 1;
+ const size_t __idx __unused = __len - 1;
+ pid_t __child;
+ int __status;
+ int sock[2] = { -1, -1 };
+ struct mmsghdr msgvec[2];
+
+ __child = fork();
+ ATF_REQUIRE(__child >= 0);
+ if (__child > 0)
+ goto monitor;
+
+ /* Child */
+ disable_coredumps();
+ __stack.__buf = malloc(__bufsz);
+ memset(&msgvec[0], 0, sizeof(msgvec));
+
+ /*
+ * Same as above, make sure fortification isn't ignoring n > 1 elements
+ * of the msgvec.
+ */
+ msgvec[1].msg_hdr.msg_control = BUF;
+ msgvec[1].msg_hdr.msg_controllen = __len;
+
+ recvmmsg(sock[0], &msgvec[0], nitems(msgvec), 0, NULL);
+ _exit(1); /* Should have aborted. */
+
+monitor:
+ while (waitpid(__child, &__status, 0) != __child) {
+ ATF_REQUIRE_EQ(EINTR, errno);
+ }
+
+ ATF_REQUIRE_MSG(WIFSIGNALED(__status), "not signaled, status %x", __status);
+ ATF_REQUIRE_EQ(SIGABRT, WTERMSIG(__status));
+#undef BUF
+
+}
+
+ATF_TP_ADD_TCS(tp)
+{
+ ATF_TP_ADD_TC(tp, getpeername_before_end);
+ ATF_TP_ADD_TC(tp, getpeername_end);
+ ATF_TP_ADD_TC(tp, getpeername_heap_before_end);
+ ATF_TP_ADD_TC(tp, getpeername_heap_end);
+ ATF_TP_ADD_TC(tp, getpeername_heap_after_end);
+ ATF_TP_ADD_TC(tp, getsockname_before_end);
+ ATF_TP_ADD_TC(tp, getsockname_end);
+ ATF_TP_ADD_TC(tp, getsockname_heap_before_end);
+ ATF_TP_ADD_TC(tp, getsockname_heap_end);
+ ATF_TP_ADD_TC(tp, getsockname_heap_after_end);
+ ATF_TP_ADD_TC(tp, recv_before_end);
+ ATF_TP_ADD_TC(tp, recv_end);
+ ATF_TP_ADD_TC(tp, recv_heap_before_end);
+ ATF_TP_ADD_TC(tp, recv_heap_end);
+ ATF_TP_ADD_TC(tp, recv_heap_after_end);
+ ATF_TP_ADD_TC(tp, recvfrom_before_end);
+ ATF_TP_ADD_TC(tp, recvfrom_end);
+ ATF_TP_ADD_TC(tp, recvfrom_heap_before_end);
+ ATF_TP_ADD_TC(tp, recvfrom_heap_end);
+ ATF_TP_ADD_TC(tp, recvfrom_heap_after_end);
+ ATF_TP_ADD_TC(tp, recvfrom_sockaddr_before_end);
+ ATF_TP_ADD_TC(tp, recvfrom_sockaddr_end);
+ ATF_TP_ADD_TC(tp, recvfrom_sockaddr_heap_before_end);
+ ATF_TP_ADD_TC(tp, recvfrom_sockaddr_heap_end);
+ ATF_TP_ADD_TC(tp, recvfrom_sockaddr_heap_after_end);
+ ATF_TP_ADD_TC(tp, recvmsg_msg_name_before_end);
+ ATF_TP_ADD_TC(tp, recvmsg_msg_name_end);
+ ATF_TP_ADD_TC(tp, recvmsg_msg_name_heap_before_end);
+ ATF_TP_ADD_TC(tp, recvmsg_msg_name_heap_end);
+ ATF_TP_ADD_TC(tp, recvmsg_msg_name_heap_after_end);
+ ATF_TP_ADD_TC(tp, recvmsg_msg_iov_before_end);
+ ATF_TP_ADD_TC(tp, recvmsg_msg_iov_end);
+ ATF_TP_ADD_TC(tp, recvmsg_msg_iov_heap_before_end);
+ ATF_TP_ADD_TC(tp, recvmsg_msg_iov_heap_end);
+ ATF_TP_ADD_TC(tp, recvmsg_msg_iov_heap_after_end);
+ ATF_TP_ADD_TC(tp, recvmsg_msg_control_before_end);
+ ATF_TP_ADD_TC(tp, recvmsg_msg_control_end);
+ ATF_TP_ADD_TC(tp, recvmsg_msg_control_heap_before_end);
+ ATF_TP_ADD_TC(tp, recvmsg_msg_control_heap_end);
+ ATF_TP_ADD_TC(tp, recvmsg_msg_control_heap_after_end);
+ ATF_TP_ADD_TC(tp, recvmmsg_msgvec_before_end);
+ ATF_TP_ADD_TC(tp, recvmmsg_msgvec_end);
+ ATF_TP_ADD_TC(tp, recvmmsg_msgvec_after_end);
+ ATF_TP_ADD_TC(tp, recvmmsg_msgvec_heap_before_end);
+ ATF_TP_ADD_TC(tp, recvmmsg_msgvec_heap_end);
+ ATF_TP_ADD_TC(tp, recvmmsg_msgvec_heap_after_end);
+ ATF_TP_ADD_TC(tp, recvmmsg_msghdr_before_end);
+ ATF_TP_ADD_TC(tp, recvmmsg_msghdr_end);
+ ATF_TP_ADD_TC(tp, recvmmsg_msghdr_heap_before_end);
+ ATF_TP_ADD_TC(tp, recvmmsg_msghdr_heap_end);
+ ATF_TP_ADD_TC(tp, recvmmsg_msghdr_heap_after_end);
+ return (atf_no_error());
+}
diff --git a/lib/libc/tests/secure/fortify_stdio_test.c b/lib/libc/tests/secure/fortify_stdio_test.c
--- a/lib/libc/tests/secure/fortify_stdio_test.c
+++ b/lib/libc/tests/secure/fortify_stdio_test.c
@@ -7,6 +7,7 @@
#include <sys/random.h>
#include <sys/resource.h>
#include <sys/select.h>
+#include <sys/socket.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/wait.h>
@@ -65,6 +66,50 @@
return (linkname);
}
+/*
+ * For our purposes, first descriptor will be the reader; we'll send both
+ * raw data and a control message over it so that the result can be used for
+ * any of our recv*() tests.
+ */
+static void __unused
+new_socket(int sock[2])
+{
+ unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 };
+ static char sockbuf[256];
+ ssize_t rv;
+ size_t total = 0;
+ struct msghdr hdr = { 0 };
+ struct cmsghdr *cmsg;
+ int error, fd;
+
+ error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
+ ATF_REQUIRE(error == 0);
+
+ while (total != sizeof(sockbuf)) {
+ rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0);
+
+ ATF_REQUIRE_MSG(rv > 0,
+ "expected bytes sent, got %zd with %zu left (size %zu, total %zu)",
+ rv, sizeof(sockbuf) - total, sizeof(sockbuf), total);
+ ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf),
+ "%zd exceeds total %zu", rv, sizeof(sockbuf));
+ total += rv;
+ }
+
+ hdr.msg_control = ctrl;
+ hdr.msg_controllen = sizeof(ctrl);
+
+ cmsg = CMSG_FIRSTHDR(&hdr);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+ fd = STDIN_FILENO;
+ memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
+
+ error = sendmsg(sock[1], &hdr, 0);
+ ATF_REQUIRE(error != -1);
+}
+
/*
* Constructs a tmpfile that we can use for testing read(2) and friends.
*/
diff --git a/lib/libc/tests/secure/fortify_stdlib_test.c b/lib/libc/tests/secure/fortify_stdlib_test.c
--- a/lib/libc/tests/secure/fortify_stdlib_test.c
+++ b/lib/libc/tests/secure/fortify_stdlib_test.c
@@ -7,6 +7,7 @@
#include <sys/random.h>
#include <sys/resource.h>
#include <sys/select.h>
+#include <sys/socket.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/wait.h>
@@ -65,6 +66,50 @@
return (linkname);
}
+/*
+ * For our purposes, first descriptor will be the reader; we'll send both
+ * raw data and a control message over it so that the result can be used for
+ * any of our recv*() tests.
+ */
+static void __unused
+new_socket(int sock[2])
+{
+ unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 };
+ static char sockbuf[256];
+ ssize_t rv;
+ size_t total = 0;
+ struct msghdr hdr = { 0 };
+ struct cmsghdr *cmsg;
+ int error, fd;
+
+ error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
+ ATF_REQUIRE(error == 0);
+
+ while (total != sizeof(sockbuf)) {
+ rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0);
+
+ ATF_REQUIRE_MSG(rv > 0,
+ "expected bytes sent, got %zd with %zu left (size %zu, total %zu)",
+ rv, sizeof(sockbuf) - total, sizeof(sockbuf), total);
+ ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf),
+ "%zd exceeds total %zu", rv, sizeof(sockbuf));
+ total += rv;
+ }
+
+ hdr.msg_control = ctrl;
+ hdr.msg_controllen = sizeof(ctrl);
+
+ cmsg = CMSG_FIRSTHDR(&hdr);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+ fd = STDIN_FILENO;
+ memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
+
+ error = sendmsg(sock[1], &hdr, 0);
+ ATF_REQUIRE(error != -1);
+}
+
/*
* Constructs a tmpfile that we can use for testing read(2) and friends.
*/
diff --git a/lib/libc/tests/secure/fortify_string_test.c b/lib/libc/tests/secure/fortify_string_test.c
--- a/lib/libc/tests/secure/fortify_string_test.c
+++ b/lib/libc/tests/secure/fortify_string_test.c
@@ -7,6 +7,7 @@
#include <sys/random.h>
#include <sys/resource.h>
#include <sys/select.h>
+#include <sys/socket.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/wait.h>
@@ -65,6 +66,50 @@
return (linkname);
}
+/*
+ * For our purposes, first descriptor will be the reader; we'll send both
+ * raw data and a control message over it so that the result can be used for
+ * any of our recv*() tests.
+ */
+static void __unused
+new_socket(int sock[2])
+{
+ unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 };
+ static char sockbuf[256];
+ ssize_t rv;
+ size_t total = 0;
+ struct msghdr hdr = { 0 };
+ struct cmsghdr *cmsg;
+ int error, fd;
+
+ error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
+ ATF_REQUIRE(error == 0);
+
+ while (total != sizeof(sockbuf)) {
+ rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0);
+
+ ATF_REQUIRE_MSG(rv > 0,
+ "expected bytes sent, got %zd with %zu left (size %zu, total %zu)",
+ rv, sizeof(sockbuf) - total, sizeof(sockbuf), total);
+ ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf),
+ "%zd exceeds total %zu", rv, sizeof(sockbuf));
+ total += rv;
+ }
+
+ hdr.msg_control = ctrl;
+ hdr.msg_controllen = sizeof(ctrl);
+
+ cmsg = CMSG_FIRSTHDR(&hdr);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+ fd = STDIN_FILENO;
+ memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
+
+ error = sendmsg(sock[1], &hdr, 0);
+ ATF_REQUIRE(error != -1);
+}
+
/*
* Constructs a tmpfile that we can use for testing read(2) and friends.
*/
diff --git a/lib/libc/tests/secure/fortify_strings_test.c b/lib/libc/tests/secure/fortify_strings_test.c
--- a/lib/libc/tests/secure/fortify_strings_test.c
+++ b/lib/libc/tests/secure/fortify_strings_test.c
@@ -7,6 +7,7 @@
#include <sys/random.h>
#include <sys/resource.h>
#include <sys/select.h>
+#include <sys/socket.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/wait.h>
@@ -65,6 +66,50 @@
return (linkname);
}
+/*
+ * For our purposes, first descriptor will be the reader; we'll send both
+ * raw data and a control message over it so that the result can be used for
+ * any of our recv*() tests.
+ */
+static void __unused
+new_socket(int sock[2])
+{
+ unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 };
+ static char sockbuf[256];
+ ssize_t rv;
+ size_t total = 0;
+ struct msghdr hdr = { 0 };
+ struct cmsghdr *cmsg;
+ int error, fd;
+
+ error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
+ ATF_REQUIRE(error == 0);
+
+ while (total != sizeof(sockbuf)) {
+ rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0);
+
+ ATF_REQUIRE_MSG(rv > 0,
+ "expected bytes sent, got %zd with %zu left (size %zu, total %zu)",
+ rv, sizeof(sockbuf) - total, sizeof(sockbuf), total);
+ ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf),
+ "%zd exceeds total %zu", rv, sizeof(sockbuf));
+ total += rv;
+ }
+
+ hdr.msg_control = ctrl;
+ hdr.msg_controllen = sizeof(ctrl);
+
+ cmsg = CMSG_FIRSTHDR(&hdr);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+ fd = STDIN_FILENO;
+ memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
+
+ error = sendmsg(sock[1], &hdr, 0);
+ ATF_REQUIRE(error != -1);
+}
+
/*
* Constructs a tmpfile that we can use for testing read(2) and friends.
*/
diff --git a/lib/libc/tests/secure/fortify_uio_test.c b/lib/libc/tests/secure/fortify_uio_test.c
--- a/lib/libc/tests/secure/fortify_uio_test.c
+++ b/lib/libc/tests/secure/fortify_uio_test.c
@@ -7,6 +7,7 @@
#include <sys/random.h>
#include <sys/resource.h>
#include <sys/select.h>
+#include <sys/socket.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/wait.h>
@@ -65,6 +66,50 @@
return (linkname);
}
+/*
+ * For our purposes, first descriptor will be the reader; we'll send both
+ * raw data and a control message over it so that the result can be used for
+ * any of our recv*() tests.
+ */
+static void __unused
+new_socket(int sock[2])
+{
+ unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 };
+ static char sockbuf[256];
+ ssize_t rv;
+ size_t total = 0;
+ struct msghdr hdr = { 0 };
+ struct cmsghdr *cmsg;
+ int error, fd;
+
+ error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
+ ATF_REQUIRE(error == 0);
+
+ while (total != sizeof(sockbuf)) {
+ rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0);
+
+ ATF_REQUIRE_MSG(rv > 0,
+ "expected bytes sent, got %zd with %zu left (size %zu, total %zu)",
+ rv, sizeof(sockbuf) - total, sizeof(sockbuf), total);
+ ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf),
+ "%zd exceeds total %zu", rv, sizeof(sockbuf));
+ total += rv;
+ }
+
+ hdr.msg_control = ctrl;
+ hdr.msg_controllen = sizeof(ctrl);
+
+ cmsg = CMSG_FIRSTHDR(&hdr);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+ fd = STDIN_FILENO;
+ memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
+
+ error = sendmsg(sock[1], &hdr, 0);
+ ATF_REQUIRE(error != -1);
+}
+
/*
* Constructs a tmpfile that we can use for testing read(2) and friends.
*/
diff --git a/lib/libc/tests/secure/fortify_unistd_test.c b/lib/libc/tests/secure/fortify_unistd_test.c
--- a/lib/libc/tests/secure/fortify_unistd_test.c
+++ b/lib/libc/tests/secure/fortify_unistd_test.c
@@ -7,6 +7,7 @@
#include <sys/random.h>
#include <sys/resource.h>
#include <sys/select.h>
+#include <sys/socket.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/wait.h>
@@ -65,6 +66,50 @@
return (linkname);
}
+/*
+ * For our purposes, first descriptor will be the reader; we'll send both
+ * raw data and a control message over it so that the result can be used for
+ * any of our recv*() tests.
+ */
+static void __unused
+new_socket(int sock[2])
+{
+ unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 };
+ static char sockbuf[256];
+ ssize_t rv;
+ size_t total = 0;
+ struct msghdr hdr = { 0 };
+ struct cmsghdr *cmsg;
+ int error, fd;
+
+ error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
+ ATF_REQUIRE(error == 0);
+
+ while (total != sizeof(sockbuf)) {
+ rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0);
+
+ ATF_REQUIRE_MSG(rv > 0,
+ "expected bytes sent, got %zd with %zu left (size %zu, total %zu)",
+ rv, sizeof(sockbuf) - total, sizeof(sockbuf), total);
+ ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf),
+ "%zd exceeds total %zu", rv, sizeof(sockbuf));
+ total += rv;
+ }
+
+ hdr.msg_control = ctrl;
+ hdr.msg_controllen = sizeof(ctrl);
+
+ cmsg = CMSG_FIRSTHDR(&hdr);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+ fd = STDIN_FILENO;
+ memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
+
+ error = sendmsg(sock[1], &hdr, 0);
+ ATF_REQUIRE(error != -1);
+}
+
/*
* Constructs a tmpfile that we can use for testing read(2) and friends.
*/
diff --git a/lib/libc/tests/secure/fortify_wchar_test.c b/lib/libc/tests/secure/fortify_wchar_test.c
--- a/lib/libc/tests/secure/fortify_wchar_test.c
+++ b/lib/libc/tests/secure/fortify_wchar_test.c
@@ -7,6 +7,7 @@
#include <sys/random.h>
#include <sys/resource.h>
#include <sys/select.h>
+#include <sys/socket.h>
#include <sys/time.h>
#include <sys/uio.h>
#include <sys/wait.h>
@@ -65,6 +66,50 @@
return (linkname);
}
+/*
+ * For our purposes, first descriptor will be the reader; we'll send both
+ * raw data and a control message over it so that the result can be used for
+ * any of our recv*() tests.
+ */
+static void __unused
+new_socket(int sock[2])
+{
+ unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 };
+ static char sockbuf[256];
+ ssize_t rv;
+ size_t total = 0;
+ struct msghdr hdr = { 0 };
+ struct cmsghdr *cmsg;
+ int error, fd;
+
+ error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
+ ATF_REQUIRE(error == 0);
+
+ while (total != sizeof(sockbuf)) {
+ rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0);
+
+ ATF_REQUIRE_MSG(rv > 0,
+ "expected bytes sent, got %zd with %zu left (size %zu, total %zu)",
+ rv, sizeof(sockbuf) - total, sizeof(sockbuf), total);
+ ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf),
+ "%zd exceeds total %zu", rv, sizeof(sockbuf));
+ total += rv;
+ }
+
+ hdr.msg_control = ctrl;
+ hdr.msg_controllen = sizeof(ctrl);
+
+ cmsg = CMSG_FIRSTHDR(&hdr);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+ fd = STDIN_FILENO;
+ memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
+
+ error = sendmsg(sock[1], &hdr, 0);
+ ATF_REQUIRE(error != -1);
+}
+
/*
* Constructs a tmpfile that we can use for testing read(2) and friends.
*/
diff --git a/lib/libc/tests/secure/generate-fortify-tests.lua b/lib/libc/tests/secure/generate-fortify-tests.lua
--- a/lib/libc/tests/secure/generate-fortify-tests.lua
+++ b/lib/libc/tests/secure/generate-fortify-tests.lua
@@ -31,6 +31,7 @@
"sys/random.h",
"sys/resource.h",
"sys/select.h",
+ "sys/socket.h",
"sys/time.h",
"sys/uio.h",
"sys/wait.h",
@@ -80,6 +81,20 @@
replace_stdin();
]]
+local socket_stackvars = "\tint sock[2] = { -1, -1 };\n"
+local recvfrom_sockaddr_stackvars = socket_stackvars .. [[
+ char data[16];
+ socklen_t socklen;
+]]
+local recvmsg_stackvars = socket_stackvars .. "\tstruct msghdr msg;\n"
+local socket_init = [[
+ new_socket(sock);
+ ATF_REQUIRE(sock[0] >= 0);
+]]
+local socket_socklen_init = socket_init .. [[
+ socklen = __len;
+]]
+
local stdio_init = [[
replace_stdin();
]]
@@ -165,6 +180,187 @@
},
},
},
+ socket = {
+ -- <sys/socket.h>
+ {
+ func = "getpeername",
+ buftype = "struct sockaddr",
+ bufsize = "sizeof(struct sockaddr)",
+ arguments = {
+ "sock[0]",
+ "__buf",
+ "&socklen",
+ },
+ exclude = excludes_stack_overflow,
+ stackvars = socket_stackvars .. "\tsocklen_t socklen;",
+ init = socket_socklen_init,
+ uses_len = true,
+ },
+ {
+ func = "getsockname",
+ buftype = "struct sockaddr",
+ bufsize = "sizeof(struct sockaddr)",
+ arguments = {
+ "sock[0]",
+ "__buf",
+ "&socklen",
+ },
+ exclude = excludes_stack_overflow,
+ stackvars = socket_stackvars .. "\tsocklen_t socklen;",
+ init = socket_socklen_init,
+ uses_len = true,
+ },
+ {
+ func = "recv",
+ arguments = {
+ "sock[0]",
+ "__buf",
+ "__len",
+ "0",
+ },
+ exclude = excludes_stack_overflow,
+ stackvars = socket_stackvars,
+ init = socket_init,
+ },
+ {
+ func = "recvfrom",
+ arguments = {
+ "sock[0]",
+ "__buf",
+ "__len",
+ "0",
+ "NULL",
+ "NULL",
+ },
+ exclude = excludes_stack_overflow,
+ stackvars = socket_stackvars,
+ init = socket_init,
+ },
+ {
+ func = "recvfrom",
+ variant = "sockaddr",
+ buftype = "struct sockaddr",
+ bufsize = "sizeof(struct sockaddr)",
+ arguments = {
+ "sock[0]",
+ "data",
+ "sizeof(data)",
+ "0",
+ "__buf",
+ "&socklen",
+ },
+ exclude = excludes_stack_overflow,
+ stackvars = recvfrom_sockaddr_stackvars,
+ init = socket_socklen_init,
+ uses_len = true,
+ },
+ {
+ func = "recvmsg",
+ variant = "msg_name",
+ buftype = "struct sockaddr",
+ bufsize = "sizeof(struct sockaddr)",
+ arguments = {
+ "sock[0]",
+ "&msg",
+ "0",
+ },
+ exclude = excludes_stack_overflow,
+ stackvars = recvmsg_stackvars,
+ init = [[
+ memset(&msg, 0, sizeof(msg));
+ msg.msg_name = BUF;
+ msg.msg_namelen = __len;
+]],
+ uses_len = true,
+ },
+ {
+ func = "recvmsg",
+ variant = "msg_iov",
+ arguments = {
+ "sock[0]",
+ "&msg",
+ "0",
+ },
+ exclude = excludes_stack_overflow,
+ stackvars = recvmsg_stackvars .. "\tstruct iovec iov[2];\n",
+ init = [[
+ memset(&msg, 0, sizeof(msg));
+ memset(&iov[0], 0, sizeof(iov));
+
+ /*
+ * We position the buffer second just so that we can confirm that the
+ * fortification bits are traversing the iovec correctly.
+ */
+ iov[1].iov_base = BUF;
+ iov[1].iov_len = __len;
+
+ msg.msg_iov = &iov[0];
+ msg.msg_iovlen = nitems(iov);
+]],
+ uses_len = true,
+ },
+ {
+ func = "recvmsg",
+ variant = "msg_control",
+ bufsize = "CMSG_SPACE(sizeof(int))",
+ arguments = {
+ "sock[0]",
+ "&msg",
+ "0",
+ },
+ exclude = excludes_stack_overflow,
+ stackvars = recvmsg_stackvars,
+ init = [[
+ memset(&msg, 0, sizeof(msg));
+
+ msg.msg_control = BUF;
+ msg.msg_controllen = __len;
+]],
+ uses_len = true,
+ },
+ {
+ func = "recvmmsg",
+ variant = "msgvec",
+ buftype = "struct mmsghdr[]",
+ bufsize = "2",
+ arguments = {
+ "sock[0]",
+ "__buf",
+ "__len",
+ "0",
+ "NULL",
+ },
+ stackvars = socket_stackvars,
+ },
+ {
+ -- We'll assume that recvmsg is covering msghdr
+ -- validation thoroughly enough, we'll just try tossing
+ -- an error in the second element of a msgvec to try and
+ -- make sure that each one is being validated.
+ func = "recvmmsg",
+ variant = "msghdr",
+ arguments = {
+ "sock[0]",
+ "&msgvec[0]",
+ "nitems(msgvec)",
+ "0",
+ "NULL",
+ },
+ exclude = excludes_stack_overflow,
+ stackvars = socket_stackvars .. "\tstruct mmsghdr msgvec[2];\n",
+ init = [[
+ memset(&msgvec[0], 0, sizeof(msgvec));
+
+ /*
+ * Same as above, make sure fortification isn't ignoring n > 1 elements
+ * of the msgvec.
+ */
+ msgvec[1].msg_hdr.msg_control = BUF;
+ msgvec[1].msg_hdr.msg_controllen = __len;
+]],
+ uses_len = true,
+ },
+ },
uio = {
-- <sys/uio.h>
{
@@ -1138,6 +1334,50 @@
return (linkname);
}
+/*
+ * For our purposes, first descriptor will be the reader; we'll send both
+ * raw data and a control message over it so that the result can be used for
+ * any of our recv*() tests.
+ */
+static void __unused
+new_socket(int sock[2])
+{
+ unsigned char ctrl[CMSG_SPACE(sizeof(int))] = { 0 };
+ static char sockbuf[256];
+ ssize_t rv;
+ size_t total = 0;
+ struct msghdr hdr = { 0 };
+ struct cmsghdr *cmsg;
+ int error, fd;
+
+ error = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
+ ATF_REQUIRE(error == 0);
+
+ while (total != sizeof(sockbuf)) {
+ rv = send(sock[1], &sockbuf[total], sizeof(sockbuf) - total, 0);
+
+ ATF_REQUIRE_MSG(rv > 0,
+ "expected bytes sent, got %zd with %zu left (size %zu, total %zu)",
+ rv, sizeof(sockbuf) - total, sizeof(sockbuf), total);
+ ATF_REQUIRE_MSG(total + (size_t)rv <= sizeof(sockbuf),
+ "%zd exceeds total %zu", rv, sizeof(sockbuf));
+ total += rv;
+ }
+
+ hdr.msg_control = ctrl;
+ hdr.msg_controllen = sizeof(ctrl);
+
+ cmsg = CMSG_FIRSTHDR(&hdr);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(fd));
+ fd = STDIN_FILENO;
+ memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd));
+
+ error = sendmsg(sock[1], &hdr, 0);
+ ATF_REQUIRE(error != -1);
+}
+
/*
* Constructs a tmpfile that we can use for testing read(2) and friends.
*/
diff --git a/lib/libsys/recvmmsg.c b/lib/libsys/recvmmsg.c
--- a/lib/libsys/recvmmsg.c
+++ b/lib/libsys/recvmmsg.c
@@ -32,11 +32,12 @@
#include <errno.h>
#include <poll.h>
#include <stddef.h>
+#include <ssp/ssp.h>
#include "libc_private.h"
ssize_t
-recvmmsg(int s, struct mmsghdr *__restrict msgvec, size_t vlen, int flags,
- const struct timespec *__restrict timeout)
+__ssp_real(recvmmsg)(int s, struct mmsghdr *__restrict msgvec, size_t vlen,
+ int flags, const struct timespec *__restrict timeout)
{
struct pollfd pfd[1];
size_t i, rcvd;
diff --git a/sys/sys/socket.h b/sys/sys/socket.h
--- a/sys/sys/socket.h
+++ b/sys/sys/socket.h
@@ -670,6 +670,10 @@
};
#endif /* __BSD_VISIBLE */
+#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0
+#include <ssp/socket.h>
+#endif
+
#ifndef _KERNEL
#include <sys/cdefs.h>
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Fri, Aug 14, 9:42 PM (2 h, 19 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
36768537
Default Alt Text
D45686.id140087.diff (70 KB)
Attached To
Mode
D45686: include: ssp: fortify <sys/socket.h>
Attached
Detach File
Event Timeline
Log In to Comment