Module Name: src Committed By: martin Date: Wed Jun 21 20:38:35 UTC 2023
Modified Files: src/sys/compat/netbsd32 [netbsd-8]: netbsd32.h netbsd32_conv.h netbsd32_fs.c netbsd32_netbsd.c netbsd32_socket.c Log Message: Pull up following revision(s) (requested by riastradh in ticket #1833): sys/compat/netbsd32/netbsd32_netbsd.c: revision 1.232 sys/compat/netbsd32/netbsd32_socket.c: revision 1.56 sys/compat/netbsd32/netbsd32_conv.h: revision 1.45 sys/compat/netbsd32/netbsd32_fs.c: revision 1.92 sys/compat/netbsd32/netbsd32.h: revision 1.137 The read/write/send/recv system calls return ssize_t because -1 is returned on error. Therefore we must restrict the lengths of any buffers to NETBSD32_SSIZE_MAX with compat32 to avoid garbage return values. Fixes ATF lib/libc/sys/t_write:write_err. To generate a diff of this commit: cvs rdiff -u -r1.114.8.3 -r1.114.8.4 src/sys/compat/netbsd32/netbsd32.h cvs rdiff -u -r1.31.8.3 -r1.31.8.4 src/sys/compat/netbsd32/netbsd32_conv.h cvs rdiff -u -r1.80.2.1 -r1.80.2.2 src/sys/compat/netbsd32/netbsd32_fs.c cvs rdiff -u -r1.206.2.2 -r1.206.2.3 \ src/sys/compat/netbsd32/netbsd32_netbsd.c cvs rdiff -u -r1.44.8.1 -r1.44.8.2 src/sys/compat/netbsd32/netbsd32_socket.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/compat/netbsd32/netbsd32.h diff -u src/sys/compat/netbsd32/netbsd32.h:1.114.8.3 src/sys/compat/netbsd32/netbsd32.h:1.114.8.4 --- src/sys/compat/netbsd32/netbsd32.h:1.114.8.3 Sat Aug 25 11:13:05 2018 +++ src/sys/compat/netbsd32/netbsd32.h Wed Jun 21 20:38:35 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32.h,v 1.114.8.3 2018/08/25 11:13:05 martin Exp $ */ +/* $NetBSD: netbsd32.h,v 1.114.8.4 2023/06/21 20:38:35 martin Exp $ */ /* * Copyright (c) 1998, 2001, 2008, 2015 Matthew R. Green @@ -54,7 +54,7 @@ #include <nfs/rpcv2.h> /* - * first, define the basic types we need. + * first define the basic types we need, and any applicable limits. */ typedef int32_t netbsd32_long; @@ -69,6 +69,9 @@ typedef int32_t netbsd32_key_t; typedef int32_t netbsd32_intptr_t; typedef uint32_t netbsd32_uintptr_t; +/* Note: 32-bit sparc defines ssize_t as long but still has same size as int. */ +#define NETBSD32_SSIZE_MAX INT32_MAX + /* netbsd32_[u]int64 are machine dependent and defined below */ /* Index: src/sys/compat/netbsd32/netbsd32_conv.h diff -u src/sys/compat/netbsd32/netbsd32_conv.h:1.31.8.3 src/sys/compat/netbsd32/netbsd32_conv.h:1.31.8.4 --- src/sys/compat/netbsd32/netbsd32_conv.h:1.31.8.3 Sat Feb 23 06:58:14 2019 +++ src/sys/compat/netbsd32/netbsd32_conv.h Wed Jun 21 20:38:35 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32_conv.h,v 1.31.8.3 2019/02/23 06:58:14 martin Exp $ */ +/* $NetBSD: netbsd32_conv.h,v 1.31.8.4 2023/06/21 20:38:35 martin Exp $ */ /* * Copyright (c) 1998, 2001 Matthew R. Green @@ -251,13 +251,15 @@ netbsd32_to_iovecin(const struct netbsd3 { int i, error=0; u_int32_t iov_base; - u_int32_t iov_len; + u_int32_t iov_len, total_iov_len; + /* * We could allocate an iov32p, do a copyin, and translate * each field and then free it all up, or we could copyin * each field separately. I'm doing the latter to reduce * the number of MALLOC()s. */ + total_iov_len = 0; for (i = 0; i < len; i++, iovp++, iov32p++) { if ((error = copyin(&iov32p->iov_base, &iov_base, sizeof(iov_base)))) return (error); @@ -265,6 +267,19 @@ netbsd32_to_iovecin(const struct netbsd3 return (error); iovp->iov_base = (void *)(u_long)iov_base; iovp->iov_len = (size_t)iov_len; + + /* + * System calls return ssize_t because -1 is returned + * on error. Therefore we must restrict the length to + * SSIZE_MAX (NETBSD32_SSIZE_MAX with compat32) to + * avoid garbage return values. + */ + total_iov_len += iov_len; + if (iov_len > NETBSD32_SSIZE_MAX || + total_iov_len > NETBSD32_SSIZE_MAX) { + return EINVAL; + break; + } } return error; } Index: src/sys/compat/netbsd32/netbsd32_fs.c diff -u src/sys/compat/netbsd32/netbsd32_fs.c:1.80.2.1 src/sys/compat/netbsd32/netbsd32_fs.c:1.80.2.2 --- src/sys/compat/netbsd32/netbsd32_fs.c:1.80.2.1 Sat Aug 25 11:13:05 2018 +++ src/sys/compat/netbsd32/netbsd32_fs.c Wed Jun 21 20:38:35 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32_fs.c,v 1.80.2.1 2018/08/25 11:13:05 martin Exp $ */ +/* $NetBSD: netbsd32_fs.c,v 1.80.2.2 2023/06/21 20:38:35 martin Exp $ */ /* * Copyright (c) 1998, 2001 Matthew R. Green @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: netbsd32_fs.c,v 1.80.2.1 2018/08/25 11:13:05 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: netbsd32_fs.c,v 1.80.2.2 2023/06/21 20:38:35 martin Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -175,7 +175,8 @@ dofilereadv32(int fd, struct file *fp, s * Therefore we must restrict the length to SSIZE_MAX to * avoid garbage return values. */ - if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) { + if (iov->iov_len > NETBSD32_SSIZE_MAX || + auio.uio_resid > NETBSD32_SSIZE_MAX) { error = EINVAL; goto done; } @@ -279,7 +280,8 @@ dofilewritev32(int fd, struct file *fp, * Therefore we must restrict the length to SSIZE_MAX to * avoid garbage return values. */ - if (iov->iov_len > SSIZE_MAX || auio.uio_resid > SSIZE_MAX) { + if (iov->iov_len > NETBSD32_SSIZE_MAX || + auio.uio_resid > NETBSD32_SSIZE_MAX) { error = EINVAL; goto done; } Index: src/sys/compat/netbsd32/netbsd32_netbsd.c diff -u src/sys/compat/netbsd32/netbsd32_netbsd.c:1.206.2.2 src/sys/compat/netbsd32/netbsd32_netbsd.c:1.206.2.3 --- src/sys/compat/netbsd32/netbsd32_netbsd.c:1.206.2.2 Thu Dec 27 12:04:09 2018 +++ src/sys/compat/netbsd32/netbsd32_netbsd.c Wed Jun 21 20:38:35 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32_netbsd.c,v 1.206.2.2 2018/12/27 12:04:09 martin Exp $ */ +/* $NetBSD: netbsd32_netbsd.c,v 1.206.2.3 2023/06/21 20:38:35 martin Exp $ */ /* * Copyright (c) 1998, 2001, 2008 Matthew R. Green @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: netbsd32_netbsd.c,v 1.206.2.2 2018/12/27 12:04:09 martin Exp $"); +__KERNEL_RCSID(0, "$NetBSD: netbsd32_netbsd.c,v 1.206.2.3 2023/06/21 20:38:35 martin Exp $"); #if defined(_KERNEL_OPT) #include "opt_ddb.h" @@ -198,6 +198,9 @@ netbsd32_read(struct lwp *l, const struc } */ struct sys_read_args ua; + if (SCARG(uap, nbyte) > NETBSD32_SSIZE_MAX) + return EINVAL; + NETBSD32TO64_UAP(fd); NETBSD32TOP_UAP(buf, void *); NETBSD32TOX_UAP(nbyte, size_t); @@ -214,6 +217,9 @@ netbsd32_write(struct lwp *l, const stru } */ struct sys_write_args ua; + if (SCARG(uap, nbyte) > NETBSD32_SSIZE_MAX) + return EINVAL; + NETBSD32TO64_UAP(fd); NETBSD32TOP_UAP(buf, void *); NETBSD32TOX_UAP(nbyte, size_t); @@ -1341,6 +1347,9 @@ netbsd32_pread(struct lwp *l, const stru } */ struct sys_pread_args ua; + if (SCARG(uap, nbyte) > NETBSD32_SSIZE_MAX) + return EINVAL; + NETBSD32TO64_UAP(fd); NETBSD32TOP_UAP(buf, void); NETBSD32TOX_UAP(nbyte, size_t); @@ -1361,6 +1370,9 @@ netbsd32_pwrite(struct lwp *l, const str } */ struct sys_pwrite_args ua; + if (SCARG(uap, nbyte) > NETBSD32_SSIZE_MAX) + return EINVAL; + NETBSD32TO64_UAP(fd); NETBSD32TOP_UAP(buf, void); NETBSD32TOX_UAP(nbyte, size_t); Index: src/sys/compat/netbsd32/netbsd32_socket.c diff -u src/sys/compat/netbsd32/netbsd32_socket.c:1.44.8.1 src/sys/compat/netbsd32/netbsd32_socket.c:1.44.8.2 --- src/sys/compat/netbsd32/netbsd32_socket.c:1.44.8.1 Tue Nov 13 16:55:22 2018 +++ src/sys/compat/netbsd32/netbsd32_socket.c Wed Jun 21 20:38:35 2023 @@ -1,4 +1,4 @@ -/* $NetBSD: netbsd32_socket.c,v 1.44.8.1 2018/11/13 16:55:22 snj Exp $ */ +/* $NetBSD: netbsd32_socket.c,v 1.44.8.2 2023/06/21 20:38:35 martin Exp $ */ /* * Copyright (c) 1998, 2001 Matthew R. Green @@ -27,7 +27,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: netbsd32_socket.c,v 1.44.8.1 2018/11/13 16:55:22 snj Exp $"); +__KERNEL_RCSID(0, "$NetBSD: netbsd32_socket.c,v 1.44.8.2 2023/06/21 20:38:35 martin Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -399,6 +399,9 @@ netbsd32_recvfrom(struct lwp *l, const s int error; struct mbuf *from; + if (SCARG(uap, len) > NETBSD32_SSIZE_MAX) + return EINVAL; + msg.msg_name = NULL; msg.msg_iov = &aiov; msg.msg_iovlen = 1; @@ -433,6 +436,9 @@ netbsd32_sendto(struct lwp *l, const str struct msghdr msg; struct iovec aiov; + if (SCARG(uap, len) > NETBSD32_SSIZE_MAX) + return EINVAL; + msg.msg_name = SCARG_P32(uap, to); /* XXX kills const */ msg.msg_namelen = SCARG(uap, tolen); msg.msg_iov = &aiov;