Module Name: src
Committed By: riastradh
Date: Thu Mar 27 11:01:07 UTC 2025
Modified Files:
src/tests/net/net: t_unix.c
Log Message:
t_unix: Test LOCAL_CONNWAIT.
PR kern/59220: accept(2): null pointer deref
To generate a diff of this commit:
cvs rdiff -u -r1.27 -r1.28 src/tests/net/net/t_unix.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/tests/net/net/t_unix.c
diff -u src/tests/net/net/t_unix.c:1.27 src/tests/net/net/t_unix.c:1.28
--- src/tests/net/net/t_unix.c:1.27 Thu Mar 27 10:57:30 2025
+++ src/tests/net/net/t_unix.c Thu Mar 27 11:01:07 2025
@@ -1,4 +1,4 @@
-/* $NetBSD: t_unix.c,v 1.27 2025/03/27 10:57:30 riastradh Exp $ */
+/* $NetBSD: t_unix.c,v 1.28 2025/03/27 11:01:07 riastradh Exp $ */
/*-
* Copyright (c) 2011 The NetBSD Foundation, Inc.
@@ -39,7 +39,7 @@
#define _GNU_SOURCE
#include <sys/cdefs.h>
#ifdef __RCSID
-__RCSID("$Id: t_unix.c,v 1.27 2025/03/27 10:57:30 riastradh Exp $");
+__RCSID("$Id: t_unix.c,v 1.28 2025/03/27 11:01:07 riastradh Exp $");
#else
#define getprogname() argv[0]
#endif
@@ -59,6 +59,7 @@ __RCSID("$Id: t_unix.c,v 1.27 2025/03/27
#include <err.h>
#include <errno.h>
+#include <poll.h>
#include <stdbool.h>
#include <stddef.h>
#include <stdint.h>
@@ -395,6 +396,8 @@ fail:
#ifndef TEST
+#include "h_macros.h"
+
ATF_TC(sockaddr_un_len_exceed);
ATF_TC_HEAD(sockaddr_un_len_exceed, tc)
{
@@ -439,6 +442,86 @@ ATF_TC_BODY(sockaddr_un_closed, tc)
"test(false, true, false, 100): %s", strerror(errno));
}
+ATF_TC(sockaddr_un_local_connwait);
+ATF_TC_HEAD(sockaddr_un_local_connwait, tc)
+{
+
+ atf_tc_set_md_var(tc, "descr", "Check that LOCAL_CONNWAIT works");
+}
+
+ATF_TC_BODY(sockaddr_un_local_connwait, tc)
+{
+ /* too annoying to fit this into the test(...) framework above */
+ struct sockaddr_un sun = {.sun_family = AF_UNIX, .sun_path = "sock"};
+ int listener, conn, acc;
+ const int one = 1;
+ struct pollfd pfd;
+ int nfd, error;
+ socklen_t errorlen = sizeof(error);
+
+ /*
+ * Create and bind a listening socket.
+ */
+ RL(listener = socket(PF_LOCAL, SOCK_STREAM|SOCK_NONBLOCK, 0));
+ RL(bind(listener, (const struct sockaddr *)&sun, sizeof(sun)));
+ RL(listen(listener, 5));
+
+ /*
+ * Nobody's trying to connect, so accept would block.
+ */
+ ATF_REQUIRE_ERRNO(EAGAIN, accept(listener, NULL, NULL) == -1);
+
+ /*
+ * Connect should succeed immediately even though nobody is
+ * waiting to accept on the other end yet.
+ */
+ RL(conn = socket(PF_LOCAL, SOCK_STREAM|SOCK_NONBLOCK, 0));
+ RL(connect(conn, (const struct sockaddr *)&sun, sizeof(sun)));
+
+ /*
+ * Accept should succeed now that a client connected. Close
+ * both sides; we're done with this connection and will try
+ * again with LOCAL_CONNWAIT next.
+ */
+ RL(acc = accept(listener, NULL, NULL));
+ RL(close(acc));
+ RL(close(conn));
+
+ /*
+ * If we set LOCAL_CONNWAIT, connect should fail, but with
+ * EINPROGRESS -- note: not EAGAIN, because it has changed
+ * state. If we try to connect again, it should fail with
+ * EALREADY because the connection is already pending.
+ */
+ RL(conn = socket(PF_LOCAL, SOCK_STREAM|SOCK_NONBLOCK, 0));
+ RL(setsockopt(conn, SOL_LOCAL, LOCAL_CONNWAIT, &one, sizeof(one)));
+ ATF_REQUIRE_ERRNO(EINPROGRESS,
+ connect(conn, (const struct sockaddr *)&sun, sizeof(sun)) == -1);
+ ATF_REQUIRE_ERRNO(EALREADY,
+ connect(conn, (const struct sockaddr *)&sun, sizeof(sun)) == -1);
+
+ /*
+ * Accept should succeed immediately now.
+ */
+ RL(acc = accept(listener, NULL, NULL));
+
+ /*
+ * Verify via poll(2) that the pending connect(2) has finished
+ * -- it will report POLLOUT when that happens. And then
+ * verify that there was no error.
+ */
+ pfd = (struct pollfd){.fd = conn, .events = POLLOUT};
+ RL(nfd = poll(&pfd, 1, 0));
+ ATF_REQUIRE_MSG(pfd.revents & POLLOUT, "revents=0x%x", pfd.revents);
+ RL(getsockopt(conn, SOL_SOCKET, SO_ERROR, &error, &errorlen));
+ ATF_REQUIRE_MSG(errorlen == sizeof(error), "errorlen=%d", errorlen);
+ ATF_REQUIRE_MSG(error == 0, "error=%d", error);
+
+ RL(close(acc));
+ RL(close(conn));
+ RL(close(listener));
+}
+
ATF_TC(sockaddr_un_local_peereid);
ATF_TC_HEAD(sockaddr_un_local_peereid, tc)
{
@@ -473,6 +556,7 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_ADD_TC(tp, sockaddr_un_len_exceed);
ATF_TP_ADD_TC(tp, sockaddr_un_len_max);
ATF_TP_ADD_TC(tp, sockaddr_un_closed);
+ ATF_TP_ADD_TC(tp, sockaddr_un_local_connwait);
ATF_TP_ADD_TC(tp, sockaddr_un_local_peereid);
ATF_TP_ADD_TC(tp, sockaddr_un_fstat);
return atf_no_error();