diff options
author | trociny <trociny@FreeBSD.org> | 2013-05-01 15:01:05 +0000 |
---|---|---|
committer | trociny <trociny@FreeBSD.org> | 2013-05-01 15:01:05 +0000 |
commit | 49b0478cb530a5afcadbfee861032ec8956962e1 (patch) | |
tree | 48501b8ea224edd8ac68a511ca26b8cfe1f7b9f6 /lib | |
parent | a5058251d5c4dea7f9fca6204926f459a99f4a16 (diff) | |
download | FreeBSD-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.c | 129 |
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: |