summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authortrociny <trociny@FreeBSD.org>2013-05-01 15:01:05 +0000
committertrociny <trociny@FreeBSD.org>2013-05-01 15:01:05 +0000
commit49b0478cb530a5afcadbfee861032ec8956962e1 (patch)
tree48501b8ea224edd8ac68a511ca26b8cfe1f7b9f6 /lib
parenta5058251d5c4dea7f9fca6204926f459a99f4a16 (diff)
downloadFreeBSD-src-49b0478cb530a5afcadbfee861032ec8956962e1.zip
FreeBSD-src-49b0478cb530a5afcadbfee861032ec8956962e1.tar.gz
KVM method support for procstat_getgroups, procstat_getumask,
procstat_getrlimit, and procstat_getosrel. MFC after: 3 weeks
Diffstat (limited to 'lib')
-rw-r--r--lib/libprocstat/libprocstat.c129
1 files changed, 121 insertions, 8 deletions
diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c
index a54b90d..535cdfc 100644
--- a/lib/libprocstat/libprocstat.c
+++ b/lib/libprocstat/libprocstat.c
@@ -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_sysctl(struct filestat *fst,
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 *procstat __unused,
}
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 *procstat, struct kinfo_proc *kp,
{
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 *procstat __unused, gid_t *groups)
}
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 *procstat, struct kinfo_proc *kp,
{
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 *procstat, struct kinfo_proc *kp,
}
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 *procstat, struct kinfo_proc *kp, int which,
{
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 *procstat, struct kinfo_proc *kp,
}
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 *procstat, struct kinfo_proc *kp, int *osrelp)
{
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:
OpenPOWER on IntegriCloud