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:
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to