Index: sys/fs/procfs/procfs_dbregs.c =================================================================== RCS file: /home/ncvs/src/sys/fs/procfs/procfs_dbregs.c,v retrieving revision 1.22 diff -p -c -r1.22 procfs_dbregs.c *** sys/fs/procfs/procfs_dbregs.c 5 May 2003 15:12:51 -0000 1.22 --- sys/fs/procfs/procfs_dbregs.c 3 Oct 2003 12:52:17 -0000 *************** procfs_doprocdbregs(PFS_FILL_ARGS) *** 65,95 **** { int error; struct dbreg r; - char *kv; - int kl; PROC_LOCK(p); if (p_candebug(td, p) != 0) { PROC_UNLOCK(p); return (EPERM); } - kl = sizeof(r); - kv = (char *) &r; - - kv += uio->uio_offset; - kl -= uio->uio_offset; - if (kl > uio->uio_resid) - kl = uio->uio_resid; _PHOLD(p); ! if (kl < 0) ! error = EINVAL; ! else ! /* XXXKSE: */ ! error = proc_read_dbregs(FIRST_THREAD_IN_PROC(p), &r); if (error == 0) { PROC_UNLOCK(p); ! error = uiomove(kv, kl, uio); PROC_LOCK(p); } if (error == 0 && uio->uio_rw == UIO_WRITE) { --- 65,83 ---- { int error; struct dbreg r; PROC_LOCK(p); if (p_candebug(td, p) != 0) { PROC_UNLOCK(p); return (EPERM); } _PHOLD(p); ! /* XXXKSE: */ ! error = proc_read_dbregs(FIRST_THREAD_IN_PROC(p), &r); if (error == 0) { PROC_UNLOCK(p); ! error = uiomove_frombuf(&r, sizeof(r), uio); PROC_LOCK(p); } if (error == 0 && uio->uio_rw == UIO_WRITE) { Index: sys/fs/procfs/procfs_fpregs.c =================================================================== RCS file: /home/ncvs/src/sys/fs/procfs/procfs_fpregs.c,v retrieving revision 1.28 diff -p -c -r1.28 procfs_fpregs.c *** sys/fs/procfs/procfs_fpregs.c 5 May 2003 15:12:51 -0000 1.28 --- sys/fs/procfs/procfs_fpregs.c 3 Oct 2003 12:52:18 -0000 *************** procfs_doprocfpregs(PFS_FILL_ARGS) *** 59,89 **** { int error; struct fpreg r; - char *kv; - int kl; PROC_LOCK(p); if (p_candebug(td, p)) { PROC_UNLOCK(p); return (EPERM); } - kl = sizeof(r); - kv = (char *) &r; - - kv += uio->uio_offset; - kl -= uio->uio_offset; - if (kl > uio->uio_resid) - kl = uio->uio_resid; _PHOLD(p); ! if (kl < 0) ! error = EINVAL; ! else ! /* XXXKSE: */ ! error = proc_read_fpregs(FIRST_THREAD_IN_PROC(p), &r); if (error == 0) { PROC_UNLOCK(p); ! error = uiomove(kv, kl, uio); PROC_LOCK(p); } if (error == 0 && uio->uio_rw == UIO_WRITE) { --- 59,77 ---- { int error; struct fpreg r; PROC_LOCK(p); if (p_candebug(td, p)) { PROC_UNLOCK(p); return (EPERM); } _PHOLD(p); ! /* XXXKSE: */ ! error = proc_read_fpregs(FIRST_THREAD_IN_PROC(p), &r); if (error == 0) { PROC_UNLOCK(p); ! error = uiomove_frombuf(&r, sizeof(r), uio); PROC_LOCK(p); } if (error == 0 && uio->uio_rw == UIO_WRITE) { Index: sys/fs/procfs/procfs_regs.c =================================================================== RCS file: /home/ncvs/src/sys/fs/procfs/procfs_regs.c,v retrieving revision 1.27 diff -p -c -r1.27 procfs_regs.c *** sys/fs/procfs/procfs_regs.c 5 May 2003 15:12:51 -0000 1.27 --- sys/fs/procfs/procfs_regs.c 3 Oct 2003 12:52:18 -0000 *************** procfs_doprocregs(PFS_FILL_ARGS) *** 59,89 **** { int error; struct reg r; - char *kv; - int kl; PROC_LOCK(p); if (p_candebug(td, p)) { PROC_UNLOCK(p); return (EPERM); } - kl = sizeof(r); - kv = (char *) &r; - - kv += uio->uio_offset; - kl -= uio->uio_offset; - if (kl > uio->uio_resid) - kl = uio->uio_resid; _PHOLD(p); ! if (kl < 0) ! error = EINVAL; ! else ! /* XXXKSE: */ ! error = proc_read_regs(FIRST_THREAD_IN_PROC(p), &r); if (error == 0) { PROC_UNLOCK(p); ! error = uiomove(kv, kl, uio); PROC_LOCK(p); } if (error == 0 && uio->uio_rw == UIO_WRITE) { --- 59,77 ---- { int error; struct reg r; PROC_LOCK(p); if (p_candebug(td, p)) { PROC_UNLOCK(p); return (EPERM); } _PHOLD(p); ! /* XXXKSE: */ ! error = proc_read_regs(FIRST_THREAD_IN_PROC(p), &r); if (error == 0) { PROC_UNLOCK(p); ! error = uiomove_frombuf(&r, sizeof(r), uio); PROC_LOCK(p); } if (error == 0 && uio->uio_rw == UIO_WRITE) { Index: sys/fs/pseudofs/pseudofs_vnops.c =================================================================== RCS file: /home/ncvs/src/sys/fs/pseudofs/pseudofs_vnops.c,v retrieving revision 1.35 diff -p -c -r1.35 pseudofs_vnops.c *** sys/fs/pseudofs/pseudofs_vnops.c 2 Mar 2003 22:23:45 -0000 1.35 --- sys/fs/pseudofs/pseudofs_vnops.c 3 Oct 2003 12:52:18 -0000 *************** *** 34,39 **** --- 34,40 ---- #include #include #include + #include #include #include #include *************** pfs_read(struct vop_read_args *va) *** 472,479 **** struct uio *uio = va->a_uio; struct proc *proc = NULL; struct sbuf *sb = NULL; ! char *ps; ! int error, xlen; PFS_TRACE((pn->pn_name)); --- 473,480 ---- struct uio *uio = va->a_uio; struct proc *proc = NULL; struct sbuf *sb = NULL; ! int error; ! unsigned int buflen, offset, resid; PFS_TRACE((pn->pn_name)); *************** pfs_read(struct vop_read_args *va) *** 508,514 **** PFS_RETURN (error); } ! sb = sbuf_new(sb, NULL, uio->uio_offset + uio->uio_resid, 0); if (sb == NULL) { if (proc != NULL) PRELE(proc); --- 509,524 ---- PFS_RETURN (error); } ! /* Beaucoup sanity checks so we don't ask for bogus allocation. */ ! if (uio->uio_offset < 0 || uio->uio_resid < 0 || ! (offset = uio->uio_offset) != uio->uio_offset || ! (resid = uio->uio_resid) != uio->uio_resid || ! (buflen = offset + resid) < offset || buflen > INT_MAX) { ! if (proc != NULL) ! PRELE(proc); ! PFS_RETURN (EINVAL); ! } ! sb = sbuf_new(sb, NULL, buflen, 0); if (sb == NULL) { if (proc != NULL) PRELE(proc); *************** pfs_read(struct vop_read_args *va) *** 525,536 **** PFS_RETURN (error); } - /* XXX we should possibly detect and handle overflows */ sbuf_finish(sb); ! ps = sbuf_data(sb) + uio->uio_offset; ! xlen = sbuf_len(sb) - uio->uio_offset; ! xlen = imin(xlen, uio->uio_resid); ! error = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio)); sbuf_delete(sb); PFS_RETURN (error); } --- 535,542 ---- PFS_RETURN (error); } sbuf_finish(sb); ! error = uiomove_frombuf(sbuf_data(sb), sbuf_len(sb), uio); sbuf_delete(sb); PFS_RETURN (error); } *************** pfs_readlink(struct vop_readlink_args *v *** 676,684 **** struct pfs_node *pn = pvd->pvd_pn; struct uio *uio = va->a_uio; struct proc *proc = NULL; ! char buf[MAXPATHLEN], *ps; struct sbuf sb; ! int error, xlen; PFS_TRACE((pn->pn_name)); --- 682,690 ---- struct pfs_node *pn = pvd->pvd_pn; struct uio *uio = va->a_uio; struct proc *proc = NULL; ! char buf[MAXPATHLEN]; struct sbuf sb; ! int error; PFS_TRACE((pn->pn_name)); *************** pfs_readlink(struct vop_readlink_args *v *** 708,719 **** PFS_RETURN (error); } - /* XXX we should detect and handle overflows */ sbuf_finish(&sb); ! ps = sbuf_data(&sb) + uio->uio_offset; ! xlen = sbuf_len(&sb) - uio->uio_offset; ! xlen = imin(xlen, uio->uio_resid); ! error = (xlen <= 0 ? 0 : uiomove(ps, xlen, uio)); sbuf_delete(&sb); PFS_RETURN (error); } --- 714,721 ---- PFS_RETURN (error); } sbuf_finish(&sb); ! error = uiomove_frombuf(sbuf_data(&sb), sbuf_len(&sb), uio); sbuf_delete(&sb); PFS_RETURN (error); } Index: sys/kern/kern_subr.c =================================================================== RCS file: /home/ncvs/src/sys/kern/kern_subr.c,v retrieving revision 1.74 diff -p -c -r1.74 kern_subr.c *** sys/kern/kern_subr.c 5 May 2003 21:27:29 -0000 1.74 --- sys/kern/kern_subr.c 3 Oct 2003 12:52:18 -0000 *************** *** 45,50 **** --- 45,51 ---- #include #include #include + #include #include #include #include *************** out: *** 191,196 **** --- 192,219 ---- mtx_unlock_spin(&sched_lock); } return (error); + } + + /* + * Wrapper for uiomove() that validates the arguments against a known-good + * kernel buffer. Currently, uiomove accepts a signed (n) argument, which + * is almost definitely a bad thing, so we catch that here as well. We + * return a runtime failure, but it might be desirable to generate a runtime + * assertion failure instead. + */ + int + uiomove_frombuf(void *buf, int buflen, struct uio *uio) + { + unsigned int 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) + return (EINVAL); + return (uiomove((char *)buf + offset, n, uio)); } #ifdef ZERO_COPY_SOCKETS Index: sys/sys/uio.h =================================================================== RCS file: /home/ncvs/src/sys/sys/uio.h,v retrieving revision 1.27 diff -p -c -r1.27 uio.h *** sys/sys/uio.h 6 Mar 2003 03:41:01 -0000 1.27 --- sys/sys/uio.h 3 Oct 2003 12:52:18 -0000 *************** struct vm_object; *** 87,92 **** --- 87,93 ---- void uio_yield(void); int uiomove(void *, int, struct uio *); + int uiomove_frombuf(void *buf, int buflen, struct uio *uio); int uiomoveco(void *, int, struct uio *, struct vm_object *, int); int copyinfrom(const void *src, void *dst, size_t len, int seg); int copyinstrfrom(const void *src, void *dst, size_t len,