Index: sys/fs/procfs/procfs_dbregs.c =================================================================== RCS file: /home/ncvs/src/sys/fs/procfs/procfs_dbregs.c,v retrieving revision 1.21 diff -p -c -r1.21 procfs_dbregs.c *** sys/fs/procfs/procfs_dbregs.c 29 Jun 2002 17:26:15 -0000 1.21 --- sys/fs/procfs/procfs_dbregs.c 3 Oct 2003 12:57:04 -0000 *************** procfs_doprocdbregs(PFS_FILL_ARGS) *** 65,94 **** { 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) ! error = uiomove(kv, kl, uio); if (error == 0 && uio->uio_rw == UIO_WRITE) { if (!P_SHOULDSTOP(p)) /* XXXKSE should be P_TRACED? */ error = EBUSY; --- 65,82 ---- { 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) ! error = uiomove_frombuf(&r, sizeof(r), uio); if (error == 0 && uio->uio_rw == UIO_WRITE) { if (!P_SHOULDSTOP(p)) /* XXXKSE should be P_TRACED? */ error = EBUSY; Index: sys/fs/procfs/procfs_fpregs.c =================================================================== RCS file: /home/ncvs/src/sys/fs/procfs/procfs_fpregs.c,v retrieving revision 1.27 diff -p -c -r1.27 procfs_fpregs.c *** sys/fs/procfs/procfs_fpregs.c 29 Jun 2002 17:26:15 -0000 1.27 --- sys/fs/procfs/procfs_fpregs.c 3 Oct 2003 12:56:42 -0000 *************** procfs_doprocfpregs(PFS_FILL_ARGS) *** 59,88 **** { 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) ! error = uiomove(kv, kl, uio); if (error == 0 && uio->uio_rw == UIO_WRITE) { if (!P_SHOULDSTOP(p)) error = EBUSY; --- 59,76 ---- { 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) ! error = uiomove_frombuf(&r, sizeof(r), uio); if (error == 0 && uio->uio_rw == UIO_WRITE) { if (!P_SHOULDSTOP(p)) error = EBUSY; Index: sys/fs/procfs/procfs_regs.c =================================================================== RCS file: /home/ncvs/src/sys/fs/procfs/procfs_regs.c,v retrieving revision 1.26 diff -p -c -r1.26 procfs_regs.c *** sys/fs/procfs/procfs_regs.c 29 Jun 2002 17:26:15 -0000 1.26 --- sys/fs/procfs/procfs_regs.c 3 Oct 2003 12:57:56 -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); PROC_UNLOCK(p); ! if (kl < 0) ! error = EINVAL; ! else ! /* XXXKSE: */ ! error = proc_read_regs(FIRST_THREAD_IN_PROC(p), &r); if (error == 0) ! error = uiomove(kv, kl, uio); PROC_LOCK(p); if (error == 0 && uio->uio_rw == UIO_WRITE) { if (!P_SHOULDSTOP(p)) --- 59,77 ---- { int error; struct reg r; PROC_LOCK(p); if (p_candebug(td, p)) { PROC_UNLOCK(p); return (EPERM); } _PHOLD(p); PROC_UNLOCK(p); ! /* XXXKSE: */ ! error = proc_read_regs(FIRST_THREAD_IN_PROC(p), &r); if (error == 0) ! error = uiomove_frombuf(&r, sizeof(r), uio); PROC_LOCK(p); if (error == 0 && uio->uio_rw == UIO_WRITE) { if (!P_SHOULDSTOP(p)) Index: sys/fs/pseudofs/pseudofs_vnops.c =================================================================== RCS file: /home/ncvs/src/sys/fs/pseudofs/pseudofs_vnops.c,v retrieving revision 1.32 diff -p -c -r1.32 pseudofs_vnops.c *** sys/fs/pseudofs/pseudofs_vnops.c 26 Oct 2002 14:38:20 -0000 1.32 --- sys/fs/pseudofs/pseudofs_vnops.c 3 Oct 2003 12:54:41 -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.63 diff -p -c -r1.63 kern_subr.c *** sys/kern/kern_subr.c 28 Nov 2002 08:44:26 -0000 1.63 --- sys/kern/kern_subr.c 3 Oct 2003 12:54:41 -0000 *************** *** 45,50 **** --- 45,51 ---- #include #include #include + #include #include #include #include *************** out: *** 208,213 **** --- 209,236 ---- 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)); } #if defined(ENABLE_VFS_IOOPT) || defined(ZERO_COPY_SOCKETS) Index: sys/sys/uio.h =================================================================== RCS file: /home/ncvs/src/sys/sys/uio.h,v retrieving revision 1.23 diff -p -c -r1.23 uio.h *** sys/sys/uio.h 11 Oct 2002 18:21:50 -0000 1.23 --- sys/sys/uio.h 3 Oct 2003 12:58:36 -0000 *************** struct vm_object; *** 99,104 **** --- 99,105 ---- void uio_yield(void); int uiomove(caddr_t, int, struct uio *); + int uiomove_frombuf(void *buf, int buflen, struct uio *uio); int uiomoveco(caddr_t, int, struct uio *, struct vm_object *, int); int uioread(int, struct uio *, struct vm_object *, int *); int copyinfrom(const void *src, void *dst, size_t len, int seg);