diff options
author | kib <kib@FreeBSD.org> | 2012-02-21 01:05:12 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2012-02-21 01:05:12 +0000 |
commit | 80ae8fe82cdaa69f78dc90fa27bc9e79863de0ea (patch) | |
tree | d0d078391c4959fc08545db4ab619daadd9cf1d9 /sys/kern | |
parent | 31a24bc1664a822f3d06595f42063719e6902ff1 (diff) | |
download | FreeBSD-src-80ae8fe82cdaa69f78dc90fa27bc9e79863de0ea.zip FreeBSD-src-80ae8fe82cdaa69f78dc90fa27bc9e79863de0ea.tar.gz |
Fix found places where uio_resid is truncated to int.
Add the sysctl debug.iosize_max_clamp, enabled by default. Setting the
sysctl to zero allows to perform the SSIZE_MAX-sized i/o requests from
the usermode.
Discussed with: bde, das (previous versions)
MFC after: 1 month
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_ctf.c | 2 | ||||
-rw-r--r-- | sys/kern/kern_gzio.c | 4 | ||||
-rw-r--r-- | sys/kern/kern_ktrace.c | 2 | ||||
-rw-r--r-- | sys/kern/kern_linker.c | 5 | ||||
-rw-r--r-- | sys/kern/link_elf.c | 3 | ||||
-rw-r--r-- | sys/kern/link_elf_obj.c | 3 | ||||
-rw-r--r-- | sys/kern/subr_uio.c | 8 | ||||
-rw-r--r-- | sys/kern/sys_generic.c | 22 | ||||
-rw-r--r-- | sys/kern/sys_pipe.c | 13 | ||||
-rw-r--r-- | sys/kern/tty_ttydisc.c | 6 | ||||
-rw-r--r-- | sys/kern/uipc_mbuf.c | 3 | ||||
-rw-r--r-- | sys/kern/uipc_socket.c | 17 | ||||
-rw-r--r-- | sys/kern/uipc_syscalls.c | 29 | ||||
-rw-r--r-- | sys/kern/vfs_extattr.c | 6 | ||||
-rw-r--r-- | sys/kern/vfs_mountroot.c | 5 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 6 | ||||
-rw-r--r-- | sys/kern/vfs_vnops.c | 4 |
17 files changed, 82 insertions, 56 deletions
diff --git a/sys/kern/kern_ctf.c b/sys/kern/kern_ctf.c index 2737860..5ded1be 100644 --- a/sys/kern/kern_ctf.c +++ b/sys/kern/kern_ctf.c @@ -68,7 +68,7 @@ link_elf_ctf_get(linker_file_t lf, linker_ctf_t *lc) int flags; int i; int nbytes; - int resid; + ssize_t resid; int vfslocked; size_t sz; struct nameidata nd; diff --git a/sys/kern/kern_gzio.c b/sys/kern/kern_gzio.c index c1b2b3f..f10998e 100644 --- a/sys/kern/kern_gzio.c +++ b/sys/kern/kern_gzio.c @@ -97,7 +97,7 @@ gzFile gz_open (path, mode, vp) gz_stream *s; char fmode[80]; /* copy of mode, without the compression level */ char *m = fmode; - int resid; + ssize_t resid; int error; char buf[GZ_HEADER_LEN + 1]; @@ -342,7 +342,7 @@ local void putU32 (s, x) { uint32_t xx; off_t curoff = s->outoff; - int resid; + ssize_t resid; #if BYTE_ORDER == BIG_ENDIAN xx = bswap32(x); diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c index 120733e..2c6e36c 100644 --- a/sys/kern/kern_ktrace.c +++ b/sys/kern/kern_ktrace.c @@ -684,7 +684,7 @@ ktrgenio(fd, rw, uio, error) } uio->uio_offset = 0; uio->uio_rw = UIO_WRITE; - datalen = imin(uio->uio_resid, ktr_geniosize); + datalen = MIN(uio->uio_resid, ktr_geniosize); buf = malloc(datalen, M_KTRACE, M_WAITOK); error = uiomove(buf, datalen, uio); free(uio, M_IOV); diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c index 74fe19f..9671ee9 100644 --- a/sys/kern/kern_linker.c +++ b/sys/kern/kern_linker.c @@ -1748,7 +1748,8 @@ linker_hints_lookup(const char *path, int pathlen, const char *modname, struct vattr vattr, mattr; u_char *hints = NULL; u_char *cp, *recptr, *bufend, *result, *best, *pathbuf, *sep; - int error, ival, bestver, *intp, reclen, found, flags, clen, blen; + int error, ival, bestver, *intp, found, flags, clen, blen; + ssize_t reclen; int vfslocked = 0; result = NULL; @@ -1793,7 +1794,7 @@ linker_hints_lookup(const char *path, int pathlen, const char *modname, VFS_UNLOCK_GIANT(vfslocked); nd.ni_vp = NULL; if (reclen != 0) { - printf("can't read %d\n", reclen); + printf("can't read %zd\n", reclen); goto bad; } intp = (int *)hints; diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c index 2f9a1f6..5dd0623 100644 --- a/sys/kern/link_elf.c +++ b/sys/kern/link_elf.c @@ -655,7 +655,8 @@ link_elf_load_file(linker_class_t cls, const char* filename, Elf_Addr base_vaddr; Elf_Addr base_vlimit; int error = 0; - int resid, flags; + ssize_t resid; + int flags; elf_file_t ef; linker_file_t lf; Elf_Shdr *shdr; diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c index 135614c..52d2b2e 100644 --- a/sys/kern/link_elf_obj.c +++ b/sys/kern/link_elf_obj.c @@ -440,7 +440,8 @@ link_elf_load_file(linker_class_t cls, const char *filename, vm_offset_t mapbase; size_t mapsize; int error = 0; - int resid, flags; + ssize_t resid; + int flags; elf_file_t ef; linker_file_t lf; int symtabindex; diff --git a/sys/kern/subr_uio.c b/sys/kern/subr_uio.c index d49e3c3..3c7688a 100644 --- a/sys/kern/subr_uio.c +++ b/sys/kern/subr_uio.c @@ -171,7 +171,7 @@ uiomove_faultflag(void *cp, int n, struct uio *uio, int nofault) { struct thread *td; struct iovec *iov; - u_int cnt; + size_t cnt; int error, newflags, save; td = curthread; @@ -245,14 +245,14 @@ out: int uiomove_frombuf(void *buf, int buflen, struct uio *uio) { - unsigned int offset, n; + size_t offset, n; if (uio->uio_offset < 0 || uio->uio_resid < 0 || (offset = uio->uio_offset) != uio->uio_offset) return (EINVAL); if (buflen <= 0 || offset >= buflen) return (0); - if ((n = buflen - offset) > INT_MAX) + if ((n = buflen - offset) > IOSIZE_MAX) return (EINVAL); return (uiomove((char *)buf + offset, n, uio)); } @@ -479,7 +479,7 @@ copyinuio(const struct iovec *iovp, u_int iovcnt, struct uio **uiop) uio->uio_offset = -1; uio->uio_resid = 0; for (i = 0; i < iovcnt; i++) { - if (iov->iov_len > INT_MAX - uio->uio_resid) { + if (iov->iov_len > IOSIZE_MAX - uio->uio_resid) { free(uio, M_IOV); return (EINVAL); } diff --git a/sys/kern/sys_generic.c b/sys/kern/sys_generic.c index 3be2689..f0e98c6 100644 --- a/sys/kern/sys_generic.c +++ b/sys/kern/sys_generic.c @@ -74,6 +74,10 @@ __FBSDID("$FreeBSD$"); #include <security/audit/audit.h> +int iosize_max_clamp = 1; +SYSCTL_INT(_debug, OID_AUTO, iosize_max_clamp, CTLFLAG_RW, &iosize_max_clamp, 0, + "Clamp max i/o size to INT_MAX"); + static MALLOC_DEFINE(M_IOCTLOPS, "ioctlops", "ioctl data buffer"); static MALLOC_DEFINE(M_SELECT, "select", "select() buffer"); MALLOC_DEFINE(M_IOV, "iov", "large iov's"); @@ -145,7 +149,7 @@ sys_read(td, uap) struct iovec aiov; int error; - if (uap->nbyte > INT_MAX) + if (uap->nbyte > IOSIZE_MAX) return (EINVAL); aiov.iov_base = uap->buf; aiov.iov_len = uap->nbyte; @@ -178,7 +182,7 @@ sys_pread(td, uap) struct iovec aiov; int error; - if (uap->nbyte > INT_MAX) + if (uap->nbyte > IOSIZE_MAX) return (EINVAL); aiov.iov_base = uap->buf; aiov.iov_len = uap->nbyte; @@ -334,7 +338,12 @@ dofileread(td, fd, fp, auio, offset, flags) ktrgenio(fd, UIO_READ, ktruio, error); } #endif +#if SSIZE_MAX > LONG_MAX + td->td_retval[1] = cnt >> (sizeof(register_t) * CHAR_BIT); + td->td_retval[0] = cnt; +#else td->td_retval[0] = cnt; +#endif return (error); } @@ -354,7 +363,7 @@ sys_write(td, uap) struct iovec aiov; int error; - if (uap->nbyte > INT_MAX) + if (uap->nbyte > IOSIZE_MAX) return (EINVAL); aiov.iov_base = (void *)(uintptr_t)uap->buf; aiov.iov_len = uap->nbyte; @@ -387,7 +396,7 @@ sys_pwrite(td, uap) struct iovec aiov; int error; - if (uap->nbyte > INT_MAX) + if (uap->nbyte > IOSIZE_MAX) return (EINVAL); aiov.iov_base = (void *)(uintptr_t)uap->buf; aiov.iov_len = uap->nbyte; @@ -546,7 +555,12 @@ dofilewrite(td, fd, fp, auio, offset, flags) ktrgenio(fd, UIO_WRITE, ktruio, error); } #endif +#if SSIZE_MAX > LONG_MAX + td->td_retval[1] = cnt >> (sizeof(register_t) * CHAR_BIT); td->td_retval[0] = cnt; +#else + td->td_retval[0] = cnt; +#endif return (error); } diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c index 9edcb74..0cb4fce 100644 --- a/sys/kern/sys_pipe.c +++ b/sys/kern/sys_pipe.c @@ -617,7 +617,7 @@ pipe_read(fp, uio, active_cred, flags, td) size = rpipe->pipe_buffer.size - rpipe->pipe_buffer.out; if (size > rpipe->pipe_buffer.cnt) size = rpipe->pipe_buffer.cnt; - if (size > (u_int) uio->uio_resid) + if (size > uio->uio_resid) size = (u_int) uio->uio_resid; PIPE_UNLOCK(rpipe); @@ -650,7 +650,7 @@ pipe_read(fp, uio, active_cred, flags, td) */ } else if ((size = rpipe->pipe_map.cnt) && (rpipe->pipe_state & PIPE_DIRECTW)) { - if (size > (u_int) uio->uio_resid) + if (size > uio->uio_resid) size = (u_int) uio->uio_resid; PIPE_UNLOCK(rpipe); @@ -764,9 +764,10 @@ pipe_build_write_buffer(wpipe, uio) KASSERT(wpipe->pipe_state & PIPE_DIRECTW, ("Clone attempt on non-direct write pipe!")); - size = (u_int) uio->uio_iov->iov_len; - if (size > wpipe->pipe_buffer.size) - size = wpipe->pipe_buffer.size; + if (uio->uio_iov->iov_len > wpipe->pipe_buffer.size) + size = wpipe->pipe_buffer.size; + else + size = uio->uio_iov->iov_len; if ((i = vm_fault_quick_hold_pages(&curproc->p_vmspace->vm_map, (vm_offset_t)uio->uio_iov->iov_base, size, VM_PROT_READ, @@ -960,7 +961,7 @@ pipe_write(fp, uio, active_cred, flags, td) int flags; { int error = 0; - int desiredsize, orig_resid; + size_t desiredsize, orig_resid; struct pipe *wpipe, *rpipe; rpipe = fp->f_data; diff --git a/sys/kern/tty_ttydisc.c b/sys/kern/tty_ttydisc.c index 1ac204b..6d36de4 100644 --- a/sys/kern/tty_ttydisc.c +++ b/sys/kern/tty_ttydisc.c @@ -180,7 +180,7 @@ static int ttydisc_read_raw_no_timer(struct tty *tp, struct uio *uio, int ioflag) { size_t vmin = tp->t_termios.c_cc[VMIN]; - int oresid = uio->uio_resid; + ssize_t oresid = uio->uio_resid; int error; MPASS(tp->t_termios.c_cc[VTIME] == 0); @@ -265,7 +265,7 @@ static int ttydisc_read_raw_interbyte_timer(struct tty *tp, struct uio *uio, int ioflag) { size_t vmin = tp->t_termios.c_cc[VMIN]; - int oresid = uio->uio_resid; + ssize_t oresid = uio->uio_resid; int error; MPASS(tp->t_termios.c_cc[VMIN] != 0); @@ -1173,7 +1173,7 @@ int ttydisc_getc_uio(struct tty *tp, struct uio *uio) { int error = 0; - int obytes = uio->uio_resid; + ssize_t obytes = uio->uio_resid; size_t len; char buf[TTY_STACKBUF]; diff --git a/sys/kern/uipc_mbuf.c b/sys/kern/uipc_mbuf.c index 620246b..a6fda75 100644 --- a/sys/kern/uipc_mbuf.c +++ b/sys/kern/uipc_mbuf.c @@ -1726,7 +1726,8 @@ struct mbuf * m_uiotombuf(struct uio *uio, int how, int len, int align, int flags) { struct mbuf *m, *mb; - int error, length, total; + int error, length; + ssize_t total; int progress = 0; /* diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c index 91309de..d11e870 100644 --- a/sys/kern/uipc_socket.c +++ b/sys/kern/uipc_socket.c @@ -887,7 +887,8 @@ sosend_copyin(struct uio *uio, struct mbuf **retmp, int atomic, long *space, int flags) { struct mbuf *m, **mp, *top; - long len, resid; + long len; + ssize_t resid; int error; #ifdef ZERO_COPY_SOCKETS int cow_send; @@ -987,7 +988,8 @@ int sosend_dgram(struct socket *so, struct sockaddr *addr, struct uio *uio, struct mbuf *top, struct mbuf *control, int flags, struct thread *td) { - long space, resid; + long space; + ssize_t resid; int clen = 0, error, dontroute; #ifdef ZERO_COPY_SOCKETS int atomic = sosendallatonce(so) || top; @@ -1159,7 +1161,8 @@ int sosend_generic(struct socket *so, struct sockaddr *addr, struct uio *uio, struct mbuf *top, struct mbuf *control, int flags, struct thread *td) { - long space, resid; + long space; + ssize_t resid; int clen = 0, error, dontroute; int atomic = sosendallatonce(so) || top; @@ -1456,11 +1459,12 @@ soreceive_generic(struct socket *so, struct sockaddr **psa, struct uio *uio, struct mbuf **mp0, struct mbuf **controlp, int *flagsp) { struct mbuf *m, **mp; - int flags, len, error, offset; + int flags, error, offset; + ssize_t len; struct protosw *pr = so->so_proto; struct mbuf *nextrecord; int moff, type = 0; - int orig_resid = uio->uio_resid; + ssize_t orig_resid = uio->uio_resid; mp = mp0; if (psa != NULL) @@ -2119,7 +2123,8 @@ soreceive_dgram(struct socket *so, struct sockaddr **psa, struct uio *uio, struct mbuf **mp0, struct mbuf **controlp, int *flagsp) { struct mbuf *m, *m2; - int flags, len, error; + int flags, error; + ssize_t len; struct protosw *pr = so->so_proto; struct mbuf *nextrecord; diff --git a/sys/kern/uipc_syscalls.c b/sys/kern/uipc_syscalls.c index 3b83e1c..3b44848 100644 --- a/sys/kern/uipc_syscalls.c +++ b/sys/kern/uipc_syscalls.c @@ -756,8 +756,8 @@ kern_sendit(td, s, mp, flags, control, segflg) struct uio auio; struct iovec *iov; struct socket *so; - int i; - int len, error; + int i, error; + ssize_t len; cap_rights_t rights; #ifdef KTRACE struct uio *ktruio = NULL; @@ -956,7 +956,7 @@ kern_recvit(td, s, mp, fromseg, controlp) struct uio auio; struct iovec *iov; int i; - socklen_t len; + ssize_t len; int error; struct mbuf *m, *control = 0; caddr_t ctlbuf; @@ -1007,19 +1007,19 @@ kern_recvit(td, s, mp, fromseg, controlp) (mp->msg_control || controlp) ? &control : (struct mbuf **)0, &mp->msg_flags); if (error) { - if (auio.uio_resid != (int)len && (error == ERESTART || + if (auio.uio_resid != len && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; } #ifdef KTRACE if (ktruio != NULL) { - ktruio->uio_resid = (int)len - auio.uio_resid; + ktruio->uio_resid = len - auio.uio_resid; ktrgenio(s, UIO_READ, ktruio, error); } #endif if (error) goto out; - td->td_retval[0] = (int)len - auio.uio_resid; + td->td_retval[0] = len - auio.uio_resid; if (mp->msg_name) { len = mp->msg_namelen; if (len <= 0 || fromsa == 0) @@ -2086,7 +2086,8 @@ retry_space: else if (uap->flags & SF_NODISKIO) error = EBUSY; else { - int bsize, resid; + int bsize; + ssize_t resid; /* * Ensure that our page is still around @@ -2510,7 +2511,8 @@ sys_sctp_generic_sendmsg_iov(td, uap) struct sctp_sndrcvinfo sinfo, *u_sinfo = NULL; struct socket *so; struct file *fp = NULL; - int error=0, len, i; + int error=0, i; + ssize_t len; struct sockaddr *to = NULL; #ifdef KTRACE struct uio *ktruio = NULL; @@ -2637,7 +2639,8 @@ sys_sctp_generic_recvmsg(td, uap) struct file *fp = NULL; struct sockaddr *fromsa; int fromlen; - int len, i, msg_flags; + ssize_t len; + int i, msg_flags; int error = 0; #ifdef KTRACE struct uio *ktruio = NULL; @@ -2711,7 +2714,7 @@ sys_sctp_generic_recvmsg(td, uap) (struct sctp_sndrcvinfo *)&sinfo, 1); CURVNET_RESTORE(); if (error) { - if (auio.uio_resid != (int)len && (error == ERESTART || + if (auio.uio_resid != len && (error == ERESTART || error == EINTR || error == EWOULDBLOCK)) error = 0; } else { @@ -2720,13 +2723,13 @@ sys_sctp_generic_recvmsg(td, uap) } #ifdef KTRACE if (ktruio != NULL) { - ktruio->uio_resid = (int)len - auio.uio_resid; + ktruio->uio_resid = len - auio.uio_resid; ktrgenio(uap->sd, UIO_READ, ktruio, error); } #endif /* KTRACE */ if (error) goto out; - td->td_retval[0] = (int)len - auio.uio_resid; + td->td_retval[0] = len - auio.uio_resid; if (fromlen && uap->from) { len = fromlen; @@ -2734,7 +2737,7 @@ sys_sctp_generic_recvmsg(td, uap) len = 0; else { len = MIN(len, fromsa->sa_len); - error = copyout(fromsa, uap->from, (unsigned)len); + error = copyout(fromsa, uap->from, (size_t)len); if (error) goto out; } diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index 7732a94..a6355d9 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.c @@ -181,7 +181,7 @@ extattr_set_vp(struct vnode *vp, int attrnamespace, const char *attrname, auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_offset = 0; - if (nbytes > INT_MAX) { + if (nbytes > IOSIZE_MAX) { error = EINVAL; goto done; } @@ -355,7 +355,7 @@ extattr_get_vp(struct vnode *vp, int attrnamespace, const char *attrname, auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_offset = 0; - if (nbytes > INT_MAX) { + if (nbytes > IOSIZE_MAX) { error = EINVAL; goto done; } @@ -672,7 +672,7 @@ extattr_list_vp(struct vnode *vp, int attrnamespace, void *data, auio.uio_iov = &aiov; auio.uio_iovcnt = 1; auio.uio_offset = 0; - if (nbytes > INT_MAX) { + if (nbytes > IOSIZE_MAX) { error = EINVAL; goto done; } diff --git a/sys/kern/vfs_mountroot.c b/sys/kern/vfs_mountroot.c index c722bd3..62a49ae 100644 --- a/sys/kern/vfs_mountroot.c +++ b/sys/kern/vfs_mountroot.c @@ -871,9 +871,8 @@ vfs_mountroot_readconf(struct thread *td, struct sbuf *sb) static char buf[128]; struct nameidata nd; off_t ofs; - int error, flags; - int len, resid; - int vfslocked; + ssize_t resid; + int error, flags, len, vfslocked; NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE, UIO_SYSSPACE, "/.mount.conf", td); diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index e460570..9b7cbe4 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -2692,7 +2692,7 @@ kern_readlinkat(struct thread *td, int fd, char *path, enum uio_seg pathseg, struct nameidata nd; int vfslocked; - if (count > INT_MAX) + if (count > IOSIZE_MAX) return (EINVAL); NDINIT_AT(&nd, LOOKUP, NOFOLLOW | LOCKSHARED | LOCKLEAF | MPSAFE | @@ -4153,7 +4153,8 @@ kern_getdirentries(struct thread *td, int fd, char *buf, u_int count, int error, eofflag; AUDIT_ARG_FD(fd); - if (count > INT_MAX) + auio.uio_resid = count; + if (auio.uio_resid > IOSIZE_MAX) return (EINVAL); if ((error = getvnode(td->td_proc->p_fd, fd, CAP_READ | CAP_SEEK, &fp)) != 0) @@ -4177,7 +4178,6 @@ unionread: auio.uio_rw = UIO_READ; auio.uio_segflg = UIO_USERSPACE; auio.uio_td = td; - auio.uio_resid = count; vn_lock(vp, LK_SHARED | LK_RETRY); AUDIT_ARG_VNODE1(vp); loff = auio.uio_offset = fp->f_offset; diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c index f94bc12..ce2d701 100644 --- a/sys/kern/vfs_vnops.c +++ b/sys/kern/vfs_vnops.c @@ -373,7 +373,7 @@ vn_rdwr(rw, vp, base, len, offset, segflg, ioflg, active_cred, file_cred, int ioflg; struct ucred *active_cred; struct ucred *file_cred; - int *aresid; + ssize_t *aresid; struct thread *td; { struct uio auio; @@ -470,7 +470,7 @@ vn_rdwr_inchunks(rw, vp, base, len, offset, segflg, ioflg, active_cred, struct thread *td; { int error = 0; - int iaresid; + ssize_t iaresid; VFS_ASSERT_GIANT(vp->v_mount); |