kernel - more procfs work
authorMatthew Dillon <dillon@apollo.backplane.com>
Thu, 17 Nov 2011 17:17:51 +0000 (09:17 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Thu, 17 Nov 2011 17:17:51 +0000 (09:17 -0800)
* uiomove_frombuf() takes care of indexing uio_offset and checking its
  range for us so we don't have to do it ourselves, clean up use cases
  in procfs.

* Generate somewhat more consistent text output for /proc/<pid>/map by
  formatting the map entry range with static widths.

* ps_nargvstr is a signed number, do a better range check on it.

sys/kern/kern_subr.c
sys/vfs/procfs/procfs_dbregs.c
sys/vfs/procfs/procfs_fpregs.c
sys/vfs/procfs/procfs_map.c
sys/vfs/procfs/procfs_regs.c
sys/vfs/procfs/procfs_rlimit.c
sys/vfs/procfs/procfs_status.c

index 044fb59..11be675 100644 (file)
@@ -187,7 +187,8 @@ uiomovez(size_t n, struct uio *uio)
 
 /*
  * Wrapper for uiomove() that validates the arguments against a known-good
- * kernel buffer.
+ * kernel buffer.  This function automatically indexes the buffer by
+ * uio_offset and handles all range checking.
  */
 int
 uiomove_frombuf(void *buf, size_t buflen, struct uio *uio)
index 2fb2162..ebd6c4f 100644 (file)
@@ -59,22 +59,12 @@ procfs_dodbregs(struct proc *curp, struct lwp *lp, struct pfsnode *pfs,
        struct proc *p = lp->lwp_proc;
        int error;
        struct dbreg r;
-       char *kv;
-       int kl;
 
        /* Can't trace a process that's currently exec'ing. */ 
        if ((p->p_flags & P_INEXEC) != 0)
                return EAGAIN;
        if (!CHECKIO(curp, p) || p_trespass(curp->p_ucred, p->p_ucred))
                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;
-
        LWPHOLD(lp);
        error = procfs_read_dbregs(lp, &r);
        if (error == 0)
@@ -86,8 +76,8 @@ procfs_dodbregs(struct proc *curp, struct lwp *lp, struct pfsnode *pfs,
                        error = procfs_write_dbregs(lp, &r);
        }
        LWPRELE(lp);
-
        uio->uio_offset = 0;
+
        return (error);
 }
 
index a9acf20..313f72c 100644 (file)
@@ -56,21 +56,12 @@ procfs_dofpregs(struct proc *curp, struct lwp *lp, struct pfsnode *pfs,
        struct proc *p = lp->lwp_proc;
        int error;
        struct fpreg r;
-       char *kv;
-       int kl;
 
        /* Can't trace a process that's currently exec'ing. */ 
        if ((p->p_flags & P_INEXEC) != 0)
                return EAGAIN;
        if (!CHECKIO(curp, p) || p_trespass(curp->p_ucred, p->p_ucred))
                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;
 
        LWPHOLD(lp);
        error = procfs_read_fpregs(lp, &r);
@@ -83,8 +74,8 @@ procfs_dofpregs(struct proc *curp, struct lwp *lp, struct pfsnode *pfs,
                        error = procfs_write_fpregs(lp, &r);
        }
        LWPRELE(lp);
-
        uio->uio_offset = 0;
+
        return (error);
 }
 
index 1fb423b..add7bb8 100644 (file)
@@ -49,6 +49,7 @@
 #include <vm/vm_page.h>
 #include <vm/vm_object.h>
 
+#include <machine/limits.h>
 
 #define MEBUFFERSIZE 256
 
@@ -188,7 +189,12 @@ procfs_domap(struct proc *curp, struct lwp *lp, struct pfsnode *pfs,
                 *  start, end, res, priv res, cow, access, type, (fullpath).
                 */
                ksnprintf(mebuffer, sizeof(mebuffer),
-                   "0x%lx 0x%lx %d %d %p %s%s%s %d %d 0x%x %s %s %s %s\n",
+#if LONG_BIT == 64
+                         "0x%016lx 0x%016lx %d %d %p %s%s%s %d %d "
+#else
+                         "0x%08lx 0x%08lx %d %d %p %s%s%s %d %d "
+#endif
+                         "0x%04x %s %s %s %s\n",
                        (u_long)entry->start, (u_long)entry->end,
                        resident, privateresident, obj,
                        (entry->protection & VM_PROT_READ)?"r":"-",
index 52d743d..a50ba53 100644 (file)
@@ -57,24 +57,14 @@ procfs_doregs(struct proc *curp, struct lwp *lp, struct pfsnode *pfs,
        struct proc *p = lp->lwp_proc;
        int error;
        struct reg r;
-       char *kv;
-       int kl;
 
        /* Can't trace a process that's currently exec'ing. */ 
        if ((p->p_flags & P_INEXEC) != 0)
                return EAGAIN;
        if (!CHECKIO(curp, p) || p_trespass(curp->p_ucred, p->p_ucred))
                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;
 
        LWPHOLD(lp);
-
        error = procfs_read_regs(lp, &r);
        if (error == 0)
                error = uiomove_frombuf(&r, sizeof(r), uio);
@@ -85,8 +75,8 @@ procfs_doregs(struct proc *curp, struct lwp *lp, struct pfsnode *pfs,
                        error = procfs_write_regs(lp, &r);
        }
        LWPRELE(lp);
-
        uio->uio_offset = 0;
+
        return (error);
 }
 
index c2b0157..d2bcb5c 100644 (file)
@@ -107,19 +107,9 @@ procfs_dorlimit(struct proc *curp, struct lwp *lp, struct pfsnode *pfs,
                }
        }
 
-       /*
-        * This logic is rather tasty - but its from procfs_status.c, so
-        * I guess I'll use it here.
-        */
-
        xlen = ps - psbuf;
-       xlen -= (size_t)uio->uio_offset;
-       ps = psbuf + (size_t)uio->uio_offset;
-       xlen = szmin(xlen, uio->uio_resid);
-       if (xlen == 0)
-               error = 0;
-       else
-               error = uiomove_frombuf(psbuf, xlen, uio);
+       error = uiomove_frombuf(psbuf, xlen, uio);
+
        return (error);
 }
 
index 6f782b2..4a42226 100644 (file)
 #include <vm/vm_param.h>
 #include <sys/exec.h>
 
-#define DOCHECK() do { if (ps >= psbuf+sizeof(psbuf)) goto bailout; } while (0)
+#define DOCHECK() do { \
+       if (ps >= psbuf+sizeof(psbuf)) {        \
+               error = ENOMEM;                 \
+               goto bailout;                   \
+       }                                       \
+    } while (0)
+
 int
 procfs_dostatus(struct proc *curp, struct lwp *lp, struct pfsnode *pfs,
                struct uio *uio)
@@ -168,18 +174,10 @@ procfs_dostatus(struct proc *curp, struct lwp *lp, struct pfsnode *pfs,
        DOCHECK();
 
        xlen = ps - psbuf;
-       xlen -= (size_t)uio->uio_offset;
-       ps = psbuf + uio->uio_offset;
-       xlen = szmin(xlen, uio->uio_resid);
-       if (xlen == 0)
-               error = 0;
-       else
-               error = uiomove_frombuf(ps, xlen, uio);
-
-       return (error);
+       error = uiomove_frombuf(psbuf, xlen, uio);
 
 bailout:
-       return (ENOMEM);
+       return (error);
 }
 
 int
@@ -194,7 +192,7 @@ procfs_docmdline(struct proc *curp, struct lwp *lp, struct pfsnode *pfs,
        char **ps_argvstr;
        int i;
        size_t bytes_left, done;
-       size_t buflen, xlen;
+       size_t buflen;
 
        if (uio->uio_rw != UIO_READ)
                return (EOPNOTSUPP);
@@ -227,18 +225,24 @@ procfs_docmdline(struct proc *curp, struct lwp *lp, struct pfsnode *pfs,
                bp = buf;
                ps = buf;
                error = copyin((void*)PS_STRINGS, &pstr, sizeof(pstr));
+
                if (error) {
                        FREE(buf, M_TEMP);
                        return (error);
                }
+               if (pstr.ps_nargvstr < 0) {
+                       FREE(buf, M_TEMP);
+                       return (EINVAL);
+               }
                if (pstr.ps_nargvstr > ARG_MAX) {
                        FREE(buf, M_TEMP);
                        return (E2BIG);
                }
-               MALLOC(ps_argvstr, char **, pstr.ps_nargvstr * sizeof(char *),
-                   M_TEMP, M_WAITOK);
+               MALLOC(ps_argvstr, char **,
+                      pstr.ps_nargvstr * sizeof(char *),
+                      M_TEMP, M_WAITOK);
                error = copyin((void *)pstr.ps_argvstr, ps_argvstr,
-                   pstr.ps_nargvstr * sizeof(char *));
+                              pstr.ps_nargvstr * sizeof(char *));
                if (error) {
                        FREE(ps_argvstr, M_TEMP);
                        FREE(buf, M_TEMP);
@@ -260,13 +264,7 @@ procfs_docmdline(struct proc *curp, struct lwp *lp, struct pfsnode *pfs,
                FREE(ps_argvstr, M_TEMP);
        }
 
-       buflen -= (size_t)uio->uio_offset;
-       ps = bp + (size_t)uio->uio_offset;
-       xlen = szmin(buflen, uio->uio_resid);
-       if (xlen == 0)
-               error = 0;
-       else
-               error = uiomove_frombuf(bp, buflen, uio);
+       error = uiomove_frombuf(bp, buflen, uio);
        if (buf)
                FREE(buf, M_TEMP);
        return (error);