Source-Changes-HG archive

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

[src/trunk]: src/sys Add some new sysctls to help abolish the dreaded "proc s...



details:   https://anonhg.NetBSD.org/src/rev/6209c2ab2182
branches:  trunk
changeset: 486580:6209c2ab2182
user:      simonb <simonb%NetBSD.org@localhost>
date:      Fri May 26 02:23:12 2000 +0000

description:
Add some new sysctls to help abolish the dreaded "proc size mismatch"
errors from ps(1) and some other kernel grovellers, and return some
data that has previously only been accessable with /dev/kmem read
access.  The sysctls are:

 + KERN_PROC2 - return an array of fixed sized "struct kinfo_proc2"
   structures that contain most of the useful user-level data in
   "struct proc" and "struct user".  The sysctl also takes the size of
   each element, so that if "struct kinfo_proc2" grows over time old
   binaries will still be able to request a fixed size amount of data.
 + KERN_PROC_ARGS - return the argv or envv for a particular process id.
   envv will only be returned if the process has the same user id as the
   requestor or if the requestor is root.
 + KERN_FSCALE - return the current kernel fixpt scale factor.
 + KERN_CCPU - return the scheduler exponential decay value.
 + KERN_CP_TIME - return cpu time state counters.

With input and suggestions from many people on tech-kern.

diffstat:

 sys/kern/kern_sysctl.c |  492 +++++++++++++++++++++++++++++++++++++++++++-----
 sys/sys/proc.h         |    8 +-
 sys/sys/sysctl.h       |  149 ++++++++++++++-
 3 files changed, 592 insertions(+), 57 deletions(-)

diffs (truncated from 833 to 300 lines):

diff -r 4041f5376b22 -r 6209c2ab2182 sys/kern/kern_sysctl.c
--- a/sys/kern/kern_sysctl.c    Fri May 26 02:10:18 2000 +0000
+++ b/sys/kern/kern_sysctl.c    Fri May 26 02:23:12 2000 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: kern_sysctl.c,v 1.61 2000/04/15 04:38:07 simonb Exp $  */
+/*     $NetBSD: kern_sysctl.c,v 1.62 2000/05/26 02:23:12 simonb Exp $  */
 
 /*-
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -50,33 +50,32 @@
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
+#include <sys/buf.h>
+#include <sys/device.h>
+#include <sys/disklabel.h>
+#include <sys/dkstat.h>
+#include <sys/exec.h>
+#include <sys/file.h>
+#include <sys/ioctl.h>
 #include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/msgbuf.h>
 #include <sys/pool.h>
 #include <sys/proc.h>
-#include <sys/file.h>
-#include <sys/vnode.h>
-#include <sys/unistd.h>
-#include <sys/buf.h>
-#include <sys/ioctl.h>
-#include <sys/tty.h>
-#include <sys/disklabel.h>
-#include <sys/device.h>
-#include <vm/vm.h>
-#include <sys/sysctl.h>
-#include <sys/msgbuf.h>
-
-#include <uvm/uvm_extern.h>
-
-#include <sys/mount.h>
-#include <sys/syscallargs.h>
 #include <sys/resource.h>
 #include <sys/resourcevar.h>
-
+#include <sys/syscallargs.h>
+#include <sys/tty.h>
+#include <sys/unistd.h>
+#include <sys/vnode.h>
+#include <sys/sysctl.h>
 
 #if defined(DDB)
 #include <ddb/ddbvar.h>
 #endif
 
+#define PTRTOINT64(foo)        ((u_int64_t)(uintptr_t)(foo))
+
 /*
  * Locking and stats
  */
@@ -86,6 +85,10 @@
        int     sl_locked;
 } memlock;
 
+static int sysctl_doeproc __P((int *, u_int, char *, size_t *));
+static void fill_kproc2 __P((struct proc *, struct kinfo_proc2 *));
+static int sysctl_procargs __P((int *, u_int, void *, size_t *, struct proc *));
+
 int
 sys___sysctl(p, v, retval)
        struct proc *p;
@@ -234,6 +237,7 @@
 int defcorenamelen = sizeof("%n.core");
 #endif
 extern int     kern_logsigexit;
+extern fixpt_t ccpu;
 
 /*
  * kernel related system variables.
@@ -255,8 +259,10 @@
        /* All sysctl names at this level, except for a few, are terminal. */
        switch (name[0]) {
        case KERN_PROC:
+       case KERN_PROC2:
        case KERN_PROF:
        case KERN_MBUF:
+       case KERN_PROC_ARGS:
                /* Not terminal. */
                break;
        default:
@@ -321,7 +327,11 @@
        case KERN_VNODE:
                return (sysctl_vnode(oldp, oldlenp, p));
        case KERN_PROC:
-               return (sysctl_doeproc(name + 1, namelen - 1, oldp, oldlenp));
+       case KERN_PROC2:
+               return (sysctl_doeproc(name, namelen, oldp, oldlenp));
+       case KERN_PROC_ARGS:
+               return (sysctl_procargs(name + 1, namelen - 1,
+                   oldp, oldlenp, p));
        case KERN_FILE:
                return (sysctl_file(oldp, oldlenp));
 #ifdef GPROF
@@ -423,7 +433,15 @@
        case KERN_LOGIN_NAME_MAX:
                return (sysctl_rdint(oldp, oldlenp, newp, LOGIN_NAME_MAX));
        case KERN_LOGSIGEXIT:
-               return (sysctl_int(oldp, oldlenp, newp, newlen, &kern_logsigexit));
+               return (sysctl_int(oldp, oldlenp, newp, newlen,
+                   &kern_logsigexit));
+       case KERN_FSCALE:
+               return (sysctl_rdint(oldp, oldlenp, newp, FSCALE));
+       case KERN_CCPU:
+               return (sysctl_rdint(oldp, oldlenp, newp, ccpu));
+       case KERN_CP_TIME:
+               return (sysctl_rdstruct(oldp, oldlenp, newp, cp_time,
+                   sizeof(cp_time)));
        default:
                return (EOPNOTSUPP);
        }
@@ -528,7 +546,7 @@
        size_t newlen;
        struct proc *p;
 {
-       struct proc *ptmp=NULL;
+       struct proc *ptmp = NULL;
        const struct proclist_desc *pd;
        int error = 0;
        struct rlimit alim;
@@ -954,23 +972,40 @@
        char *where;
        size_t *sizep;
 {
-       struct proc *p;
+       struct eproc eproc;
+       struct kinfo_proc2 kproc2;
        struct kinfo_proc *dp = (struct kinfo_proc *)where;
-       int needed = 0;
-       int buflen = where != NULL ? *sizep : 0;
+       struct proc *p;
        const struct proclist_desc *pd;
-       struct eproc eproc;
-       int error = 0;
+       char *dp2;
+       int type, op, arg, elem_size, elem_count;
+       int buflen, needed, error;
+
+       dp2 = where;
+       buflen = where != NULL ? *sizep : 0;
+       error = needed = 0;
+       type = name[0];
 
-       if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL))
-               return (EINVAL);
+       if (type == KERN_PROC) {
+               if (namelen != 3 && !(namelen == 2 && name[1] == KERN_PROC_ALL))
+                       return (EINVAL);
+               op = name[1];
+               if (op != KERN_PROC_ALL)
+                       arg = name[2];
+       } else {
+               if (namelen != 5)
+                       return (EINVAL);
+               op = name[1];
+               arg = name[2];
+               elem_size = name[3];
+               elem_count = name[4];
+       }
 
        proclist_lock_read();
 
        pd = proclists;
 again:
-       for (p = LIST_FIRST(pd->pd_list); p != NULL;
-            p = LIST_NEXT(p, p_list)) {
+       for (p = LIST_FIRST(pd->pd_list); p != NULL; p = LIST_NEXT(p, p_list)) {
                /*
                 * Skip embryonic processes.
                 */
@@ -980,59 +1015,75 @@
                 * TODO - make more efficient (see notes below).
                 * do by session.
                 */
-               switch (name[0]) {
+               switch (op) {
 
                case KERN_PROC_PID:
                        /* could do this with just a lookup */
-                       if (p->p_pid != (pid_t)name[1])
+                       if (p->p_pid != (pid_t)arg)
                                continue;
                        break;
 
                case KERN_PROC_PGRP:
                        /* could do this by traversing pgrp */
-                       if (p->p_pgrp->pg_id != (pid_t)name[1])
+                       if (p->p_pgrp->pg_id != (pid_t)arg)
                                continue;
                        break;
 
                case KERN_PROC_TTY:
-                       if (name[1] == KERN_PROC_TTY_REVOKE) {
+                       if (arg == KERN_PROC_TTY_REVOKE) {
                                if ((p->p_flag & P_CONTROLT) == 0 ||
                                    p->p_session->s_ttyp == NULL ||
                                    p->p_session->s_ttyvp != NULL)
                                        continue;
                        } else if ((p->p_flag & P_CONTROLT) == 0 ||
                            p->p_session->s_ttyp == NULL) {
-                               if ((dev_t)name[1] != KERN_PROC_TTY_NODEV)
+                               if ((dev_t)arg != KERN_PROC_TTY_NODEV)
                                        continue;
-                       } else if (p->p_session->s_ttyp->t_dev !=
-                           (dev_t)name[1])
+                       } else if (p->p_session->s_ttyp->t_dev != (dev_t)arg)
                                continue;
                        break;
 
                case KERN_PROC_UID:
-                       if (p->p_ucred->cr_uid != (uid_t)name[1])
+                       if (p->p_ucred->cr_uid != (uid_t)arg)
                                continue;
                        break;
 
                case KERN_PROC_RUID:
-                       if (p->p_cred->p_ruid != (uid_t)name[1])
+                       if (p->p_cred->p_ruid != (uid_t)arg)
                                continue;
                        break;
                }
-               if (buflen >= sizeof(struct kinfo_proc)) {
-                       fill_eproc(p, &eproc);
-                       error = copyout((caddr_t)p, &dp->kp_proc,
-                                       sizeof(struct proc));
-                       if (error)
-                               goto cleanup;
-                       error = copyout((caddr_t)&eproc, &dp->kp_eproc,
-                                       sizeof(eproc));
-                       if (error)
-                               goto cleanup;
-                       dp++;
-                       buflen -= sizeof(struct kinfo_proc);
+               if (type == KERN_PROC) {
+                       if (buflen >= sizeof(struct kinfo_proc)) {
+                               fill_eproc(p, &eproc);
+                               error = copyout((caddr_t)p, &dp->kp_proc,
+                                               sizeof(struct proc));
+                               if (error)
+                                       goto cleanup;
+                               error = copyout((caddr_t)&eproc, &dp->kp_eproc,
+                                               sizeof(eproc));
+                               if (error)
+                                       goto cleanup;
+                               dp++;
+                               buflen -= sizeof(struct kinfo_proc);
+                       }
+                       needed += sizeof(struct kinfo_proc);
+               } else { /* KERN_PROC2 */
+                       if (buflen >= elem_size) {
+                               fill_kproc2(p, &kproc2);
+                               /*
+                                * Copy out elem_size, but not larger than
+                                * the size of a struct kinfo_proc2.
+                                */
+                               error = copyout(&kproc2, dp2,
+                                   min(sizeof(kproc2), elem_size));
+                               if (error)
+                                       goto cleanup;
+                               dp2 += elem_size;
+                               buflen -= elem_size;
+                       }
+                       needed += elem_size;
                }
-               needed += sizeof(struct kinfo_proc);
        }
        pd++;
        if (pd->pd_list != NULL)
@@ -1040,7 +1091,10 @@
        proclist_unlock_read();
 
        if (where != NULL) {
-               *sizep = (caddr_t)dp - where;
+               if (type == KERN_PROC)
+                       *sizep = (caddr_t)dp - where;
+               else
+                       *sizep = dp2 - where;
                if (needed > *sizep)
                        return (ENOMEM);
        } else {
@@ -1104,3 +1158,335 @@
                ep->e_flag |= EPROC_SLEADER;
        strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME);
 }
+
+/*
+ * Fill in an eproc structure for the specified process.
+ */
+static void
+fill_kproc2(p, ki)
+       struct proc *p;
+       struct kinfo_proc2 *ki;



Home | Main Index | Thread Index | Old Index