diff options
author | Jacques Vidrine <nectar@FreeBSD.org> | 2003-10-03 13:07:38 +0000 |
---|---|---|
committer | Jacques Vidrine <nectar@FreeBSD.org> | 2003-10-03 13:07:38 +0000 |
commit | 5b0811458aa73c87058a6805acb73faebe8d6091 (patch) | |
tree | 8a41abebdfb9198a45d347d76307479f6339e8c2 | |
parent | 9fd7edd2204124afa9bebf46efd1a2710d067244 (diff) | |
download | src-test2-5b0811458aa73c87058a6805acb73faebe8d6091.tar.gz src-test2-5b0811458aa73c87058a6805acb73faebe8d6091.zip |
Notes
-rw-r--r-- | UPDATING | 3 | ||||
-rw-r--r-- | sys/conf/newvers.sh | 2 | ||||
-rw-r--r-- | sys/i386/linux/linprocfs/linprocfs_misc.c | 59 | ||||
-rw-r--r-- | sys/kern/kern_subr.c | 23 | ||||
-rw-r--r-- | sys/miscfs/procfs/procfs_dbregs.c | 17 | ||||
-rw-r--r-- | sys/miscfs/procfs/procfs_fpregs.c | 16 | ||||
-rw-r--r-- | sys/miscfs/procfs/procfs_regs.c | 14 | ||||
-rw-r--r-- | sys/miscfs/procfs/procfs_rlimit.c | 16 | ||||
-rw-r--r-- | sys/miscfs/procfs/procfs_status.c | 18 | ||||
-rw-r--r-- | sys/sys/uio.h | 1 |
10 files changed, 47 insertions, 122 deletions
@@ -17,6 +17,9 @@ minimal number of processes, if possible, for that patch. For those updates that don't have an advisory, or to be safe, you can do a full build and install as described in the COMMON ITEMS section. +20031003: p22 FreeBSD-SA-03:17.procfs + Correct integer underflows/overflows in procfs(5) and linprocfs(5). + 20031002: p21 FreeBSD-SA-03:16.filedesc Correct a reference counting bug in readv(2). diff --git a/sys/conf/newvers.sh b/sys/conf/newvers.sh index ef12eaf063af..7d417991cf6b 100644 --- a/sys/conf/newvers.sh +++ b/sys/conf/newvers.sh @@ -36,7 +36,7 @@ TYPE="FreeBSD" REVISION="4.7" -BRANCH="RELEASE-p21" +BRANCH="RELEASE-p22" RELEASE="${REVISION}-${BRANCH}" VERSION="${TYPE} ${RELEASE}" diff --git a/sys/i386/linux/linprocfs/linprocfs_misc.c b/sys/i386/linux/linprocfs/linprocfs_misc.c index c8070c614c38..33e008bd161d 100644 --- a/sys/i386/linux/linprocfs/linprocfs_misc.c +++ b/sys/i386/linux/linprocfs/linprocfs_misc.c @@ -85,7 +85,6 @@ linprocfs_domeminfo(curp, p, pfs, uio) 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 */ @@ -156,11 +155,7 @@ linprocfs_domeminfo(curp, p, pfs, uio) 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)); + return (uiomove_frombuf(psbuf, ps - psbuf, uio)); } int @@ -171,7 +166,6 @@ linprocfs_docpuinfo(curp, p, pfs, uio) struct uio *uio; { char *ps; - int xlen; char psbuf[512]; /* XXX - conservative */ int class; int i; @@ -248,12 +242,7 @@ linprocfs_docpuinfo(curp, p, pfs, uio) (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)); + return (uiomove_frombuf(psbuf, ps - psbuf, uio)); } int @@ -265,7 +254,6 @@ linprocfs_dostat(curp, p, pfs, uio) { char *ps; char psbuf[512]; - int xlen; ps = psbuf; ps += sprintf(ps, @@ -287,11 +275,7 @@ linprocfs_dostat(curp, p, pfs, uio) 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)); + return (uiomove_frombuf(psbuf, ps - psbuf, uio)); } int @@ -302,7 +286,6 @@ linprocfs_douptime(curp, p, pfs, uio) struct uio *uio; { char *ps; - int xlen; char psbuf[64]; struct timeval tv; @@ -311,11 +294,7 @@ linprocfs_douptime(curp, p, pfs, uio) 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)); + return (uiomove_frombuf(psbuf, ps - psbuf, uio)); } int @@ -332,10 +311,7 @@ linprocfs_doversion(curp, p, pfs, uio) 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)); + return (uiomove_frombuf(ps, xlen, uio)); } int @@ -346,7 +322,6 @@ linprocfs_doprocstat(curp, p, pfs, uio) struct uio *uio; { char *ps, psbuf[1024]; - int xlen; ps = psbuf; ps += sprintf(ps, "%d", p->p_pid); @@ -388,11 +363,7 @@ linprocfs_doprocstat(curp, p, pfs, uio) #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)); + return (uiomove_frombuf(psbuf, ps - psbuf, uio)); } /* @@ -419,7 +390,7 @@ linprocfs_doprocstatus(curp, p, pfs, uio) { char *ps, psbuf[1024]; char *state; - int i, xlen; + int i; ps = psbuf; @@ -490,11 +461,7 @@ linprocfs_doprocstatus(curp, p, pfs, uio) 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)); + return (uiomove_frombuf(psbuf, ps - psbuf, uio)); } int @@ -504,8 +471,7 @@ linprocfs_doloadavg(curp, p, pfs, uio) struct pfsnode *pfs; struct uio *uio; { - char *ps, psbuf[512]; - int xlen; + char *ps, psbuf[512]; extern int nextpid; ps=psbuf; @@ -522,10 +488,5 @@ linprocfs_doloadavg(curp, p, pfs, uio) -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)); + return (uiomove_frombuf(psbuf, ps - psbuf, uio)); } diff --git a/sys/kern/kern_subr.c b/sys/kern/kern_subr.c index ea08de5e9eb0..8de24b003063 100644 --- a/sys/kern/kern_subr.c +++ b/sys/kern/kern_subr.c @@ -47,6 +47,7 @@ #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> @@ -119,6 +120,28 @@ uiomove(cp, n, uio) 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 uiomoveco(cp, n, uio, obj) caddr_t cp; diff --git a/sys/miscfs/procfs/procfs_dbregs.c b/sys/miscfs/procfs/procfs_dbregs.c index 9fe4968d37c6..971c09eb0af7 100644 --- a/sys/miscfs/procfs/procfs_dbregs.c +++ b/sys/miscfs/procfs/procfs_dbregs.c @@ -59,30 +59,17 @@ procfs_dodbregs(curp, p, pfs, uio) { 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); + error = procfs_read_dbregs(p, &r); if (error == 0) - error = uiomove(kv, kl, uio); + error = uiomove_frombuf(&r, sizeof(r), uio); if (error == 0 && uio->uio_rw == UIO_WRITE) { if (p->p_stat != SSTOP) error = EBUSY; diff --git a/sys/miscfs/procfs/procfs_fpregs.c b/sys/miscfs/procfs/procfs_fpregs.c index 7074148cfbfc..c8afd55d96d9 100644 --- a/sys/miscfs/procfs/procfs_fpregs.c +++ b/sys/miscfs/procfs/procfs_fpregs.c @@ -56,30 +56,18 @@ procfs_dofpregs(curp, p, pfs, uio) { 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); + error = procfs_read_fpregs(p, &r); if (error == 0) - error = uiomove(kv, kl, uio); + error = uiomove_frombuf(&r, sizeof(r), uio); if (error == 0 && uio->uio_rw == UIO_WRITE) { if (p->p_stat != SSTOP) error = EBUSY; diff --git a/sys/miscfs/procfs/procfs_regs.c b/sys/miscfs/procfs/procfs_regs.c index ccde00af6da5..8604d0a4a9a7 100644 --- a/sys/miscfs/procfs/procfs_regs.c +++ b/sys/miscfs/procfs/procfs_regs.c @@ -65,22 +65,12 @@ procfs_doregs(curp, p, pfs, uio) 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); + error = procfs_read_regs(p, &r); if (error == 0) - error = uiomove(kv, kl, uio); + error = uiomove(&r, sizeof(r), uio); if (error == 0 && uio->uio_rw == UIO_WRITE) { if (p->p_stat != SSTOP) error = EBUSY; diff --git a/sys/miscfs/procfs/procfs_rlimit.c b/sys/miscfs/procfs/procfs_rlimit.c index 361f6f6e9d7d..552e901c9798 100644 --- a/sys/miscfs/procfs/procfs_rlimit.c +++ b/sys/miscfs/procfs/procfs_rlimit.c @@ -64,7 +64,6 @@ procfs_dorlimit(curp, p, pfs, uio) { char *ps; int i; - int xlen; int error; char psbuf[512]; /* XXX - conservative */ @@ -109,20 +108,7 @@ procfs_dorlimit(curp, p, pfs, uio) } } - /* - * 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); - + error = uiomove_frombuf(psbuf, ps - psbuf, uio); return (error); } diff --git a/sys/miscfs/procfs/procfs_status.c b/sys/miscfs/procfs/procfs_status.c index b8cc6dbe9f91..370f23a6efb2 100644 --- a/sys/miscfs/procfs/procfs_status.c +++ b/sys/miscfs/procfs/procfs_status.c @@ -166,15 +166,7 @@ procfs_dostatus(curp, p, pfs, uio) 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); - + error = uiomove_frombuf(psbuf, ps - psbuf, uio); return (error); bailout: @@ -246,13 +238,7 @@ procfs_docmdline(curp, p, pfs, uio) 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); + error = uiomove_frombuf(bp, buflen, uio); if (buf) FREE(buf, M_TEMP); return (error); diff --git a/sys/sys/uio.h b/sys/sys/uio.h index 1a9176305f6d..027a8a048d7a 100644 --- a/sys/sys/uio.h +++ b/sys/sys/uio.h @@ -78,6 +78,7 @@ struct vm_object; 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 *)); |