Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 24 Jul 2009 19:12:20 +0000 (UTC)
From:      Brooks Davis <brooks@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r195853 - in head: sys/kern sys/sys usr.bin/procstat
Message-ID:  <200907241912.n6OJCKih018651@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: brooks
Date: Fri Jul 24 19:12:19 2009
New Revision: 195853
URL: http://svn.freebsd.org/changeset/base/195853

Log:
  Introduce a new sysctl process mib, kern.proc.groups which adds the
  ability to retrieve the group list of each process.
  
  Modify procstat's -s option to query this mib when the kinfo_proc
  reports that the field has been truncated.  If the mib does not exist,
  fall back to the truncated list.
  
  Reviewed by:	rwatson
  Approved by:	re (kib)
  MFC after:	2 weeks

Modified:
  head/sys/kern/kern_proc.c
  head/sys/sys/sysctl.h
  head/usr.bin/procstat/procstat_cred.c

Modified: head/sys/kern/kern_proc.c
==============================================================================
--- head/sys/kern/kern_proc.c	Fri Jul 24 18:31:04 2009	(r195852)
+++ head/sys/kern/kern_proc.c	Fri Jul 24 19:12:19 2009	(r195853)
@@ -1826,6 +1826,43 @@ repeat:
 }
 #endif
 
+/*
+ * This sysctl allows a process to retrieve the full list of groups from
+ * itself or another process.
+ */
+static int
+sysctl_kern_proc_groups(SYSCTL_HANDLER_ARGS)
+{
+	pid_t *pidp = (pid_t *)arg1;
+	unsigned int arglen = arg2;
+	struct proc *p;
+	struct ucred *cred;
+	int error;
+
+	if (arglen != 1)
+		return (EINVAL);
+	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);
+			return (error);
+		}
+	}
+
+	cred = crhold(p->p_ucred);
+	if (*pidp != -1)
+		PROC_UNLOCK(p);
+
+	error = SYSCTL_OUT(req, cred->cr_groups,
+	    cred->cr_ngroups * sizeof(gid_t));
+	crfree(cred);
+	return (error);
+}
+
 SYSCTL_NODE(_kern, KERN_PROC, proc, CTLFLAG_RD,  0, "Process table");
 
 SYSCTL_PROC(_kern_proc, KERN_PROC_ALL, all, CTLFLAG_RD|CTLTYPE_STRUCT|
@@ -1910,3 +1947,6 @@ static SYSCTL_NODE(_kern_proc, KERN_PROC
 static SYSCTL_NODE(_kern_proc, KERN_PROC_KSTACK, kstack, CTLFLAG_RD |
 	CTLFLAG_MPSAFE, sysctl_kern_proc_kstack, "Process kernel stacks");
 #endif
+
+static SYSCTL_NODE(_kern_proc, KERN_PROC_GROUPS, groups, CTLFLAG_RD |
+	CTLFLAG_MPSAFE, sysctl_kern_proc_groups, "Process groups");

Modified: head/sys/sys/sysctl.h
==============================================================================
--- head/sys/sys/sysctl.h	Fri Jul 24 18:31:04 2009	(r195852)
+++ head/sys/sys/sysctl.h	Fri Jul 24 19:12:19 2009	(r195853)
@@ -486,6 +486,7 @@ TAILQ_HEAD(sysctl_ctx_list, sysctl_ctx_e
 					 */
 #define	KERN_PROC_VMMAP		32	/* VM map entries for process */
 #define	KERN_PROC_FILEDESC	33	/* File descriptors for process */
+#define	KERN_PROC_GROUPS	34	/* process groups */
 
 /*
  * KERN_IPC identifiers

Modified: head/usr.bin/procstat/procstat_cred.c
==============================================================================
--- head/usr.bin/procstat/procstat_cred.c	Fri Jul 24 18:31:04 2009	(r195852)
+++ head/usr.bin/procstat/procstat_cred.c	Fri Jul 24 19:12:19 2009	(r195853)
@@ -31,7 +31,9 @@
 #include <sys/user.h>
 
 #include <err.h>
+#include <stdlib.h>
 #include <stdio.h>
+#include <unistd.h>
 
 #include "procstat.h"
 
@@ -39,6 +41,10 @@ void
 procstat_cred(pid_t pid, struct kinfo_proc *kipp)
 {
 	int i;
+	int mib[4];
+	int ngroups;
+	size_t len;
+	gid_t *groups = NULL;
 
 	if (!hflag)
 		printf("%5s %-16s %5s %5s %5s %5s %5s %5s %-20s\n", "PID",
@@ -53,7 +59,39 @@ procstat_cred(pid_t pid, struct kinfo_pr
 	printf("%5d ", kipp->ki_groups[0]);
 	printf("%5d ", kipp->ki_rgid);
 	printf("%5d ", kipp->ki_svgid);
-	for (i = 0; i < kipp->ki_ngroups; i++)
-		printf("%s%d", (i > 0) ? "," : "", kipp->ki_groups[i]);
+
+	/*
+	 * We may have too many groups to fit in kinfo_proc's statically
+	 * sized storage.  If that occurs, attempt to retrieve them via
+	 * sysctl.
+	 */
+	if (kipp->ki_cr_flags & KI_CRF_GRP_OVERFLOW) {
+		mib[0] = CTL_KERN;
+		mib[1] = KERN_PROC;
+		mib[2] = KERN_PROC_GROUPS;
+		mib[3] = pid;
+
+		ngroups = sysconf(_SC_NGROUPS_MAX) + 1;
+		len = ngroups * sizeof(gid_t);
+		if((groups = malloc(len)) == NULL)
+			err(-1, "malloc");
+
+		if (sysctl(mib, 4, groups, &len, NULL, 0) == -1) {
+			warn("sysctl: kern.proc.groups: %d "
+			    "group list truncated", pid);
+			free(groups);
+			groups = NULL;
+		}
+		ngroups = len / sizeof(gid_t);
+	}
+	if (groups == NULL) {
+		ngroups = kipp->ki_ngroups;
+		groups = kipp->ki_groups;
+	}
+	for (i = 0; i < ngroups; i++)
+		printf("%s%d", (i > 0) ? "," : "", groups[i]);
+	if (groups != kipp->ki_groups)
+		free(groups);
+
 	printf("\n");
 }



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