Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 21 Mar 2016 21:37:33 +0000 (UTC)
From:      John Baldwin <jhb@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r297167 - in head: lib/libc/sys sys/kern sys/sys tests/sys/aio
Message-ID:  <201603212137.u2LLbX46033048@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhb
Date: Mon Mar 21 21:37:33 2016
New Revision: 297167
URL: https://svnweb.freebsd.org/changeset/base/297167

Log:
  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.

Modified:
  head/lib/libc/sys/aio_return.2
  head/lib/libc/sys/aio_waitcomplete.2
  head/sys/kern/syscalls.master
  head/sys/kern/vfs_aio.c
  head/sys/sys/aio.h
  head/tests/sys/aio/aio_test.c

Modified: head/lib/libc/sys/aio_return.2
==============================================================================
--- head/lib/libc/sys/aio_return.2	Mon Mar 21 21:33:30 2016	(r297166)
+++ head/lib/libc/sys/aio_return.2	Mon Mar 21 21:37:33 2016	(r297167)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd October 7, 2006
+.Dd March 21, 2016
 .Dt AIO_RETURN 2
 .Os
 .Sh NAME
@@ -34,7 +34,7 @@
 .Lb libc
 .Sh SYNOPSIS
 .In aio.h
-.Ft int
+.Ft ssize_t
 .Fn aio_return "struct aiocb *iocb"
 .Sh DESCRIPTION
 The

Modified: head/lib/libc/sys/aio_waitcomplete.2
==============================================================================
--- head/lib/libc/sys/aio_waitcomplete.2	Mon Mar 21 21:33:30 2016	(r297166)
+++ head/lib/libc/sys/aio_waitcomplete.2	Mon Mar 21 21:37:33 2016	(r297167)
@@ -24,7 +24,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd January 19, 2000
+.Dd March 21, 2016
 .Dt AIO_WAITCOMPLETE 2
 .Os
 .Sh NAME
@@ -34,7 +34,7 @@
 .Lb libc
 .Sh SYNOPSIS
 .In aio.h
-.Ft int
+.Ft ssize_t
 .Fn aio_waitcomplete "struct aiocb **iocbp" "struct timespec *timeout"
 .Sh DESCRIPTION
 The

Modified: head/sys/kern/syscalls.master
==============================================================================
--- head/sys/kern/syscalls.master	Mon Mar 21 21:33:30 2016	(r297166)
+++ head/sys/kern/syscalls.master	Mon Mar 21 21:37:33 2016	(r297167)
@@ -554,7 +554,7 @@
 312	AUE_SETRESGID	STD	{ int setresgid(gid_t rgid, gid_t egid, \
 				    gid_t sgid); }
 313	AUE_NULL	OBSOL	signanosleep
-314	AUE_NULL	STD	{ int aio_return(struct aiocb *aiocbp); }
+314	AUE_NULL	STD	{ ssize_t aio_return(struct aiocb *aiocbp); }
 315	AUE_NULL	STD	{ int aio_suspend( \
 				    struct aiocb * const * aiocbp, int nent, \
 				    const struct timespec *timeout); }
@@ -643,7 +643,7 @@
 358	AUE_EXTATTR_DELETE_FILE	STD	{ int extattr_delete_file(const char *path, \
 				    int attrnamespace, \
 				    const char *attrname); }
-359	AUE_NULL	STD	{ int aio_waitcomplete( \
+359	AUE_NULL	STD	{ ssize_t aio_waitcomplete( \
 				    struct aiocb **aiocbp, \
 				    struct timespec *timeout); }
 360	AUE_GETRESUID	STD	{ int getresuid(uid_t *ruid, uid_t *euid, \

Modified: head/sys/kern/vfs_aio.c
==============================================================================
--- head/sys/kern/vfs_aio.c	Mon Mar 21 21:33:30 2016	(r297166)
+++ head/sys/kern/vfs_aio.c	Mon Mar 21 21:37:33 2016	(r297167)
@@ -743,7 +743,7 @@ aio_process_rw(struct kaiocb *job)
 	struct file *fp;
 	struct uio auio;
 	struct iovec aiov;
-	int cnt;
+	ssize_t cnt;
 	int error;
 	int oublock_st, oublock_end;
 	int inblock_st, inblock_end;
@@ -1447,8 +1447,7 @@ aio_aqueue(struct thread *td, struct aio
 		return (error);
 	}
 
-	/* XXX: aio_nbytes is later casted to signed types. */
-	if (job->uaiocb.aio_nbytes > INT_MAX) {
+	if (job->uaiocb.aio_nbytes > IOSIZE_MAX) {
 		uma_zfree(aiocb_zone, job);
 		return (EINVAL);
 	}
@@ -1789,7 +1788,7 @@ kern_aio_return(struct thread *td, struc
 	struct proc *p = td->td_proc;
 	struct kaiocb *job;
 	struct kaioinfo *ki;
-	int status, error;
+	long status, error;
 
 	ki = p->p_aioinfo;
 	if (ki == NULL)
@@ -2345,7 +2344,8 @@ kern_aio_waitcomplete(struct thread *td,
 	struct kaioinfo *ki;
 	struct kaiocb *job;
 	struct aiocb *ujob;
-	int error, status, timo;
+	long error, status;
+	int timo;
 
 	ops->store_aiocb(ujobp, NULL);
 

Modified: head/sys/sys/aio.h
==============================================================================
--- head/sys/sys/aio.h	Mon Mar 21 21:33:30 2016	(r297166)
+++ head/sys/sys/aio.h	Mon Mar 21 21:37:33 2016	(r297167)
@@ -238,7 +238,7 @@ int	aio_suspend(const struct aiocb * con
 int	aio_mlock(struct aiocb *);
 
 #ifdef __BSD_VISIBLE
-int	aio_waitcomplete(struct aiocb **, struct timespec *);
+ssize_t	aio_waitcomplete(struct aiocb **, struct timespec *);
 #endif
 
 int	aio_fsync(int op, struct aiocb *aiocbp);

Modified: head/tests/sys/aio/aio_test.c
==============================================================================
--- head/tests/sys/aio/aio_test.c	Mon Mar 21 21:33:30 2016	(r297166)
+++ head/tests/sys/aio/aio_test.c	Mon Mar 21 21:37:33 2016	(r297167)
@@ -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());
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201603212137.u2LLbX46033048>