Author: trociny
Date: Sat Dec 17 16:59:22 2011
New Revision: 228648
URL: http://svn.freebsd.org/changeset/base/228648

Log:
  On start most of sysctl_kern_proc functions use the same pattern:
  locate a process calling pfind() and do some additional checks like
  p_candebug(). To reduce this code duplication a new function pget() is
  introduced and used.
  
  As the function may be useful not only in kern_proc.c it is in the
  kernel name space.
  
  Suggested by: kib
  Reviewed by:  kib
  MFC after:    2 weeks

Modified:
  head/sys/kern/kern_proc.c
  head/sys/sys/proc.h

Modified: head/sys/kern/kern_proc.c
==============================================================================
--- head/sys/kern/kern_proc.c   Sat Dec 17 16:30:42 2011        (r228647)
+++ head/sys/kern/kern_proc.c   Sat Dec 17 16:59:22 2011        (r228648)
@@ -330,6 +330,55 @@ pgfind(pgid)
 }
 
 /*
+ * Locate process and do additional manipulations, depending on flags.
+ */
+int
+pget(pid_t pid, int flags, struct proc **pp)
+{
+       struct proc *p;
+       int error;
+
+       p = pfind(pid);
+       if (p == NULL)
+               return (ESRCH);
+       if ((flags & PGET_CANSEE) != 0) {
+               error = p_cansee(curthread, p);
+               if (error != 0)
+                       goto errout;
+       }
+       if ((flags & PGET_CANDEBUG) != 0) {
+               error = p_candebug(curthread, p);
+               if (error != 0)
+                       goto errout;
+       }
+       if ((flags & PGET_ISCURRENT) != 0 && curproc != p) {
+               error = EPERM;
+               goto errout;
+       }
+       if ((flags & PGET_NOTWEXIT) != 0 && (p->p_flag & P_WEXIT) != 0) {
+               error = ESRCH;
+               goto errout;
+       }
+       if ((flags & PGET_NOTINEXEC) != 0 && (p->p_flag & P_INEXEC) != 0) {
+               /*
+                * XXXRW: Not clear ESRCH is the right error during proc
+                * execve().
+                */
+               error = ESRCH;
+               goto errout;
+       }
+       if ((flags & PGET_HOLD) != 0) {
+               _PHOLD(p);
+               PROC_UNLOCK(p);
+       }
+       *pp = p;
+       return (0);
+errout:
+       PROC_UNLOCK(p);
+       return (error);
+}
+
+/*
  * Create a new process group.
  * pgid must be equal to the pid of p.
  * Begin a new session if required.
@@ -1177,13 +1226,9 @@ sysctl_kern_proc(SYSCTL_HANDLER_ARGS)
                error = sysctl_wire_old_buffer(req, 0);
                if (error)
                        return (error);         
-               p = pfind((pid_t)name[0]);
-               if (!p)
-                       return (ESRCH);
-               if ((error = p_cansee(curthread, p))) {
-                       PROC_UNLOCK(p);
+               error = pget((pid_t)name[0], PGET_CANSEE, &p);
+               if (error != 0)
                        return (error);
-               }
                error = sysctl_out_proc(p, req, flags);
                return (error);
        }
@@ -1661,24 +1706,17 @@ sysctl_kern_proc_args(SYSCTL_HANDLER_ARG
        struct pargs *newpa, *pa;
        struct proc *p;
        struct sbuf sb;
-       int error = 0, error2;
+       int flags, error = 0, error2;
 
        if (namelen != 1) 
                return (EINVAL);
 
-       p = pfind((pid_t)name[0]);
-       if (!p)
-               return (ESRCH);
-
-       if ((error = p_cansee(curthread, p)) != 0) {
-               PROC_UNLOCK(p);
+       flags = PGET_CANSEE;
+       if (req->newptr != NULL)
+               flags |= PGET_ISCURRENT;
+       error = pget((pid_t)name[0], flags, &p);
+       if (error)
                return (error);
-       }
-
-       if (req->newptr && curproc != p) {
-               PROC_UNLOCK(p);
-               return (EPERM);
-       }
 
        pa = p->p_args;
        if (pa != NULL) {
@@ -1733,23 +1771,14 @@ sysctl_kern_proc_env(SYSCTL_HANDLER_ARGS
        if (namelen != 1)
                return (EINVAL);
 
-       p = pfind((pid_t)name[0]);
-       if (p == NULL)
-               return (ESRCH);
-       if ((p->p_flag & P_WEXIT) != 0) {
-               PROC_UNLOCK(p);
-               return (ESRCH);
-       }
-       if ((error = p_candebug(curthread, p)) != 0) {
-               PROC_UNLOCK(p);
+       error = pget((pid_t)name[0], PGET_WANTREAD, &p);
+       if (error != 0)
                return (error);
-       }
        if ((p->p_flag & P_SYSTEM) != 0) {
-               PROC_UNLOCK(p);
+               PRELE(p);
                return (0);
        }
-       _PHOLD(p);
-       PROC_UNLOCK(p);
+
        sbuf_new_for_sysctl(&sb, NULL, GET_PS_STRINGS_CHUNK_SZ, req);
        error = proc_getenvv(curthread, p, &sb, req->oldlen);
        error2 = sbuf_finish(&sb);
@@ -1775,24 +1804,13 @@ sysctl_kern_proc_auxv(SYSCTL_HANDLER_ARG
        if (namelen != 1)
                return (EINVAL);
 
-       p = pfind((pid_t)name[0]);
-       if (p == NULL)
-               return (ESRCH);
-       if (p->p_flag & P_WEXIT) {
-               PROC_UNLOCK(p);
-               return (ESRCH);
-       }
-       error = p_candebug(curthread, p);
-       if (error != 0) {
-               PROC_UNLOCK(p);
+       error = pget((pid_t)name[0], PGET_WANTREAD, &p);
+       if (error != 0)
                return (error);
-       }
        if ((p->p_flag & P_SYSTEM) != 0) {
-               PROC_UNLOCK(p);
+               PRELE(p);
                return (0);
        }
-       _PHOLD(p);
-       PROC_UNLOCK(p);
        error = get_proc_vector(curthread, p, &auxv, &vsize, PROC_AUX);
        if (error == 0) {
 #ifdef COMPAT_FREEBSD32
@@ -1829,13 +1847,9 @@ sysctl_kern_proc_pathname(SYSCTL_HANDLER
        if (*pidp == -1) {      /* -1 means this process */
                p = req->td->td_proc;
        } else {
-               p = pfind(*pidp);
-               if (p == NULL)
-                       return (ESRCH);
-               if ((error = p_cansee(curthread, p)) != 0) {
-                       PROC_UNLOCK(p);
+               error = pget(*pidp, PGET_CANSEE, &p);
+               if (error != 0)
                        return (error);
-               }
        }
 
        vp = p->p_textvp;
@@ -1872,12 +1886,9 @@ sysctl_kern_proc_sv_name(SYSCTL_HANDLER_
                return (EINVAL);
 
        name = (int *)arg1;
-       if ((p = pfind((pid_t)name[0])) == NULL)
-               return (ESRCH);
-       if ((error = p_cansee(curthread, p))) {
-               PROC_UNLOCK(p);
+       error = pget((pid_t)name[0], PGET_CANSEE, &p);
+       if (error != 0)
                return (error);
-       }
        sv_name = p->p_sysent->sv_name;
        PROC_UNLOCK(p);
        return (sysctl_handle_string(oidp, sv_name, 0, req));
@@ -1904,18 +1915,9 @@ sysctl_kern_proc_ovmmap(SYSCTL_HANDLER_A
        struct vmspace *vm;
 
        name = (int *)arg1;
-       if ((p = pfind((pid_t)name[0])) == NULL)
-               return (ESRCH);
-       if (p->p_flag & P_WEXIT) {
-               PROC_UNLOCK(p);
-               return (ESRCH);
-       }
-       if ((error = p_candebug(curthread, p))) {
-               PROC_UNLOCK(p);
+       error = pget((pid_t)name[0], PGET_WANTREAD, &p);
+       if (error != 0)
                return (error);
-       }
-       _PHOLD(p);
-       PROC_UNLOCK(p);
        vm = vmspace_acquire_ref(p);
        if (vm == NULL) {
                PRELE(p);
@@ -2082,18 +2084,9 @@ sysctl_kern_proc_vmmap(SYSCTL_HANDLER_AR
        vm_map_t map;
 
        name = (int *)arg1;
-       if ((p = pfind((pid_t)name[0])) == NULL)
-               return (ESRCH);
-       if (p->p_flag & P_WEXIT) {
-               PROC_UNLOCK(p);
-               return (ESRCH);
-       }
-       if ((error = p_candebug(curthread, p))) {
-               PROC_UNLOCK(p);
+       error = pget((pid_t)name[0], PGET_WANTREAD, &p);
+       if (error != 0)
                return (error);
-       }
-       _PHOLD(p);
-       PROC_UNLOCK(p);
        vm = vmspace_acquire_ref(p);
        if (vm == NULL) {
                PRELE(p);
@@ -2267,19 +2260,9 @@ sysctl_kern_proc_kstack(SYSCTL_HANDLER_A
        struct proc *p;
 
        name = (int *)arg1;
-       if ((p = pfind((pid_t)name[0])) == NULL)
-               return (ESRCH);
-       /* XXXRW: Not clear ESRCH is the right error during proc execve(). */
-       if (p->p_flag & P_WEXIT || p->p_flag & P_INEXEC) {
-               PROC_UNLOCK(p);
-               return (ESRCH);
-       }
-       if ((error = p_candebug(curthread, p))) {
-               PROC_UNLOCK(p);
+       error = pget((pid_t)name[0], PGET_NOTINEXEC | PGET_WANTREAD, &p);
+       if (error != 0)
                return (error);
-       }
-       _PHOLD(p);
-       PROC_UNLOCK(p);
 
        kkstp = malloc(sizeof(*kkstp), M_TEMP, M_WAITOK);
        st = stack_create();
@@ -2374,13 +2357,9 @@ sysctl_kern_proc_groups(SYSCTL_HANDLER_A
        if (*pidp == -1) {      /* -1 means this process */
                p = req->td->td_proc;
        } else {
-               p = pfind(*pidp);
-               if (p == NULL)
-                       return (ESRCH);
-               if ((error = p_cansee(curthread, p)) != 0) {
-                       PROC_UNLOCK(p);
+               error = pget(*pidp, PGET_CANSEE, &p);
+               if (error != 0)
                        return (error);
-               }
        }
 
        cred = crhold(p->p_ucred);
@@ -2409,15 +2388,9 @@ sysctl_kern_proc_rlimit(SYSCTL_HANDLER_A
        if (namelen != 1)
                return (EINVAL);
 
-       p = pfind((pid_t)name[0]);
-       if (p == NULL)
-               return (ESRCH);
-
-       if ((error = p_cansee(curthread, p)) != 0) {
-               PROC_UNLOCK(p);
+       error = pget((pid_t)name[0], PGET_CANSEE, &p);
+       if (error != 0)
                return (error);
-       }
-
        /*
         * Check the request size.  We alow sizes smaller rlimit array for
         * backward binary compatibility: the number of resource limits may
@@ -2454,14 +2427,9 @@ sysctl_kern_proc_ps_strings(SYSCTL_HANDL
        if (namelen != 1)
                return (EINVAL);
 
-       p = pfind((pid_t)name[0]);
-       if (p == NULL)
-               return (ESRCH);
-       error = p_candebug(curthread, p);
-       if (error != 0) {
-               PROC_UNLOCK(p);
+       error = pget((pid_t)name[0], PGET_CANDEBUG, &p);
+       if (error != 0)
                return (error);
-       }
 #ifdef COMPAT_FREEBSD32
        if ((req->flags & SCTL_MASK32) != 0) {
                /*

Modified: head/sys/sys/proc.h
==============================================================================
--- head/sys/sys/proc.h Sat Dec 17 16:30:42 2011        (r228647)
+++ head/sys/sys/proc.h Sat Dec 17 16:59:22 2011        (r228648)
@@ -818,6 +818,20 @@ struct     proc *pfind(pid_t);             /* Find proc
 struct pgrp *pgfind(pid_t);            /* Find process group by id. */
 struct proc *zpfind(pid_t);            /* Find zombie process by id. */
 
+/*
+ * pget() flags.
+ */
+#define        PGET_HOLD       0x00001 /* Hold the process. */
+#define        PGET_CANSEE     0x00002 /* Check against p_cansee(). */
+#define        PGET_CANDEBUG   0x00004 /* Check against p_candebug(). */
+#define        PGET_ISCURRENT  0x00008 /* Check that the found process is 
current. */
+#define        PGET_NOTWEXIT   0x00010 /* Check that the process is not in 
P_WEXIT. */
+#define        PGET_NOTINEXEC  0x00020 /* Check that the process is not in 
P_INEXEC. */
+
+#define        PGET_WANTREAD   (PGET_HOLD | PGET_CANDEBUG | PGET_NOTWEXIT)
+
+int    pget(pid_t pid, int flags, struct proc **pp);
+
 void   ast(struct trapframe *framep);
 struct thread *choosethread(void);
 int    cr_cansignal(struct ucred *cred, struct proc *proc, int signum);
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to