summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTodd C. Miller <millert@cvs.openbsd.org>1998-07-28 19:47:15 +0000
committerTodd C. Miller <millert@cvs.openbsd.org>1998-07-28 19:47:15 +0000
commit3287b64e077693dbe8e5b8138453f03f4060e739 (patch)
tree76b77e1d456db5a77e92b64b2a16746f94ea8ab6
parent996b26293c9ed22d2a4601386081731cf9f5a238 (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.217
-rw-r--r--lib/libc/sys/recv.219
-rw-r--r--lib/libc/sys/send.219
-rw-r--r--lib/libc/sys/write.219
-rw-r--r--sys/kern/sys_generic.c34
-rw-r--r--sys/kern/uipc_syscalls.c10
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)) {