Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 17 Dec 2011 16:59:22 +0000 (UTC)
From:      Mikolaj Golub <trociny@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r228648 - in head/sys: kern sys
Message-ID:  <201112171659.pBHGxMVB068390@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201112171659.pBHGxMVB068390>