Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 1 May 2013 15:01:06 +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: r250146 - head/lib/libprocstat
Message-ID:  <201305011501.r41F16n4085352@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: trociny
Date: Wed May  1 15:01:05 2013
New Revision: 250146
URL: http://svnweb.freebsd.org/changeset/base/250146

Log:
  KVM method support for procstat_getgroups, procstat_getumask,
  procstat_getrlimit, and procstat_getosrel.
  
  MFC after:	3 weeks

Modified:
  head/lib/libprocstat/libprocstat.c

Modified: head/lib/libprocstat/libprocstat.c
==============================================================================
--- head/lib/libprocstat/libprocstat.c	Wed May  1 14:59:16 2013	(r250145)
+++ head/lib/libprocstat/libprocstat.c	Wed May  1 15:01:05 2013	(r250146)
@@ -39,6 +39,9 @@ __FBSDID("$FreeBSD$");
 #include <sys/elf.h>
 #include <sys/time.h>
 #include <sys/resourcevar.h>
+#define	_WANT_UCRED
+#include <sys/ucred.h>
+#undef _WANT_UCRED
 #include <sys/proc.h>
 #include <sys/user.h>
 #include <sys/stat.h>
@@ -141,19 +144,30 @@ static int	procstat_get_vnode_info_sysct
     struct vnstat *vn, char *errbuf);
 static gid_t	*procstat_getgroups_core(struct procstat_core *core,
     unsigned int *count);
+static gid_t *	procstat_getgroups_kvm(kvm_t *kd, struct kinfo_proc *kp,
+    unsigned int *count);
 static gid_t	*procstat_getgroups_sysctl(pid_t pid, unsigned int *count);
 static struct kinfo_kstack	*procstat_getkstack_sysctl(pid_t pid,
     int *cntp);
+static int	procstat_getosrel_core(struct procstat_core *core,
+    int *osrelp);
+static int	procstat_getosrel_kvm(kvm_t *kd, struct kinfo_proc *kp,
+    int *osrelp);
+static int	procstat_getosrel_sysctl(pid_t pid, int *osrelp);
 static int	procstat_getpathname_core(struct procstat_core *core,
     char *pathname, size_t maxlen);
 static int	procstat_getpathname_sysctl(pid_t pid, char *pathname,
     size_t maxlen);
 static int	procstat_getrlimit_core(struct procstat_core *core, int which,
     struct rlimit* rlimit);
+static int	procstat_getrlimit_kvm(kvm_t *kd, struct kinfo_proc *kp,
+    int which, struct rlimit* rlimit);
 static int	procstat_getrlimit_sysctl(pid_t pid, int which,
     struct rlimit* rlimit);
 static int	procstat_getumask_core(struct procstat_core *core,
     unsigned short *maskp);
+static int	procstat_getumask_kvm(kvm_t *kd, struct kinfo_proc *kp,
+    unsigned short *maskp);
 static int	procstat_getumask_sysctl(pid_t pid, unsigned short *maskp);
 static int	vntype2psfsttype(int type);
 
@@ -1790,6 +1804,46 @@ procstat_freevmmap(struct procstat *proc
 }
 
 static gid_t *
+procstat_getgroups_kvm(kvm_t *kd, struct kinfo_proc *kp, unsigned int *cntp)
+{
+	struct proc proc;
+	struct ucred ucred;
+	gid_t *groups;
+	size_t len;
+
+	assert(kd != NULL);
+	assert(kp != NULL);
+	if (!kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc,
+	    sizeof(proc))) {
+		warnx("can't read proc struct at %p for pid %d",
+		    kp->ki_paddr, kp->ki_pid);
+		return (NULL);
+	}
+	if (proc.p_ucred == NOCRED)
+		return (NULL);
+	if (!kvm_read_all(kd, (unsigned long)proc.p_ucred, &ucred,
+	    sizeof(ucred))) {
+		warnx("can't read ucred struct at %p for pid %d",
+		    proc.p_ucred, kp->ki_pid);
+		return (NULL);
+	}
+	len = ucred.cr_ngroups * sizeof(gid_t);
+	groups = malloc(len);
+	if (groups == NULL) {
+		warn("malloc(%zu)", len);
+		return (NULL);
+	}
+	if (!kvm_read_all(kd, (unsigned long)ucred.cr_groups, groups, len)) {
+		warnx("can't read groups at %p for pid %d",
+		    ucred.cr_groups, kp->ki_pid);
+		free(groups);
+		return (NULL);
+	}
+	*cntp = ucred.cr_ngroups;
+	return (groups);
+}
+
+static gid_t *
 procstat_getgroups_sysctl(pid_t pid, unsigned int *cntp)
 {
 	int mib[4];
@@ -1834,8 +1888,7 @@ procstat_getgroups(struct procstat *proc
 {
 	switch(procstat->type) {
 	case PROCSTAT_KVM:
-		warnx("kvm method is not supported");
-		return (NULL);
+		return (procstat_getgroups_kvm(procstat->kd, kp, cntp));
 	case PROCSTAT_SYSCTL:
 		return (procstat_getgroups_sysctl(kp->ki_pid, cntp));
 	case PROCSTAT_CORE:
@@ -1854,6 +1907,24 @@ procstat_freegroups(struct procstat *pro
 }
 
 static int
+procstat_getumask_kvm(kvm_t *kd, struct kinfo_proc *kp, unsigned short *maskp)
+{
+	struct filedesc fd;
+
+	assert(kd != NULL);
+	assert(kp != NULL);
+	if (kp->ki_fd == NULL)
+		return (-1);
+	if (!kvm_read_all(kd, (unsigned long)kp->ki_fd, &fd, sizeof(fd))) {
+		warnx("can't read filedesc at %p for pid %d", kp->ki_fd,
+		    kp->ki_pid);
+		return (-1);
+	}
+	*maskp = fd.fd_cmask;
+	return (0);
+}
+
+static int
 procstat_getumask_sysctl(pid_t pid, unsigned short *maskp)
 {
 	int error;
@@ -1895,8 +1966,7 @@ procstat_getumask(struct procstat *procs
 {
 	switch(procstat->type) {
 	case PROCSTAT_KVM:
-		warnx("kvm method is not supported");
-		return (-1);
+		return (procstat_getumask_kvm(procstat->kd, kp, maskp));
 	case PROCSTAT_SYSCTL:
 		return (procstat_getumask_sysctl(kp->ki_pid, maskp));
 	case PROCSTAT_CORE:
@@ -1908,6 +1978,33 @@ procstat_getumask(struct procstat *procs
 }
 
 static int
+procstat_getrlimit_kvm(kvm_t *kd, struct kinfo_proc *kp, int which,
+    struct rlimit* rlimit)
+{
+	struct proc proc;
+	unsigned long offset;
+
+	assert(kd != NULL);
+	assert(kp != NULL);
+	assert(which >= 0 && which < RLIM_NLIMITS);
+	if (!kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc,
+	    sizeof(proc))) {
+		warnx("can't read proc struct at %p for pid %d",
+		    kp->ki_paddr, kp->ki_pid);
+		return (-1);
+	}
+	if (proc.p_limit == NULL)
+		return (-1);
+	offset = (unsigned long)proc.p_limit + sizeof(struct rlimit) * which;
+	if (!kvm_read_all(kd, offset, rlimit, sizeof(*rlimit))) {
+		warnx("can't read rlimit struct at %p for pid %d",
+		    (void *)offset, kp->ki_pid);
+		return (-1);
+	}
+	return (0);
+}
+
+static int
 procstat_getrlimit_sysctl(pid_t pid, int which, struct rlimit* rlimit)
 {
 	int error, name[5];
@@ -1958,8 +2055,8 @@ procstat_getrlimit(struct procstat *proc
 {
 	switch(procstat->type) {
 	case PROCSTAT_KVM:
-		warnx("kvm method is not supported");
-		return (-1);
+		return (procstat_getrlimit_kvm(procstat->kd, kp, which,
+		    rlimit));
 	case PROCSTAT_SYSCTL:
 		return (procstat_getrlimit_sysctl(kp->ki_pid, which, rlimit));
 	case PROCSTAT_CORE:
@@ -2032,6 +2129,23 @@ procstat_getpathname(struct procstat *pr
 }
 
 static int
+procstat_getosrel_kvm(kvm_t *kd, struct kinfo_proc *kp, int *osrelp)
+{
+	struct proc proc;
+
+	assert(kd != NULL);
+	assert(kp != NULL);
+	if (!kvm_read_all(kd, (unsigned long)kp->ki_paddr, &proc,
+	    sizeof(proc))) {
+		warnx("can't read proc struct at %p for pid %d",
+		    kp->ki_paddr, kp->ki_pid);
+		return (-1);
+	}
+	*osrelp = proc.p_osrel;
+	return (0);
+}
+
+static int
 procstat_getosrel_sysctl(pid_t pid, int *osrelp)
 {
 	int error, name[4];
@@ -2071,8 +2185,7 @@ procstat_getosrel(struct procstat *procs
 {
 	switch(procstat->type) {
 	case PROCSTAT_KVM:
-		warnx("kvm method is not supported");
-		return (-1);
+		return (procstat_getosrel_kvm(procstat->kd, kp, osrelp));
 	case PROCSTAT_SYSCTL:
 		return (procstat_getosrel_sysctl(kp->ki_pid, osrelp));
 	case PROCSTAT_CORE:



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