diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c index a54b90d93bb3..535cdfce39dc 100644 --- a/lib/libprocstat/libprocstat.c +++ b/lib/libprocstat/libprocstat.c @@ -39,6 +39,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#define _WANT_UCRED +#include +#undef _WANT_UCRED #include #include #include @@ -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); @@ -1789,6 +1803,46 @@ procstat_freevmmap(struct procstat *procstat __unused, free(vmmap); } +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) { @@ -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: @@ -1853,6 +1906,24 @@ procstat_freegroups(struct procstat *procstat __unused, gid_t *groups) free(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) { @@ -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: @@ -1907,6 +1977,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) { @@ -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: @@ -2031,6 +2128,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) { @@ -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: