Page MenuHomeFreeBSD

D31901.diff
No OneTemporary

D31901.diff

diff --git a/sys/kern/sys_socket.c b/sys/kern/sys_socket.c
--- a/sys/kern/sys_socket.c
+++ b/sys/kern/sys_socket.c
@@ -808,18 +808,28 @@
if (error == 0)
return (0);
+ /* Lock through the socket, since this may be a listening socket. */
switch (job->uaiocb.aio_lio_opcode & (LIO_WRITE | LIO_READ)) {
case LIO_READ:
sb = &so->so_rcv;
+ SOCK_RECVBUF_LOCK(so);
break;
case LIO_WRITE:
sb = &so->so_snd;
+ SOCK_SENDBUF_LOCK(so);
break;
default:
return (EINVAL);
}
- SOCKBUF_LOCK(sb);
+ if (SOLISTENING(so)) {
+ if (sb == &so->so_rcv)
+ SOCK_RECVBUF_UNLOCK(so);
+ else
+ SOCK_SENDBUF_UNLOCK(so);
+ return (EINVAL);
+ }
+
if (!aio_set_cancel_function(job, soo_aio_cancel))
panic("new job was cancelled");
TAILQ_INSERT_TAIL(&sb->sb_aiojobq, job, list);
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -928,6 +928,13 @@
}
mtx_lock(&so->so_snd_mtx);
mtx_lock(&so->so_rcv_mtx);
+
+ /* Interlock with soo_aio_queue(). */
+ if ((so->so_snd.sb_flags & (SB_AIO | SB_AIO_RUNNING)) != 0 ||
+ (so->so_rcv.sb_flags & (SB_AIO | SB_AIO_RUNNING)) != 0) {
+ solisten_proto_abort(so);
+ return (EINVAL);
+ }
return (0);
}
diff --git a/tests/sys/aio/aio_test.c b/tests/sys/aio/aio_test.c
--- a/tests/sys/aio/aio_test.c
+++ b/tests/sys/aio/aio_test.c
@@ -40,11 +40,12 @@
*/
#include <sys/param.h>
+#include <sys/mdioctl.h>
#include <sys/module.h>
#include <sys/resource.h>
#include <sys/socket.h>
#include <sys/stat.h>
-#include <sys/mdioctl.h>
+#include <sys/un.h>
#include <aio.h>
#include <err.h>
@@ -1177,6 +1178,79 @@
aio_socket_blocking_short_write_test(true);
}
+/*
+ * Verify that AIO requests fail when applied to a listening socket.
+ */
+ATF_TC_WITHOUT_HEAD(aio_socket_listen_fail);
+ATF_TC_BODY(aio_socket_listen_fail, tc)
+{
+ struct aiocb iocb;
+ struct sockaddr_un sun;
+ char buf[16];
+ int s;
+
+ s = socket(AF_LOCAL, SOCK_STREAM, 0);
+ ATF_REQUIRE(s != -1);
+
+ memset(&sun, 0, sizeof(sun));
+ snprintf(sun.sun_path, sizeof(sun.sun_path), "%s", "listen.XXXXXX");
+ mktemp(sun.sun_path);
+ sun.sun_family = AF_LOCAL;
+ sun.sun_len = SUN_LEN(&sun);
+
+ ATF_REQUIRE(bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) == 0);
+ ATF_REQUIRE(listen(s, 5) == 0);
+
+ memset(buf, 0, sizeof(buf));
+ memset(&iocb, 0, sizeof(iocb));
+ iocb.aio_fildes = s;
+ iocb.aio_buf = buf;
+ iocb.aio_nbytes = sizeof(buf);
+
+ ATF_REQUIRE_ERRNO(EINVAL, aio_read(&iocb) == -1);
+ ATF_REQUIRE_ERRNO(EINVAL, aio_write(&iocb) == -1);
+
+ ATF_REQUIRE(unlink(sun.sun_path) == 0);
+ close(s);
+}
+
+/*
+ * Verify that listen(2) fails if a socket has pending AIO requests.
+ */
+ATF_TC_WITHOUT_HEAD(aio_socket_listen_pending);
+ATF_TC_BODY(aio_socket_listen_pending, tc)
+{
+ struct aiocb iocb;
+ struct sockaddr_un sun;
+ char buf[16];
+ int s;
+
+ s = socket(AF_LOCAL, SOCK_STREAM, 0);
+ ATF_REQUIRE(s != -1);
+
+ memset(&sun, 0, sizeof(sun));
+ snprintf(sun.sun_path, sizeof(sun.sun_path), "%s", "listen.XXXXXX");
+ mktemp(sun.sun_path);
+ sun.sun_family = AF_LOCAL;
+ sun.sun_len = SUN_LEN(&sun);
+
+ ATF_REQUIRE(bind(s, (struct sockaddr *)&sun, SUN_LEN(&sun)) == 0);
+
+ memset(buf, 0, sizeof(buf));
+ memset(&iocb, 0, sizeof(iocb));
+ iocb.aio_fildes = s;
+ iocb.aio_buf = buf;
+ iocb.aio_nbytes = sizeof(buf);
+ ATF_REQUIRE(aio_read(&iocb) == 0);
+
+ ATF_REQUIRE_ERRNO(EINVAL, listen(s, 5) == -1);
+
+ ATF_REQUIRE(aio_cancel(s, &iocb) != -1);
+
+ ATF_REQUIRE(unlink(sun.sun_path) == 0);
+ close(s);
+}
+
/*
* This test verifies that cancelling a partially completed socket write
* returns a short write rather than ECANCELED.
@@ -1808,6 +1882,8 @@
ATF_TP_ADD_TC(tp, aio_socket_two_reads);
ATF_TP_ADD_TC(tp, aio_socket_blocking_short_write);
ATF_TP_ADD_TC(tp, aio_socket_blocking_short_write_vectored);
+ ATF_TP_ADD_TC(tp, aio_socket_listen_fail);
+ ATF_TP_ADD_TC(tp, aio_socket_listen_pending);
ATF_TP_ADD_TC(tp, aio_socket_short_write_cancel);
ATF_TP_ADD_TC(tp, aio_writev_dos_iov_len);
ATF_TP_ADD_TC(tp, aio_writev_dos_iovcnt);

File Metadata

Mime Type
text/plain
Expires
Fri, Mar 7, 12:56 AM (16 h, 53 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
17022619
Default Alt Text
D31901.diff (3 KB)

Event Timeline