KVM method support for procstat_getgroups, procstat_getumask,

procstat_getrlimit, and procstat_getosrel.

MFC after:	3 weeks
This commit is contained in:
Mikolaj Golub 2013-05-01 15:01:05 +00:00
parent 1b8388cde9
commit 1f84c47e42
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=250146

View File

@ -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);
@ -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: