aboutsummaryrefslogtreecommitdiff
path: root/tests/sys
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2016-03-21 21:37:33 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2016-03-21 21:37:33 +0000
commitbb430bc7406fea7e7f361fb66f4d4391829b07ee (patch)
tree58c8cd3e864cd6a4c77d7330aab43fbe2a866af1 /tests/sys
parent377044270872b2720687f042cd4020afefb81958 (diff)
downloadsrc-bb430bc7406fea7e7f361fb66f4d4391829b07ee.tar.gz
src-bb430bc7406fea7e7f361fb66f4d4391829b07ee.zip
Fully handle size_t lengths in AIO requests.
First, update the return types of aio_return() and aio_waitcomplete() to ssize_t. POSIX requires aio_return() to return a ssize_t so that it can represent all return values from read() and write(). aio_waitcomplete() should use ssize_t for the same reason. aio_return() has used ssize_t in <aio.h> since r31620 but the manpage and system call entry were not updated. aio_waitcomplete() has always returned int. Note that this does not require new system call stubs as this is effectively only an API change in how the compiler interprets the return value. Second, allow aio_nbytes values up to IOSIZE_MAX instead of just INT_MAX. aio_read/write should now honor the same length limits as normal read/write. Third, use longs instead of ints in the aio_return() and aio_waitcomplete() system call functions so that the 64-bit size_t in the in-kernel aiocb isn't truncated to 32-bits before being copied out to userland or being returned. Finally, a simple test has been added to verify the bounds checking on the maximum read size from a file.
Notes
Notes: svn path=/head/; revision=297167
Diffstat (limited to 'tests/sys')
-rw-r--r--tests/sys/aio/aio_test.c76
1 files changed, 76 insertions, 0 deletions
diff --git a/tests/sys/aio/aio_test.c b/tests/sys/aio/aio_test.c
index 607f46db5acb..99ecc283f27e 100644
--- a/tests/sys/aio/aio_test.c
+++ b/tests/sys/aio/aio_test.c
@@ -649,6 +649,81 @@ ATF_TC_BODY(aio_md_test, tc)
aio_md_cleanup(&arg);
}
+ATF_TC_WITHOUT_HEAD(aio_large_read_test);
+ATF_TC_BODY(aio_large_read_test, tc)
+{
+ char pathname[PATH_MAX];
+ struct aiocb cb, *cbp;
+ ssize_t nread;
+ size_t len;
+ int fd;
+#ifdef __LP64__
+ int clamped;
+#endif
+
+ ATF_REQUIRE_KERNEL_MODULE("aio");
+ ATF_REQUIRE_UNSAFE_AIO();
+
+#ifdef __LP64__
+ len = sizeof(clamped);
+ if (sysctlbyname("debug.iosize_max_clamp", &clamped, &len, NULL, 0) ==
+ -1)
+ atf_libc_error(errno, "Failed to read debug.iosize_max_clamp");
+#endif
+
+ /* Determine the maximum supported read(2) size. */
+ len = SSIZE_MAX;
+#ifdef __LP64__
+ if (clamped)
+ len = INT_MAX;
+#endif
+
+ strcpy(pathname, PATH_TEMPLATE);
+ fd = mkstemp(pathname);
+ ATF_REQUIRE_MSG(fd != -1, "mkstemp failed: %s", strerror(errno));
+
+ unlink(pathname);
+
+ memset(&cb, 0, sizeof(cb));
+ cb.aio_nbytes = len;
+ cb.aio_fildes = fd;
+ cb.aio_buf = NULL;
+ if (aio_read(&cb) == -1)
+ atf_tc_fail("aio_read() of maximum read size failed: %s",
+ strerror(errno));
+
+ nread = aio_waitcomplete(&cbp, NULL);
+ if (nread == -1)
+ atf_tc_fail("aio_waitcomplete() failed: %s", strerror(errno));
+ if (nread != 0)
+ atf_tc_fail("aio_read() from /dev/null returned data: %zd",
+ nread);
+
+ memset(&cb, 0, sizeof(cb));
+ cb.aio_nbytes = len + 1;
+ cb.aio_fildes = fd;
+ cb.aio_buf = NULL;
+ if (aio_read(&cb) == -1) {
+ if (errno == EINVAL)
+ goto finished;
+ atf_tc_fail("aio_read() of too large read size failed: %s",
+ strerror(errno));
+ }
+
+ nread = aio_waitcomplete(&cbp, NULL);
+ if (nread == -1) {
+ if (errno == EINVAL)
+ goto finished;
+ atf_tc_fail("aio_waitcomplete() failed: %s", strerror(errno));
+ }
+ atf_tc_fail(
+ "aio_read() of too large read size from /dev/null returned: %zd",
+ nread);
+
+finished:
+ close(fd);
+}
+
ATF_TP_ADD_TCS(tp)
{
@@ -658,6 +733,7 @@ ATF_TP_ADD_TCS(tp)
ATF_TP_ADD_TC(tp, aio_pty_test);
ATF_TP_ADD_TC(tp, aio_pipe_test);
ATF_TP_ADD_TC(tp, aio_md_test);
+ ATF_TP_ADD_TC(tp, aio_large_read_test);
return (atf_no_error());
}