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 <sys/ctype.h>
  #include <sys/dirent.h>
  #include <sys/fcntl.h>
+ #include <machine/limits.h>
  #include <sys/lock.h>
  #include <sys/mount.h>
  #include <sys/mutex.h>
*************** 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 <sys/systm.h>
  #include <sys/kernel.h>
  #include <sys/ktr.h>
+ #include <sys/limits.h>
  #include <sys/lock.h>
  #include <sys/mutex.h>
  #include <sys/proc.h>
*************** 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);
