Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/miscfs/procfs Apply patch from Robert Elz in PR kern/101...



details:   https://anonhg.NetBSD.org/src/rev/42e13c3a0afc
branches:  trunk
changeset: 486235:42e13c3a0afc
user:      simonb <simonb%NetBSD.org@localhost>
date:      Tue May 16 13:45:25 2000 +0000

description:
Apply patch from Robert Elz in PR kern/10113.  This fixes two problems
with procfs's cmdline - from the PR:

        The cmdline implementation in procfs is bogus.  It's possible that
        part of the fix is a workaround of a UVM problem - that is, when
        (internally) accessing the top of the process VM (the end of the
        args) a request for I/0 of a PAGE_SIZE'd block starting at less
        than a PAGE_SIZE from the end of the mem space returns EINVAL
        rather than the data that is available.  Whether this is a bug
        in UVM or not depends upon how it is defined to work, and I was
        unable to determine that.   (Simon Burge found that problem, and
        provided the basis of the workaround/fix).

        Then, the cmdline function is unable to read more than one
        page of args, and a good thing too, as the way it is written
        attempting to get more than that would reference into lala land.

        And, on an attempt to read a lot of data when the above is
        fixed, most of the data won't be returned, only the final block
        of any read.

Tested on alpha, pmax, i386 and sparc.

diffstat:

 sys/miscfs/procfs/procfs_cmdline.c |  53 ++++++++++++++++++-------------------
 1 files changed, 26 insertions(+), 27 deletions(-)

diffs (106 lines):

diff -r ab787a0be11c -r 42e13c3a0afc sys/miscfs/procfs/procfs_cmdline.c
--- a/sys/miscfs/procfs/procfs_cmdline.c        Tue May 16 11:27:37 2000 +0000
+++ b/sys/miscfs/procfs/procfs_cmdline.c        Tue May 16 13:45:25 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: procfs_cmdline.c,v 1.6 1999/07/22 18:13:38 thorpej Exp $       */
+/*     $NetBSD: procfs_cmdline.c,v 1.7 2000/05/16 13:45:25 simonb Exp $        */
 
 /*
  * Copyright (c) 1999 Jaromir Dolecek <dolecek%ics.muni.cz@localhost>
@@ -62,8 +62,8 @@
        struct uio *uio;
 {
        struct ps_strings pss;
-       int xlen, count, error, i;
-       size_t len, upper_bound;
+       int count, error, i;
+       size_t len, xlen, upper_bound;
        struct uio auio;
        struct iovec aiov;
        vaddr_t argv;
@@ -85,7 +85,14 @@
         */
        if (P_ZOMBIE(p) || (p->p_flag & P_SYSTEM) != 0) {
                len = snprintf(arg, PAGE_SIZE, "(%s)", p->p_comm);
-               goto doio;
+               xlen = len - uio->uio_offset;
+               if (xlen <= 0) 
+                       error = 0;
+               else
+                       error = uiomove(arg, xlen, uio);
+
+               free(arg, M_TEMP);
+               return (error);
        }
 
        /*
@@ -142,14 +149,15 @@
         */
        len = 0;
        count = pss.ps_nargvstr;
-       upper_bound = round_page(uio->uio_offset + 1);
-       for (; count && len < upper_bound; len += PAGE_SIZE) {
+       upper_bound = round_page(uio->uio_offset + uio->uio_resid);
+       for (; count && len < upper_bound; len += xlen) {
                aiov.iov_base = arg;
                aiov.iov_len = PAGE_SIZE;
                auio.uio_iov = &aiov;
                auio.uio_iovcnt = 1;
                auio.uio_offset = argv + len;
-               auio.uio_resid = PAGE_SIZE;
+               xlen = PAGE_SIZE - ((argv + len) & PAGE_MASK);
+               auio.uio_resid = xlen;
                auio.uio_segflg = UIO_SYSSPACE;
                auio.uio_rw = UIO_READ;
                auio.uio_procp = NULL;
@@ -157,39 +165,30 @@
                if (error)
                        goto bad;
 
-               for (i = len; i < (len + PAGE_SIZE) && count != 0; i++) {
+               for (i = 0; i < xlen && count != 0; i++) {
                        if (arg[i] == '\0')
                                count--;        /* one full string */
                }
 
-               if (count == 0) {
-                       /* No more argv strings, set up len and break. */
-                       len = i;
-                       break;
+               if (count == 0)
+                       i--;            /* exclude the final NUL */
+
+               if (len + i > uio->uio_offset) {
+                       /* Have data in this page, copy it out */
+                       error = uiomove(arg + uio->uio_offset - len,
+                           i + len - uio->uio_offset, uio);
+                       if (error || uio->uio_resid <= 0)
+                               break;
                }
        }
-       if (len > 0)
-               len--;                  /* exclude last NUL */
 
+ bad:
        /*
         * Release the process.
         */
        PRELE(p);
        uvmspace_free(p->p_vmspace);
 
- doio:
-       xlen = len - uio->uio_offset;
-       if (xlen <= 0) 
-               error = 0;
-       else
-               error = uiomove(arg + trunc_page(len), xlen, uio);
-
-       free(arg, M_TEMP);
-       return (error);
-
- bad:
-       PRELE(p);
-       uvmspace_free(p->p_vmspace);
        free(arg, M_TEMP);
        return (error);
 }



Home | Main Index | Thread Index | Old Index