diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 1998-07-28 19:47:15 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 1998-07-28 19:47:15 +0000 |
commit | 3287b64e077693dbe8e5b8138453f03f4060e739 (patch) | |
tree | 76b77e1d456db5a77e92b64b2a16746f94ea8ab6 | |
parent | 996b26293c9ed22d2a4601386081731cf9f5a238 (diff) |
For read, write, send, sendto, recv, recvfrom return EINVAL is size arg > SSIZE_MAX. For readv, writev, sendmsg, recvmsg return EINVAL if sum of the over iov_len values overflows an ssize_t. Based on what XPG 4.2 says (though XPG is not entirely consistent here). Basically since the return value is ssize_t allowing size > SSIZE_MAX is bad since people who (incorrectly mind you) check the return value for < 0 instead of == -1 will have bad things happen to them.
-rw-r--r-- | lib/libc/sys/read.2 | 17 | ||||
-rw-r--r-- | lib/libc/sys/recv.2 | 19 | ||||
-rw-r--r-- | lib/libc/sys/send.2 | 19 | ||||
-rw-r--r-- | lib/libc/sys/write.2 | 19 | ||||
-rw-r--r-- | sys/kern/sys_generic.c | 34 | ||||
-rw-r--r-- | sys/kern/uipc_syscalls.c | 10 |
6 files changed, 84 insertions, 34 deletions
diff --git a/lib/libc/sys/read.2 b/lib/libc/sys/read.2 index 70f8d5c7ab8..9f42215bf7c 100644 --- a/lib/libc/sys/read.2 +++ b/lib/libc/sys/read.2 @@ -1,4 +1,4 @@ -.\" $OpenBSD: read.2,v 1.4 1998/07/28 04:13:34 millert Exp $ +.\" $OpenBSD: read.2,v 1.5 1998/07/28 19:47:10 millert Exp $ .\" $NetBSD: read.2,v 1.6 1995/02/27 12:35:47 cgd Exp $ .\" .\" Copyright (c) 1980, 1991, 1993 @@ -34,7 +34,7 @@ .\" .\" @(#)read.2 8.4 (Berkeley) 2/26/94 .\" -.Dd February 26, 1994 +.Dd July 28, 1998 .Dt READ 2 .Os BSD 4 .Sh NAME @@ -151,6 +151,16 @@ and no data were ready to be read. .El .Pp In addition, +.Fn read +may return following error: +.Bl -tag -width Er +.It Bq Er EINVAL +.Fa nbytes +was larger than +.Ev SSIZE_MAX . +.El +.Pp +Also, .Fn readv may return one of the following errors: .Bl -tag -width Er @@ -164,7 +174,8 @@ The sum of the .Fa iov_len values in the .Fa iov -array overflowed an unsigned 32-bit integer. +array overflowed an +.Em ssize_t . .It Bq Er EFAULT Part of the .Fa iov diff --git a/lib/libc/sys/recv.2 b/lib/libc/sys/recv.2 index 6da1689db3f..5dea0e73042 100644 --- a/lib/libc/sys/recv.2 +++ b/lib/libc/sys/recv.2 @@ -1,4 +1,4 @@ -.\" $OpenBSD: recv.2,v 1.7 1998/07/28 04:49:31 millert Exp $ +.\" $OpenBSD: recv.2,v 1.8 1998/07/28 19:47:14 millert Exp $ .\" $NetBSD: recv.2,v 1.6 1995/02/27 12:36:08 cgd Exp $ .\" .\" Copyright (c) 1983, 1990, 1991, 1993 @@ -259,7 +259,19 @@ The receive buffer pointer(s) point outside the process's address space. .El .Pp -In addition, +In addition, +.Fn recv +and +.Fn recvfrom +may return following error: +.Bl -tag -width Er +.It Bq Er EINVAL +.Fa len +was larger than +.Ev SSIZE_MAX . +.El +.Pp +Also, .Fn recvmsg may return following error: .Bl -tag -width Er @@ -268,7 +280,8 @@ The sum of the .Fa iov_len values in the .Fa msg_iov -array overflowed an unsigned 32-bit integer. +array overflowed an +.Em ssize_t . .El .Sh SEE ALSO .Xr fcntl 2 , diff --git a/lib/libc/sys/send.2 b/lib/libc/sys/send.2 index be9234bae76..2e522a1be9f 100644 --- a/lib/libc/sys/send.2 +++ b/lib/libc/sys/send.2 @@ -1,4 +1,4 @@ -.\" $OpenBSD: send.2,v 1.6 1998/07/28 04:49:32 millert Exp $ +.\" $OpenBSD: send.2,v 1.7 1998/07/28 19:47:12 millert Exp $ .\" $NetBSD: send.2,v 1.6 1996/01/15 01:17:18 thorpej Exp $ .\" .\" Copyright (c) 1983, 1991, 1993 @@ -34,7 +34,7 @@ .\" .\" @(#)send.2 8.2 (Berkeley) 2/21/94 .\" -.Dd July 27, 1998 +.Dd July 28, 1998 .Dt SEND 2 .Os BSD 4.2 .Sh NAME @@ -161,6 +161,18 @@ parameter is invalid. .El .Pp In addition, +.Fn send +and +.Fn sendto +may return following error: +.Bl -tag -width Er +.It Bq Er EINVAL +.Fa len +was larger than +.Ev SSIZE_MAX . +.El +.Pp +Also, .Fn sendmsg may return following error: .Bl -tag -width Er @@ -169,7 +181,8 @@ The sum of the .Fa iov_len values in the .Fa msg_iov -array overflowed an unsigned 32-bit integer. +array overflowed an +.Em ssize_t . .El .Sh SEE ALSO .Xr fcntl 2 , diff --git a/lib/libc/sys/write.2 b/lib/libc/sys/write.2 index b5d6bb5dcef..5acf9029136 100644 --- a/lib/libc/sys/write.2 +++ b/lib/libc/sys/write.2 @@ -1,4 +1,4 @@ -.\" $OpenBSD: write.2,v 1.5 1998/07/28 04:13:33 millert Exp $ +.\" $OpenBSD: write.2,v 1.6 1998/07/28 19:47:11 millert Exp $ .\" $NetBSD: write.2,v 1.6 1995/02/27 12:39:43 cgd Exp $ .\" .\" Copyright (c) 1980, 1991, 1993 @@ -34,7 +34,7 @@ .\" .\" @(#)write.2 8.5 (Berkeley) 4/2/94 .\" -.Dd April 2, 1994 +.Dd July 28, 1998 .Dt WRITE 2 .Os BSD 4 .Sh NAME @@ -177,7 +177,17 @@ The file was marked for non-blocking I/O, and no data could be written immediately. .El .Pp -In addition, +In addition, +.Fn write +may return following error: +.Bl -tag -width Er +.It Bq Er EINVAL +.Fa nbytes +was larger than +.Ev SSIZE_MAX . +.El +.Pp +Also, .Fn writev may return one of the following errors: .Bl -tag -width Er @@ -190,7 +200,8 @@ The sum of the .Fa iov_len values in the .Fa iov -array overflowed an unsigned 32-bit integer. +array overflowed an +.Em ssize_t . .El .Sh SEE ALSO .Xr fcntl 2 , diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index fb6cf718aef..e7750e21900 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sys_generic.c,v 1.13 1998/07/28 00:12:58 millert Exp $ */ +/* $OpenBSD: sys_generic.c,v 1.14 1998/07/28 19:47:07 millert Exp $ */ /* $NetBSD: sys_generic.c,v 1.24 1996/03/29 00:25:32 cgd Exp $ */ /* @@ -78,8 +78,8 @@ sys_read(p, v, retval) { register struct sys_read_args /* { syscallarg(int) fd; - syscallarg(char *) buf; - syscallarg(u_int) nbyte; + syscallarg(void *) buf; + syscallarg(size_t) nbyte; } */ *uap = v; register struct file *fp; register struct filedesc *fdp = p->p_fd; @@ -94,6 +94,9 @@ sys_read(p, v, retval) (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL || (fp->f_flag & FREAD) == 0) return (EBADF); + /* Don't allow nbyte to be larger than max return val */ + if (SCARG(uap, nbyte) > SSIZE_MAX) + return(EINVAL); aiov.iov_base = (caddr_t)SCARG(uap, buf); aiov.iov_len = SCARG(uap, nbyte); auio.uio_iov = &aiov; @@ -137,7 +140,7 @@ sys_readv(p, v, retval) register struct sys_readv_args /* { syscallarg(int) fd; syscallarg(struct iovec *) iovp; - syscallarg(u_int) iovcnt; + syscallarg(int) iovcnt; } */ *uap = v; register struct file *fp; register struct filedesc *fdp = p->p_fd; @@ -177,14 +180,12 @@ sys_readv(p, v, retval) if (error) goto done; auio.uio_resid = 0; - for (i = 0; i < SCARG(uap, iovcnt); i++) { - if (auio.uio_resid + iov->iov_len < auio.uio_resid) { + for (i = 0; i < SCARG(uap, iovcnt); i++, iov++) { + /* Don't allow sum > SSIZE_MAX */ + if ((ssize_t)(auio.uio_resid += iov->iov_len) <= 0) { error = EINVAL; goto done; } - - auio.uio_resid += iov->iov_len; - iov++; } #ifdef KTRACE /* @@ -228,8 +229,8 @@ sys_write(p, v, retval) { register struct sys_write_args /* { syscallarg(int) fd; - syscallarg(char *) buf; - syscallarg(u_int) nbyte; + syscallarg(void *) buf; + syscallarg(size_t) nbyte; } */ *uap = v; register struct file *fp; register struct filedesc *fdp = p->p_fd; @@ -244,6 +245,9 @@ sys_write(p, v, retval) (fp = fdp->fd_ofiles[SCARG(uap, fd)]) == NULL || (fp->f_flag & FWRITE) == 0) return (EBADF); + /* Don't allow nbyte to be larger than max return val */ + if (SCARG(uap, nbyte) > SSIZE_MAX) + return(EINVAL); aiov.iov_base = (caddr_t)SCARG(uap, buf); aiov.iov_len = SCARG(uap, nbyte); auio.uio_iov = &aiov; @@ -330,14 +334,12 @@ sys_writev(p, v, retval) if (error) goto done; auio.uio_resid = 0; - for (i = 0; i < SCARG(uap, iovcnt); i++) { - if (auio.uio_resid + iov->iov_len < auio.uio_resid) { + for (i = 0; i < SCARG(uap, iovcnt); i++, iov++) { + /* Don't allow sum > SSIZE_MAX */ + if ((ssize_t)(auio.uio_resid += iov->iov_len) <= 0) { error = EINVAL; goto done; } - - auio.uio_resid += iov->iov_len; - iov++; } #ifdef KTRACE /* diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index c7fa95c9ad9..8470e9fb5fe 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -1,4 +1,4 @@ -/* $OpenBSD: uipc_syscalls.c,v 1.9 1998/07/28 04:29:45 millert Exp $ */ +/* $OpenBSD: uipc_syscalls.c,v 1.10 1998/07/28 19:47:08 millert Exp $ */ /* $NetBSD: uipc_syscalls.c,v 1.19 1996/02/09 19:00:48 christos Exp $ */ /* @@ -439,9 +439,9 @@ sendit(p, s, mp, flags, retsize) auio.uio_resid = 0; iov = mp->msg_iov; for (i = 0; i < mp->msg_iovlen; i++, iov++) { - if (auio.uio_resid + iov->iov_len < auio.uio_resid) + /* Don't allow sum > SSIZE_MAX */ + if ((ssize_t)(auio.uio_resid += iov->iov_len) <= 0) return (EINVAL); - auio.uio_resid += iov->iov_len; } if (mp->msg_name) { error = sockargs(&to, mp->msg_name, mp->msg_namelen, @@ -632,9 +632,9 @@ recvit(p, s, mp, namelenp, retsize) auio.uio_resid = 0; iov = mp->msg_iov; for (i = 0; i < mp->msg_iovlen; i++, iov++) { - if (auio.uio_resid + iov->iov_len < auio.uio_resid) + /* Don't allow sum > SSIZE_MAX */ + if ((ssize_t)(auio.uio_resid += iov->iov_len) <= 0) return (EINVAL); - auio.uio_resid += iov->iov_len; } #ifdef KTRACE if (KTRPOINT(p, KTR_GENIO)) { |