Index: sys/i386/linux/linprocfs/linprocfs_misc.c
===================================================================
RCS file: /home/ncvs/src/sys/i386/linux/linprocfs/Attic/linprocfs_misc.c,v
retrieving revision 1.3.2.8
diff -p -c -r1.3.2.8 linprocfs_misc.c
*** sys/i386/linux/linprocfs/linprocfs_misc.c	25 Jun 2001 19:46:47 -0000	1.3.2.8
--- sys/i386/linux/linprocfs/linprocfs_misc.c	3 Oct 2003 12:39:55 -0000
*************** linprocfs_domeminfo(curp, p, pfs, uio)
*** 85,91 ****
  	struct uio *uio;
  {
  	char *ps;
- 	int xlen;
  	char psbuf[512];		/* XXX - conservative */
  	unsigned long memtotal;		/* total memory in bytes */
  	unsigned long memused;		/* used memory in bytes */
--- 85,90 ----
*************** linprocfs_domeminfo(curp, p, pfs, uio)
*** 156,166 ****
  		B2K(memshared), B2K(buffers), B2K(cached),
  		B2K(swaptotal), B2K(swapfree));
  
! 	xlen = ps - psbuf;
! 	xlen -= uio->uio_offset;
! 	ps = psbuf + uio->uio_offset;
! 	xlen = imin(xlen, uio->uio_resid);
! 	return (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
  }
  
  int
--- 155,161 ----
  		B2K(memshared), B2K(buffers), B2K(cached),
  		B2K(swaptotal), B2K(swapfree));
  
! 	return (uiomove_frombuf(psbuf, ps - psbuf, uio));
  }
  
  int
*************** linprocfs_docpuinfo(curp, p, pfs, uio)
*** 171,177 ****
  	struct uio *uio;
  {
  	char *ps;
- 	int xlen;
  	char psbuf[512];		/* XXX - conservative */
  	int class;
          int i;
--- 166,171 ----
*************** linprocfs_docpuinfo(curp, p, pfs, uio)
*** 248,259 ****
                          (tsc_freq + 4999) / 1000000,
                          ((tsc_freq + 4999) / 10000) % 100);
          }
!         
! 	xlen = ps - psbuf;
! 	xlen -= uio->uio_offset;
! 	ps = psbuf + uio->uio_offset;
! 	xlen = imin(xlen, uio->uio_resid);
! 	return (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
  }
  
  int
--- 242,248 ----
                          (tsc_freq + 4999) / 1000000,
                          ((tsc_freq + 4999) / 10000) % 100);
          }
! 	return (uiomove_frombuf(psbuf, ps - psbuf, uio));
  }
  
  int
*************** linprocfs_dostat(curp, p, pfs, uio)
*** 265,271 ****
  {
          char *ps;
  	char psbuf[512];
- 	int xlen;
  
  	ps = psbuf;
  	ps += sprintf(ps,
--- 254,259 ----
*************** linprocfs_dostat(curp, p, pfs, uio)
*** 287,297 ****
  		      cnt.v_intr,
  		      cnt.v_swtch,
  		      boottime.tv_sec);
! 	xlen = ps - psbuf;
! 	xlen -= uio->uio_offset;
! 	ps = psbuf + uio->uio_offset;
! 	xlen = imin(xlen, uio->uio_resid);
! 	return (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
  }
  
  int
--- 275,281 ----
  		      cnt.v_intr,
  		      cnt.v_swtch,
  		      boottime.tv_sec);
! 	return (uiomove_frombuf(psbuf, ps - psbuf, uio));
  }
  
  int
*************** linprocfs_douptime(curp, p, pfs, uio)
*** 302,308 ****
  	struct uio *uio;
  {
  	char *ps;
- 	int xlen;
  	char psbuf[64];
  	struct timeval tv;
  
--- 286,291 ----
*************** linprocfs_douptime(curp, p, pfs, uio)
*** 311,321 ****
  	ps += sprintf(ps, "%ld.%02ld %ld.%02ld\n",
  		      tv.tv_sec, tv.tv_usec / 10000,
  		      T2S(cp_time[CP_IDLE]), T2J(cp_time[CP_IDLE]) % 100);
! 	xlen = ps - psbuf;
! 	xlen -= uio->uio_offset;
! 	ps = psbuf + uio->uio_offset;
! 	xlen = imin(xlen, uio->uio_resid);
! 	return (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
  }
  
  int
--- 294,300 ----
  	ps += sprintf(ps, "%ld.%02ld %ld.%02ld\n",
  		      tv.tv_sec, tv.tv_usec / 10000,
  		      T2S(cp_time[CP_IDLE]), T2J(cp_time[CP_IDLE]) % 100);
! 	return (uiomove_frombuf(psbuf, ps - psbuf, uio));
  }
  
  int
*************** linprocfs_doversion(curp, p, pfs, uio)
*** 332,341 ****
  	for (xlen = 0; ps[xlen] != '\n'; ++xlen)
  		/* nothing */ ;
  	++xlen;
! 	xlen -= uio->uio_offset;
! 	ps += uio->uio_offset;
! 	xlen = imin(xlen, uio->uio_resid);
! 	return (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
  }
  
  int
--- 311,317 ----
  	for (xlen = 0; ps[xlen] != '\n'; ++xlen)
  		/* nothing */ ;
  	++xlen;
! 	return (uiomove_frombuf(ps, xlen, uio));
  }
  
  int
*************** linprocfs_doprocstat(curp, p, pfs, uio)
*** 346,352 ****
  	struct uio *uio;
  {
  	char *ps, psbuf[1024];
- 	int xlen;
  
  	ps = psbuf;
  	ps += sprintf(ps, "%d", p->p_pid);
--- 322,327 ----
*************** linprocfs_doprocstat(curp, p, pfs, uio)
*** 388,398 ****
  #undef PS_ADD
  	ps += sprintf(ps, "\n");
  	
! 	xlen = ps - psbuf;
! 	xlen -= uio->uio_offset;
! 	ps = psbuf + uio->uio_offset;
! 	xlen = imin(xlen, uio->uio_resid);
! 	return (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
  }
  
  /*
--- 363,369 ----
  #undef PS_ADD
  	ps += sprintf(ps, "\n");
  	
! 	return (uiomove_frombuf(psbuf, ps - psbuf, uio));
  }
  
  /*
*************** linprocfs_doprocstatus(curp, p, pfs, uio
*** 419,425 ****
  {
  	char *ps, psbuf[1024];
  	char *state;
! 	int i, xlen;
  
  	ps = psbuf;
  
--- 390,396 ----
  {
  	char *ps, psbuf[1024];
  	char *state;
! 	int i;
  
  	ps = psbuf;
  
*************** linprocfs_doprocstatus(curp, p, pfs, uio
*** 490,500 ****
  	PS_ADD(ps, "CapEff:\t%016x\n",	  0);
  #undef PS_ADD
  	
! 	xlen = ps - psbuf;
! 	xlen -= uio->uio_offset;
! 	ps = psbuf + uio->uio_offset;
! 	xlen = imin(xlen, uio->uio_resid);
! 	return (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
  }
  
  int
--- 461,467 ----
  	PS_ADD(ps, "CapEff:\t%016x\n",	  0);
  #undef PS_ADD
  	
! 	return (uiomove_frombuf(psbuf, ps - psbuf, uio));
  }
  
  int
*************** linprocfs_doloadavg(curp, p, pfs, uio)
*** 504,511 ****
  	struct pfsnode *pfs;
  	struct uio *uio;
  {
!      char *ps, psbuf[512];
!      int xlen;
  	extern int nextpid;
  
  	ps=psbuf;
--- 471,477 ----
  	struct pfsnode *pfs;
  	struct uio *uio;
  {
! 	char *ps, psbuf[512];
  	extern int nextpid;
  
  	ps=psbuf;
*************** linprocfs_doloadavg(curp, p, pfs, uio)
*** 522,531 ****
  		-1,			/* number of tasks */
  		nextpid		/* The last pid */
  	);
! 
! 	xlen = ps - psbuf;
! 	xlen -= uio->uio_offset;
! 	ps = psbuf + uio->uio_offset;
! 	xlen = imin(xlen, uio->uio_resid);
!      return (xlen <= 0 ? 0 : uiomove(ps, xlen, uio));
  }
--- 488,492 ----
  		-1,			/* number of tasks */
  		nextpid		/* The last pid */
  	);
! 	return (uiomove_frombuf(psbuf, ps - psbuf, uio));
  }
Index: sys/kern/kern_subr.c
===================================================================
RCS file: /home/ncvs/src/sys/kern/kern_subr.c,v
retrieving revision 1.31.2.2
diff -p -c -r1.31.2.2 kern_subr.c
*** sys/kern/kern_subr.c	21 Apr 2002 08:09:37 -0000	1.31.2.2
--- sys/kern/kern_subr.c	3 Oct 2003 12:39:55 -0000
***************
*** 47,52 ****
--- 47,53 ----
  #include <sys/lock.h>
  #include <sys/resourcevar.h>
  #include <sys/vnode.h>
+ #include <machine/limits.h>
  
  #include <vm/vm.h>
  #include <vm/vm_page.h>
*************** uiomove(cp, n, uio)
*** 117,122 ****
--- 118,145 ----
  	if (curproc)
  		curproc->p_flag = (curproc->p_flag & ~P_DEADLKTREAT) | save;
  	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));
  }
  
  int
Index: sys/miscfs/procfs/procfs_dbregs.c
===================================================================
RCS file: /home/ncvs/src/sys/miscfs/procfs/Attic/procfs_dbregs.c,v
retrieving revision 1.4.2.3
diff -p -c -r1.4.2.3 procfs_dbregs.c
*** sys/miscfs/procfs/procfs_dbregs.c	22 Jan 2002 17:22:59 -0000	1.4.2.3
--- sys/miscfs/procfs/procfs_dbregs.c	3 Oct 2003 12:39:55 -0000
*************** procfs_dodbregs(curp, p, pfs, uio)
*** 59,88 ****
  {
  	int error;
  	struct dbreg r;
- 	char *kv;
- 	int kl;
  
  	/* Can't trace a process that's currently exec'ing. */ 
  	if ((p->p_flag & P_INEXEC) != 0)
  		return EAGAIN;
  	if (!CHECKIO(curp, p) || p_trespass(curp, 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
! 		error = procfs_read_dbregs(p, &r);
  	if (error == 0)
! 		error = uiomove(kv, kl, uio);
  	if (error == 0 && uio->uio_rw == UIO_WRITE) {
  		if (p->p_stat != SSTOP)
  			error = EBUSY;
--- 59,75 ----
  {
  	int error;
  	struct dbreg r;
  
  	/* Can't trace a process that's currently exec'ing. */ 
  	if ((p->p_flag & P_INEXEC) != 0)
  		return EAGAIN;
  	if (!CHECKIO(curp, p) || p_trespass(curp, p))
  		return (EPERM);
  
  	PHOLD(p);
! 	error = procfs_read_dbregs(p, &r);
  	if (error == 0)
! 		error = uiomove_frombuf(&r, sizeof(r), uio);
  	if (error == 0 && uio->uio_rw == UIO_WRITE) {
  		if (p->p_stat != SSTOP)
  			error = EBUSY;
Index: sys/miscfs/procfs/procfs_fpregs.c
===================================================================
RCS file: /home/ncvs/src/sys/miscfs/procfs/Attic/procfs_fpregs.c,v
retrieving revision 1.11.2.3
diff -p -c -r1.11.2.3 procfs_fpregs.c
*** sys/miscfs/procfs/procfs_fpregs.c	22 Jan 2002 17:22:59 -0000	1.11.2.3
--- sys/miscfs/procfs/procfs_fpregs.c	3 Oct 2003 12:39:55 -0000
*************** procfs_dofpregs(curp, p, pfs, uio)
*** 56,85 ****
  {
  	int error;
  	struct fpreg r;
- 	char *kv;
- 	int kl;
  
  	/* Can't trace a process that's currently exec'ing. */ 
  	if ((p->p_flag & P_INEXEC) != 0)
  		return EAGAIN;
  	if (!CHECKIO(curp, p) || p_trespass(curp, 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
! 		error = procfs_read_fpregs(p, &r);
  	if (error == 0)
! 		error = uiomove(kv, kl, uio);
  	if (error == 0 && uio->uio_rw == UIO_WRITE) {
  		if (p->p_stat != SSTOP)
  			error = EBUSY;
--- 56,73 ----
  {
  	int error;
  	struct fpreg r;
  
  	/* Can't trace a process that's currently exec'ing. */ 
  	if ((p->p_flag & P_INEXEC) != 0)
  		return EAGAIN;
  	if (!CHECKIO(curp, p) || p_trespass(curp, p))
  		return EPERM;
  
  	PHOLD(p);
  
! 	error = procfs_read_fpregs(p, &r);
  	if (error == 0)
! 		error = uiomove_frombuf(&r, sizeof(r), uio);
  	if (error == 0 && uio->uio_rw == UIO_WRITE) {
  		if (p->p_stat != SSTOP)
  			error = EBUSY;
Index: sys/miscfs/procfs/procfs_regs.c
===================================================================
RCS file: /home/ncvs/src/sys/miscfs/procfs/Attic/procfs_regs.c,v
retrieving revision 1.10.2.3
diff -p -c -r1.10.2.3 procfs_regs.c
*** sys/miscfs/procfs/procfs_regs.c	22 Jan 2002 17:22:59 -0000	1.10.2.3
--- sys/miscfs/procfs/procfs_regs.c	3 Oct 2003 12:39:55 -0000
*************** procfs_doregs(curp, p, pfs, uio)
*** 65,86 ****
  		return EAGAIN;
  	if (!CHECKIO(curp, p) || p_trespass(curp, 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
! 		error = procfs_read_regs(p, &r);
  	if (error == 0)
! 		error = uiomove(kv, kl, uio);
  	if (error == 0 && uio->uio_rw == UIO_WRITE) {
  		if (p->p_stat != SSTOP)
  			error = EBUSY;
--- 65,76 ----
  		return EAGAIN;
  	if (!CHECKIO(curp, p) || p_trespass(curp, p))
  		return EPERM;
  
  	PHOLD(p);
  
! 	error = procfs_read_regs(p, &r);
  	if (error == 0)
! 		error = uiomove_frombuf(&r, sizeof(r), uio);
  	if (error == 0 && uio->uio_rw == UIO_WRITE) {
  		if (p->p_stat != SSTOP)
  			error = EBUSY;
Index: sys/miscfs/procfs/procfs_rlimit.c
===================================================================
RCS file: /home/ncvs/src/sys/miscfs/procfs/Attic/procfs_rlimit.c,v
retrieving revision 1.5
diff -p -c -r1.5 procfs_rlimit.c
*** sys/miscfs/procfs/procfs_rlimit.c	8 Dec 1999 08:59:37 -0000	1.5
--- sys/miscfs/procfs/procfs_rlimit.c	3 Oct 2003 12:39:55 -0000
*************** procfs_dorlimit(curp, p, pfs, uio)
*** 64,70 ****
  {
  	char *ps;
  	int i;
- 	int xlen;
  	int error;
  	char psbuf[512];		/* XXX - conservative */
  
--- 64,69 ----
*************** procfs_dorlimit(curp, p, pfs, uio)
*** 109,128 ****
  		}
  	}
  
! 	/*
! 	 * This logic is rather tasty - but its from procfs_status.c, so
! 	 * I guess I'll use it here.
! 	 */
! 
! 	xlen = ps - psbuf;
! 	xlen -= uio->uio_offset;
! 	ps = psbuf + uio->uio_offset;
! 	xlen = imin(xlen, uio->uio_resid);
! 	if (xlen <= 0)
! 		error = 0;
! 	else
! 		error = uiomove(ps, xlen, uio);
! 
  	return (error);
  }
  
--- 108,114 ----
  		}
  	}
  
! 	error = uiomove_frombuf(psbuf, ps - psbuf, uio);
  	return (error);
  }
  
Index: sys/miscfs/procfs/procfs_status.c
===================================================================
RCS file: /home/ncvs/src/sys/miscfs/procfs/Attic/procfs_status.c,v
retrieving revision 1.20.2.4
diff -p -c -r1.20.2.4 procfs_status.c
*** sys/miscfs/procfs/procfs_status.c	22 Jan 2002 17:22:59 -0000	1.20.2.4
--- sys/miscfs/procfs/procfs_status.c	3 Oct 2003 12:39:55 -0000
*************** procfs_dostatus(curp, p, pfs, uio)
*** 166,180 ****
  	ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, "\n");
  	DOCHECK();
  
! 	xlen = ps - psbuf;
! 	xlen -= uio->uio_offset;
! 	ps = psbuf + uio->uio_offset;
! 	xlen = imin(xlen, uio->uio_resid);
! 	if (xlen <= 0)
! 		error = 0;
! 	else
! 		error = uiomove(ps, xlen, uio);
! 
  	return (error);
  
  bailout:
--- 166,172 ----
  	ps += snprintf(ps, psbuf + sizeof(psbuf) - ps, "\n");
  	DOCHECK();
  
! 	error = uiomove_frombuf(psbuf, ps - psbuf, uio);
  	return (error);
  
  bailout:
*************** procfs_docmdline(curp, p, pfs, uio)
*** 246,258 ****
  		buflen = ps - buf;
  	}
  
! 	buflen -= uio->uio_offset;
! 	ps = bp + uio->uio_offset;
! 	xlen = min(buflen, uio->uio_resid);
! 	if (xlen <= 0)
! 		error = 0;
! 	else
! 		error = uiomove(ps, xlen, uio);
  	if (buf)
  		FREE(buf, M_TEMP);
  	return (error);
--- 238,244 ----
  		buflen = ps - buf;
  	}
  
! 	error = uiomove_frombuf(bp, buflen, uio);
  	if (buf)
  		FREE(buf, M_TEMP);
  	return (error);
Index: sys/sys/uio.h
===================================================================
RCS file: /home/ncvs/src/sys/sys/uio.h,v
retrieving revision 1.11.2.1
diff -p -c -r1.11.2.1 uio.h
*** sys/sys/uio.h	28 Sep 2001 16:58:35 -0000	1.11.2.1
--- sys/sys/uio.h	3 Oct 2003 12:39:55 -0000
*************** struct vm_object;
*** 78,83 ****
--- 78,84 ----
  
  void	uio_yield __P((void));
  int	uiomove __P((caddr_t, int, struct uio *));
+ int	uiomove_frombuf __P((void *buf, int buflen, struct uio *uio));
  int	uiomoveco __P((caddr_t, int, struct uio *, struct vm_object *));
  int	uioread __P((int, struct uio *, struct vm_object *, int *));
  
