svn commit: r195853 - in head: sys/kern sys/sys usr.bin/procstat
Brooks Davis
brooks at FreeBSD.org
Fri Jul 24 19:12:20 UTC 2009
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");
}
More information about the svn-src-all
mailing list