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.
This commit is contained in:
parent
b9a5258529
commit
3daa70af17
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: netbsd32.h,v 1.136 2021/01/18 23:14:22 simonb Exp $ */
|
||||
/* $NetBSD: netbsd32.h,v 1.137 2021/01/19 03:41:22 simonb Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998, 2001, 2008, 2015 Matthew R. Green
|
||||
|
@ -58,7 +58,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;
|
||||
|
@ -73,6 +73,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 */
|
||||
|
||||
/*
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: netbsd32_conv.h,v 1.44 2021/01/19 03:20:13 simonb Exp $ */
|
||||
/* $NetBSD: netbsd32_conv.h,v 1.45 2021/01/19 03:41:22 simonb Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998, 2001 Matthew R. Green
|
||||
|
@ -246,13 +246,15 @@ netbsd32_to_iovecin(const struct netbsd32_iovec *iov32p, struct iovec *iovp,
|
|||
{
|
||||
int i, error=0;
|
||||
uint32_t iov_base;
|
||||
uint32_t iov_len;
|
||||
uint32_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;
|
||||
|
@ -260,6 +262,19 @@ netbsd32_to_iovecin(const struct netbsd32_iovec *iov32p, struct iovec *iovp,
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: netbsd32_fs.c,v 1.91 2021/01/19 03:20:13 simonb Exp $ */
|
||||
/* $NetBSD: netbsd32_fs.c,v 1.92 2021/01/19 03:41:22 simonb 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.91 2021/01/19 03:20:13 simonb Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: netbsd32_fs.c,v 1.92 2021/01/19 03:41:22 simonb Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -176,7 +176,8 @@ dofilereadv32(int fd, struct file *fp, struct netbsd32_iovec *iovp, int iovcnt,
|
|||
* 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;
|
||||
}
|
||||
|
@ -281,7 +282,8 @@ dofilewritev32(int fd, struct file *fp, struct netbsd32_iovec *iovp, int iovcnt,
|
|||
* 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;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: netbsd32_netbsd.c,v 1.231 2021/01/15 03:51:41 simonb Exp $ */
|
||||
/* $NetBSD: netbsd32_netbsd.c,v 1.232 2021/01/19 03:41:22 simonb Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1998, 2001, 2008, 2018 Matthew R. Green
|
||||
|
@ -27,7 +27,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: netbsd32_netbsd.c,v 1.231 2021/01/15 03:51:41 simonb Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: netbsd32_netbsd.c,v 1.232 2021/01/19 03:41:22 simonb Exp $");
|
||||
|
||||
/*
|
||||
* below are all the standard NetBSD system calls, in the 32bit
|
||||
|
@ -182,6 +182,9 @@ netbsd32_read(struct lwp *l, const struct netbsd32_read_args *uap, register_t *r
|
|||
} */
|
||||
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);
|
||||
|
@ -198,6 +201,9 @@ netbsd32_write(struct lwp *l, const struct netbsd32_write_args *uap, register_t
|
|||
} */
|
||||
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);
|
||||
|
@ -1181,6 +1187,9 @@ netbsd32_pread(struct lwp *l, const struct netbsd32_pread_args *uap, register_t
|
|||
} */
|
||||
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);
|
||||
|
@ -1202,6 +1211,9 @@ netbsd32_pwrite(struct lwp *l, const struct netbsd32_pwrite_args *uap, register_
|
|||
} */
|
||||
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);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: netbsd32_socket.c,v 1.55 2021/01/19 03:20:13 simonb Exp $ */
|
||||
/* $NetBSD: netbsd32_socket.c,v 1.56 2021/01/19 03:41:22 simonb 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.55 2021/01/19 03:20:13 simonb Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: netbsd32_socket.c,v 1.56 2021/01/19 03:41:22 simonb Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -637,6 +637,9 @@ netbsd32_recvfrom(struct lwp *l, const struct netbsd32_recvfrom_args *uap,
|
|||
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;
|
||||
|
@ -671,6 +674,9 @@ netbsd32_sendto(struct lwp *l, const struct netbsd32_sendto_args *uap,
|
|||
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;
|
||||
|
|
Loading…
Reference in New Issue