aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJacques Vidrine <nectar@FreeBSD.org>2003-10-03 13:07:38 +0000
committerJacques Vidrine <nectar@FreeBSD.org>2003-10-03 13:07:38 +0000
commit13bba0f1a042803c0d4e5135d0d34ae838a3f9c3 (patch)
tree903d1ccf3f7820a73e1814c045e67c9f2a44c552
parent2dedd3f3699b615fdeabd02fe6544ad15764db9d (diff)
downloadsrc-13bba0f1a042803c0d4e5135d0d34ae838a3f9c3.tar.gz
src-13bba0f1a042803c0d4e5135d0d34ae838a3f9c3.zip
Merge from RELENG_4: kern_subr.c 1.31.2.3, procfs_dbregs.c 1.4.2.4,
procfs_fpregs.c 1.11.2.4, procfs_regs.c 1.10.2.4, procfs_rlimit.c 1.5.2.1, procfs_status.c 1.20.2.5, uio.h 1.11.2.2, linprocfs_misc.c 1.3.2.9. Correct several integer underflows/overflows in procfs and linprocfs.
Notes
Notes: svn path=/releng/4.4/; revision=120689
-rw-r--r--UPDATING3
-rw-r--r--sys/conf/newvers.sh2
-rw-r--r--sys/i386/linux/linprocfs/linprocfs_misc.c59
-rw-r--r--sys/kern/kern_subr.c23
-rw-r--r--sys/miscfs/procfs/procfs_dbregs.c17
-rw-r--r--sys/miscfs/procfs/procfs_fpregs.c16
-rw-r--r--sys/miscfs/procfs/procfs_regs.c14
-rw-r--r--sys/miscfs/procfs/procfs_rlimit.c16
-rw-r--r--sys/miscfs/procfs/procfs_status.c18
-rw-r--r--sys/sys/uio.h1
10 files changed, 47 insertions, 122 deletions
diff --git a/UPDATING b/UPDATING
index 44491df70c64..670aefb3a69c 100644
--- a/UPDATING
+++ b/UPDATING
@@ -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: p46 FreeBSD-SA-03:17.procfs
+ Correct integer underflows/overflows in procfs(5) and linprocfs(5).
+
20031002: p45 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 d03a894115ab..0b4545a32d54 100644
--- a/sys/conf/newvers.sh
+++ b/sys/conf/newvers.sh
@@ -36,7 +36,7 @@
TYPE="FreeBSD"
REVISION="4.4"
-BRANCH="RELEASE-p45"
+BRANCH="RELEASE-p46"
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 c0f7f6479e48..e751288c06e6 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>
@@ -121,6 +122,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 a2de90ac235b..2d252e5269e2 100644
--- a/sys/sys/uio.h
+++ b/sys/sys/uio.h
@@ -77,6 +77,7 @@ struct uio {
struct vm_object;
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 *));