Move sysctl routines from init_sysctl.c to kern_descrip.c (for
descriptors) and kern_proc.c (for processes). This makes them usable in a rump kernel, in case somebody was wondering.
This commit is contained in:
parent
0199e732f8
commit
dd7a40671a
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: init_main.c,v 1.426 2011/01/18 08:18:43 matt Exp $ */
|
||||
/* $NetBSD: init_main.c,v 1.427 2011/01/28 18:44:44 pooka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
|
||||
|
@ -97,7 +97,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.426 2011/01/18 08:18:43 matt Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: init_main.c,v 1.427 2011/01/28 18:44:44 pooka Exp $");
|
||||
|
||||
#include "opt_ddb.h"
|
||||
#include "opt_ipsec.h"
|
||||
|
@ -584,6 +584,8 @@ main(void)
|
|||
|
||||
machdep_init();
|
||||
|
||||
procinit_sysctl();
|
||||
|
||||
/*
|
||||
* Create process 1 (init(8)). We do this now, as Unix has
|
||||
* historically had init be process 1, and changing this would
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: kern_descrip.c,v 1.209 2011/01/01 22:05:11 pooka Exp $ */
|
||||
/* $NetBSD: kern_descrip.c,v 1.210 2011/01/28 18:44:44 pooka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2008, 2009 The NetBSD Foundation, Inc.
|
||||
|
@ -70,7 +70,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_descrip.c,v 1.209 2011/01/01 22:05:11 pooka Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_descrip.c,v 1.210 2011/01/28 18:44:44 pooka Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
|
@ -94,6 +94,8 @@ __KERNEL_RCSID(0, "$NetBSD: kern_descrip.c,v 1.209 2011/01/01 22:05:11 pooka Exp
|
|||
#include <sys/cpu.h>
|
||||
#include <sys/kmem.h>
|
||||
#include <sys/vnode.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/ktrace.h>
|
||||
|
||||
static int file_ctor(void *, void *, int);
|
||||
static void file_dtor(void *, void *);
|
||||
|
@ -103,6 +105,11 @@ static int filedesc_ctor(void *, void *, int);
|
|||
static void filedesc_dtor(void *, void *);
|
||||
static int filedescopen(dev_t, int, int, lwp_t *);
|
||||
|
||||
static int sysctl_kern_file(SYSCTLFN_PROTO);
|
||||
static int sysctl_kern_file2(SYSCTLFN_PROTO);
|
||||
static void fill_file(struct kinfo_file *, const file_t *, const fdfile_t *,
|
||||
int, pid_t);
|
||||
|
||||
kmutex_t filelist_lock; /* lock on filehead */
|
||||
struct filelist filehead; /* head of list of open files */
|
||||
u_int nfiles; /* actual number of open files */
|
||||
|
@ -126,6 +133,7 @@ __strong_alias(fd_putsock,fd_putfile)
|
|||
void
|
||||
fd_sys_init(void)
|
||||
{
|
||||
static struct sysctllog *clog;
|
||||
|
||||
mutex_init(&filelist_lock, MUTEX_DEFAULT, IPL_NONE);
|
||||
|
||||
|
@ -142,6 +150,22 @@ fd_sys_init(void)
|
|||
0, 0, "filedesc", NULL, IPL_NONE, filedesc_ctor, filedesc_dtor,
|
||||
NULL);
|
||||
KASSERT(filedesc_cache != NULL);
|
||||
|
||||
sysctl_createv(&clog, 0, NULL, NULL,
|
||||
CTLFLAG_PERMANENT, CTLTYPE_NODE, "kern", NULL,
|
||||
NULL, 0, NULL, 0, CTL_KERN, CTL_EOL);
|
||||
sysctl_createv(&clog, 0, NULL, NULL,
|
||||
CTLFLAG_PERMANENT,
|
||||
CTLTYPE_STRUCT, "file",
|
||||
SYSCTL_DESCR("System open file table"),
|
||||
sysctl_kern_file, 0, NULL, 0,
|
||||
CTL_KERN, KERN_FILE, CTL_EOL);
|
||||
sysctl_createv(&clog, 0, NULL, NULL,
|
||||
CTLFLAG_PERMANENT,
|
||||
CTLTYPE_STRUCT, "file2",
|
||||
SYSCTL_DESCR("System open file table"),
|
||||
sysctl_kern_file2, 0, NULL, 0,
|
||||
CTL_KERN, KERN_FILE2, CTL_EOL);
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -1841,3 +1865,387 @@ fbadop_close(file_t *fp)
|
|||
|
||||
return EOPNOTSUPP;
|
||||
}
|
||||
|
||||
/*
|
||||
* sysctl routines pertaining to file descriptors
|
||||
*/
|
||||
|
||||
/* Initialized in sysctl_init() for now... */
|
||||
extern kmutex_t sysctl_file_marker_lock;
|
||||
static u_int sysctl_file_marker = 1;
|
||||
|
||||
/*
|
||||
* Expects to be called with proc_lock and sysctl_file_marker_lock locked.
|
||||
*/
|
||||
static void
|
||||
sysctl_file_marker_reset(void)
|
||||
{
|
||||
struct proc *p;
|
||||
|
||||
PROCLIST_FOREACH(p, &allproc) {
|
||||
struct filedesc *fd = p->p_fd;
|
||||
fdtab_t *dt;
|
||||
u_int i;
|
||||
|
||||
mutex_enter(&fd->fd_lock);
|
||||
|
||||
dt = fd->fd_dt;
|
||||
for (i = 0; i < dt->dt_nfiles; i++) {
|
||||
struct file *fp;
|
||||
fdfile_t *ff;
|
||||
|
||||
if ((ff = dt->dt_ff[i]) == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((fp = ff->ff_file) == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
fp->f_marker = 0;
|
||||
}
|
||||
|
||||
mutex_exit(&fd->fd_lock);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* sysctl helper routine for kern.file pseudo-subtree.
|
||||
*/
|
||||
static int
|
||||
sysctl_kern_file(SYSCTLFN_ARGS)
|
||||
{
|
||||
int error;
|
||||
size_t buflen;
|
||||
struct file *fp, fbuf;
|
||||
char *start, *where;
|
||||
struct proc *p;
|
||||
|
||||
start = where = oldp;
|
||||
buflen = *oldlenp;
|
||||
|
||||
if (where == NULL) {
|
||||
/*
|
||||
* overestimate by 10 files
|
||||
*/
|
||||
*oldlenp = sizeof(filehead) + (nfiles + 10) *
|
||||
sizeof(struct file);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* first sysctl_copyout filehead
|
||||
*/
|
||||
if (buflen < sizeof(filehead)) {
|
||||
*oldlenp = 0;
|
||||
return (0);
|
||||
}
|
||||
sysctl_unlock();
|
||||
error = sysctl_copyout(l, &filehead, where, sizeof(filehead));
|
||||
if (error) {
|
||||
sysctl_relock();
|
||||
return error;
|
||||
}
|
||||
buflen -= sizeof(filehead);
|
||||
where += sizeof(filehead);
|
||||
|
||||
/*
|
||||
* followed by an array of file structures
|
||||
*/
|
||||
mutex_enter(&sysctl_file_marker_lock);
|
||||
mutex_enter(proc_lock);
|
||||
PROCLIST_FOREACH(p, &allproc) {
|
||||
struct filedesc *fd;
|
||||
fdtab_t *dt;
|
||||
u_int i;
|
||||
|
||||
if (p->p_stat == SIDL) {
|
||||
/* skip embryonic processes */
|
||||
continue;
|
||||
}
|
||||
mutex_enter(p->p_lock);
|
||||
error = kauth_authorize_process(l->l_cred,
|
||||
KAUTH_PROCESS_CANSEE, p,
|
||||
KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_OPENFILES),
|
||||
NULL, NULL);
|
||||
mutex_exit(p->p_lock);
|
||||
if (error != 0) {
|
||||
/*
|
||||
* Don't leak kauth retval if we're silently
|
||||
* skipping this entry.
|
||||
*/
|
||||
error = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Grab a hold on the process.
|
||||
*/
|
||||
if (!rw_tryenter(&p->p_reflock, RW_READER)) {
|
||||
continue;
|
||||
}
|
||||
mutex_exit(proc_lock);
|
||||
|
||||
fd = p->p_fd;
|
||||
mutex_enter(&fd->fd_lock);
|
||||
dt = fd->fd_dt;
|
||||
for (i = 0; i < dt->dt_nfiles; i++) {
|
||||
fdfile_t *ff;
|
||||
|
||||
if ((ff = dt->dt_ff[i]) == NULL) {
|
||||
continue;
|
||||
}
|
||||
if ((fp = ff->ff_file) == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
mutex_enter(&fp->f_lock);
|
||||
|
||||
if ((fp->f_count == 0) ||
|
||||
(fp->f_marker == sysctl_file_marker)) {
|
||||
mutex_exit(&fp->f_lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Check that we have enough space. */
|
||||
if (buflen < sizeof(struct file)) {
|
||||
*oldlenp = where - start;
|
||||
mutex_exit(&fp->f_lock);
|
||||
error = ENOMEM;
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(&fbuf, fp, sizeof(fbuf));
|
||||
mutex_exit(&fp->f_lock);
|
||||
error = sysctl_copyout(l, &fbuf, where, sizeof(fbuf));
|
||||
if (error) {
|
||||
break;
|
||||
}
|
||||
buflen -= sizeof(struct file);
|
||||
where += sizeof(struct file);
|
||||
|
||||
fp->f_marker = sysctl_file_marker;
|
||||
}
|
||||
mutex_exit(&fd->fd_lock);
|
||||
|
||||
/*
|
||||
* Release reference to process.
|
||||
*/
|
||||
mutex_enter(proc_lock);
|
||||
rw_exit(&p->p_reflock);
|
||||
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
|
||||
sysctl_file_marker++;
|
||||
/* Reset all markers if wrapped. */
|
||||
if (sysctl_file_marker == 0) {
|
||||
sysctl_file_marker_reset();
|
||||
sysctl_file_marker++;
|
||||
}
|
||||
|
||||
mutex_exit(proc_lock);
|
||||
mutex_exit(&sysctl_file_marker_lock);
|
||||
|
||||
*oldlenp = where - start;
|
||||
sysctl_relock();
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* sysctl helper function for kern.file2
|
||||
*/
|
||||
static int
|
||||
sysctl_kern_file2(SYSCTLFN_ARGS)
|
||||
{
|
||||
struct proc *p;
|
||||
struct file *fp;
|
||||
struct filedesc *fd;
|
||||
struct kinfo_file kf;
|
||||
char *dp;
|
||||
u_int i, op;
|
||||
size_t len, needed, elem_size, out_size;
|
||||
int error, arg, elem_count;
|
||||
fdfile_t *ff;
|
||||
fdtab_t *dt;
|
||||
|
||||
if (namelen == 1 && name[0] == CTL_QUERY)
|
||||
return (sysctl_query(SYSCTLFN_CALL(rnode)));
|
||||
|
||||
if (namelen != 4)
|
||||
return (EINVAL);
|
||||
|
||||
error = 0;
|
||||
dp = oldp;
|
||||
len = (oldp != NULL) ? *oldlenp : 0;
|
||||
op = name[0];
|
||||
arg = name[1];
|
||||
elem_size = name[2];
|
||||
elem_count = name[3];
|
||||
out_size = MIN(sizeof(kf), elem_size);
|
||||
needed = 0;
|
||||
|
||||
if (elem_size < 1 || elem_count < 0)
|
||||
return (EINVAL);
|
||||
|
||||
switch (op) {
|
||||
case KERN_FILE_BYFILE:
|
||||
case KERN_FILE_BYPID:
|
||||
/*
|
||||
* We're traversing the process list in both cases; the BYFILE
|
||||
* case does additional work of keeping track of files already
|
||||
* looked at.
|
||||
*/
|
||||
|
||||
/* doesn't use arg so it must be zero */
|
||||
if ((op == KERN_FILE_BYFILE) && (arg != 0))
|
||||
return EINVAL;
|
||||
|
||||
if ((op == KERN_FILE_BYPID) && (arg < -1))
|
||||
/* -1 means all processes */
|
||||
return (EINVAL);
|
||||
|
||||
sysctl_unlock();
|
||||
if (op == KERN_FILE_BYFILE)
|
||||
mutex_enter(&sysctl_file_marker_lock);
|
||||
mutex_enter(proc_lock);
|
||||
PROCLIST_FOREACH(p, &allproc) {
|
||||
if (p->p_stat == SIDL) {
|
||||
/* skip embryonic processes */
|
||||
continue;
|
||||
}
|
||||
if (arg > 0 && p->p_pid != arg) {
|
||||
/* pick only the one we want */
|
||||
/* XXX want 0 to mean "kernel files" */
|
||||
continue;
|
||||
}
|
||||
mutex_enter(p->p_lock);
|
||||
error = kauth_authorize_process(l->l_cred,
|
||||
KAUTH_PROCESS_CANSEE, p,
|
||||
KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_OPENFILES),
|
||||
NULL, NULL);
|
||||
mutex_exit(p->p_lock);
|
||||
if (error != 0) {
|
||||
/*
|
||||
* Don't leak kauth retval if we're silently
|
||||
* skipping this entry.
|
||||
*/
|
||||
error = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Grab a hold on the process.
|
||||
*/
|
||||
if (!rw_tryenter(&p->p_reflock, RW_READER)) {
|
||||
continue;
|
||||
}
|
||||
mutex_exit(proc_lock);
|
||||
|
||||
fd = p->p_fd;
|
||||
mutex_enter(&fd->fd_lock);
|
||||
dt = fd->fd_dt;
|
||||
for (i = 0; i < dt->dt_nfiles; i++) {
|
||||
if ((ff = dt->dt_ff[i]) == NULL) {
|
||||
continue;
|
||||
}
|
||||
if ((fp = ff->ff_file) == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((op == KERN_FILE_BYFILE) &&
|
||||
(fp->f_marker == sysctl_file_marker)) {
|
||||
continue;
|
||||
}
|
||||
if (len >= elem_size && elem_count > 0) {
|
||||
mutex_enter(&fp->f_lock);
|
||||
fill_file(&kf, fp, ff, i, p->p_pid);
|
||||
mutex_exit(&fp->f_lock);
|
||||
mutex_exit(&fd->fd_lock);
|
||||
error = sysctl_copyout(l,
|
||||
&kf, dp, out_size);
|
||||
mutex_enter(&fd->fd_lock);
|
||||
if (error)
|
||||
break;
|
||||
dp += elem_size;
|
||||
len -= elem_size;
|
||||
}
|
||||
if (op == KERN_FILE_BYFILE)
|
||||
fp->f_marker = sysctl_file_marker;
|
||||
needed += elem_size;
|
||||
if (elem_count > 0 && elem_count != INT_MAX)
|
||||
elem_count--;
|
||||
}
|
||||
mutex_exit(&fd->fd_lock);
|
||||
|
||||
/*
|
||||
* Release reference to process.
|
||||
*/
|
||||
mutex_enter(proc_lock);
|
||||
rw_exit(&p->p_reflock);
|
||||
}
|
||||
if (op == KERN_FILE_BYFILE) {
|
||||
sysctl_file_marker++;
|
||||
|
||||
/* Reset all markers if wrapped. */
|
||||
if (sysctl_file_marker == 0) {
|
||||
sysctl_file_marker_reset();
|
||||
sysctl_file_marker++;
|
||||
}
|
||||
}
|
||||
mutex_exit(proc_lock);
|
||||
if (op == KERN_FILE_BYFILE)
|
||||
mutex_exit(&sysctl_file_marker_lock);
|
||||
sysctl_relock();
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
if (oldp == NULL)
|
||||
needed += KERN_FILESLOP * elem_size;
|
||||
*oldlenp = needed;
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static void
|
||||
fill_file(struct kinfo_file *kp, const file_t *fp, const fdfile_t *ff,
|
||||
int i, pid_t pid)
|
||||
{
|
||||
|
||||
memset(kp, 0, sizeof(*kp));
|
||||
|
||||
kp->ki_fileaddr = PTRTOUINT64(fp);
|
||||
kp->ki_flag = fp->f_flag;
|
||||
kp->ki_iflags = 0;
|
||||
kp->ki_ftype = fp->f_type;
|
||||
kp->ki_count = fp->f_count;
|
||||
kp->ki_msgcount = fp->f_msgcount;
|
||||
kp->ki_fucred = PTRTOUINT64(fp->f_cred);
|
||||
kp->ki_fuid = kauth_cred_geteuid(fp->f_cred);
|
||||
kp->ki_fgid = kauth_cred_getegid(fp->f_cred);
|
||||
kp->ki_fops = PTRTOUINT64(fp->f_ops);
|
||||
kp->ki_foffset = fp->f_offset;
|
||||
kp->ki_fdata = PTRTOUINT64(fp->f_data);
|
||||
|
||||
/* vnode information to glue this file to something */
|
||||
if (fp->f_type == DTYPE_VNODE) {
|
||||
struct vnode *vp = (struct vnode *)fp->f_data;
|
||||
|
||||
kp->ki_vun = PTRTOUINT64(vp->v_un.vu_socket);
|
||||
kp->ki_vsize = vp->v_size;
|
||||
kp->ki_vtype = vp->v_type;
|
||||
kp->ki_vtag = vp->v_tag;
|
||||
kp->ki_vdata = PTRTOUINT64(vp->v_data);
|
||||
}
|
||||
|
||||
/* process information when retrieved via KERN_FILE_BYPID */
|
||||
if (ff != NULL) {
|
||||
kp->ki_pid = pid;
|
||||
kp->ki_fd = i;
|
||||
kp->ki_ofileflags = ff->ff_exclose;
|
||||
kp->ki_usecount = ff->ff_refcnt;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: kern_proc.c,v 1.169 2011/01/17 07:13:31 uebayasi Exp $ */
|
||||
/* $NetBSD: kern_proc.c,v 1.170 2011/01/28 18:44:44 pooka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 1999, 2006, 2007, 2008 The NetBSD Foundation, Inc.
|
||||
|
@ -62,7 +62,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.169 2011/01/17 07:13:31 uebayasi Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.170 2011/01/28 18:44:44 pooka Exp $");
|
||||
|
||||
#ifdef _KERNEL_OPT
|
||||
#include "opt_kstack.h"
|
||||
|
@ -97,6 +97,9 @@ __KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.169 2011/01/17 07:13:31 uebayasi Exp
|
|||
#include <sys/atomic.h>
|
||||
#include <sys/kmem.h>
|
||||
#include <sys/dtrace_bsd.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <sys/exec.h>
|
||||
#include <sys/cpu.h>
|
||||
|
||||
#include <uvm/uvm_extern.h>
|
||||
#include <uvm/uvm_extern.h>
|
||||
|
@ -199,6 +202,10 @@ int cmask = CMASK;
|
|||
MALLOC_DEFINE(M_EMULDATA, "emuldata", "Per-process emulation data");
|
||||
MALLOC_DEFINE(M_SUBPROC, "subproc", "Proc sub-structures");
|
||||
|
||||
static int sysctl_doeproc(SYSCTLFN_PROTO);
|
||||
static int sysctl_kern_proc_args(SYSCTLFN_PROTO);
|
||||
static void fill_kproc2(struct proc *, struct kinfo_proc2 *, bool);
|
||||
|
||||
/*
|
||||
* The process list descriptors, used during pid allocation and
|
||||
* by sysctl. No locking on this data structure is needed since
|
||||
|
@ -335,6 +342,53 @@ procinit(void)
|
|||
proc_listener_cb, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
procinit_sysctl(void)
|
||||
{
|
||||
static struct sysctllog *clog;
|
||||
|
||||
sysctl_createv(&clog, 0, NULL, NULL,
|
||||
CTLFLAG_PERMANENT,
|
||||
CTLTYPE_NODE, "kern", NULL,
|
||||
NULL, 0, NULL, 0,
|
||||
CTL_KERN, CTL_EOL);
|
||||
|
||||
sysctl_createv(&clog, 0, NULL, NULL,
|
||||
CTLFLAG_PERMANENT,
|
||||
CTLTYPE_NODE, "proc",
|
||||
SYSCTL_DESCR("System-wide process information"),
|
||||
sysctl_doeproc, 0, NULL, 0,
|
||||
CTL_KERN, KERN_PROC, CTL_EOL);
|
||||
sysctl_createv(&clog, 0, NULL, NULL,
|
||||
CTLFLAG_PERMANENT,
|
||||
CTLTYPE_NODE, "proc2",
|
||||
SYSCTL_DESCR("Machine-independent process information"),
|
||||
sysctl_doeproc, 0, NULL, 0,
|
||||
CTL_KERN, KERN_PROC2, CTL_EOL);
|
||||
sysctl_createv(&clog, 0, NULL, NULL,
|
||||
CTLFLAG_PERMANENT,
|
||||
CTLTYPE_NODE, "proc_args",
|
||||
SYSCTL_DESCR("Process argument information"),
|
||||
sysctl_kern_proc_args, 0, NULL, 0,
|
||||
CTL_KERN, KERN_PROC_ARGS, CTL_EOL);
|
||||
|
||||
/*
|
||||
"nodes" under these:
|
||||
|
||||
KERN_PROC_ALL
|
||||
KERN_PROC_PID pid
|
||||
KERN_PROC_PGRP pgrp
|
||||
KERN_PROC_SESSION sess
|
||||
KERN_PROC_TTY tty
|
||||
KERN_PROC_UID uid
|
||||
KERN_PROC_RUID uid
|
||||
KERN_PROC_GID gid
|
||||
KERN_PROC_RGID gid
|
||||
|
||||
all in all, probably not worth the effort...
|
||||
*/
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize process 0.
|
||||
*/
|
||||
|
@ -1456,3 +1510,821 @@ proc_uidmatch(kauth_cred_t cred, kauth_cred_t target)
|
|||
|
||||
return (r);
|
||||
}
|
||||
|
||||
/*
|
||||
* sysctl stuff
|
||||
*/
|
||||
|
||||
#define KERN_PROCSLOP (5 * sizeof(struct kinfo_proc))
|
||||
|
||||
static const u_int sysctl_flagmap[] = {
|
||||
PK_ADVLOCK, P_ADVLOCK,
|
||||
PK_EXEC, P_EXEC,
|
||||
PK_NOCLDWAIT, P_NOCLDWAIT,
|
||||
PK_32, P_32,
|
||||
PK_CLDSIGIGN, P_CLDSIGIGN,
|
||||
PK_SUGID, P_SUGID,
|
||||
0
|
||||
};
|
||||
|
||||
static const u_int sysctl_sflagmap[] = {
|
||||
PS_NOCLDSTOP, P_NOCLDSTOP,
|
||||
PS_WEXIT, P_WEXIT,
|
||||
PS_STOPFORK, P_STOPFORK,
|
||||
PS_STOPEXEC, P_STOPEXEC,
|
||||
PS_STOPEXIT, P_STOPEXIT,
|
||||
0
|
||||
};
|
||||
|
||||
static const u_int sysctl_slflagmap[] = {
|
||||
PSL_TRACED, P_TRACED,
|
||||
PSL_FSTRACE, P_FSTRACE,
|
||||
PSL_CHTRACED, P_CHTRACED,
|
||||
PSL_SYSCALL, P_SYSCALL,
|
||||
0
|
||||
};
|
||||
|
||||
static const u_int sysctl_lflagmap[] = {
|
||||
PL_CONTROLT, P_CONTROLT,
|
||||
PL_PPWAIT, P_PPWAIT,
|
||||
0
|
||||
};
|
||||
|
||||
static const u_int sysctl_stflagmap[] = {
|
||||
PST_PROFIL, P_PROFIL,
|
||||
0
|
||||
|
||||
};
|
||||
|
||||
/* used by kern_lwp also */
|
||||
const u_int sysctl_lwpflagmap[] = {
|
||||
LW_SINTR, L_SINTR,
|
||||
LW_SYSTEM, L_SYSTEM,
|
||||
LW_SA, L_SA, /* WRS ??? */
|
||||
0
|
||||
};
|
||||
|
||||
/*
|
||||
* Find the most ``active'' lwp of a process and return it for ps display
|
||||
* purposes
|
||||
*/
|
||||
static struct lwp *
|
||||
proc_active_lwp(struct proc *p)
|
||||
{
|
||||
static const int ostat[] = {
|
||||
0,
|
||||
2, /* LSIDL */
|
||||
6, /* LSRUN */
|
||||
5, /* LSSLEEP */
|
||||
4, /* LSSTOP */
|
||||
0, /* LSZOMB */
|
||||
1, /* LSDEAD */
|
||||
7, /* LSONPROC */
|
||||
3 /* LSSUSPENDED */
|
||||
};
|
||||
|
||||
struct lwp *l, *lp = NULL;
|
||||
LIST_FOREACH(l, &p->p_lwps, l_sibling) {
|
||||
KASSERT(l->l_stat >= 0 && l->l_stat < __arraycount(ostat));
|
||||
if (lp == NULL ||
|
||||
ostat[l->l_stat] > ostat[lp->l_stat] ||
|
||||
(ostat[l->l_stat] == ostat[lp->l_stat] &&
|
||||
l->l_cpticks > lp->l_cpticks)) {
|
||||
lp = l;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
return lp;
|
||||
}
|
||||
|
||||
static int
|
||||
sysctl_doeproc(SYSCTLFN_ARGS)
|
||||
{
|
||||
union {
|
||||
struct kinfo_proc kproc;
|
||||
struct kinfo_proc2 kproc2;
|
||||
} *kbuf;
|
||||
struct proc *p, *next, *marker;
|
||||
char *where, *dp;
|
||||
int type, op, arg, error;
|
||||
u_int elem_size, kelem_size, elem_count;
|
||||
size_t buflen, needed;
|
||||
bool match, zombie, mmmbrains;
|
||||
|
||||
if (namelen == 1 && name[0] == CTL_QUERY)
|
||||
return (sysctl_query(SYSCTLFN_CALL(rnode)));
|
||||
|
||||
dp = where = oldp;
|
||||
buflen = where != NULL ? *oldlenp : 0;
|
||||
error = 0;
|
||||
needed = 0;
|
||||
type = rnode->sysctl_num;
|
||||
|
||||
if (type == KERN_PROC) {
|
||||
if (namelen != 2 && !(namelen == 1 && name[0] == KERN_PROC_ALL))
|
||||
return (EINVAL);
|
||||
op = name[0];
|
||||
if (op != KERN_PROC_ALL)
|
||||
arg = name[1];
|
||||
else
|
||||
arg = 0; /* Quell compiler warning */
|
||||
elem_count = 0; /* Ditto */
|
||||
kelem_size = elem_size = sizeof(kbuf->kproc);
|
||||
} else {
|
||||
if (namelen != 4)
|
||||
return (EINVAL);
|
||||
op = name[0];
|
||||
arg = name[1];
|
||||
elem_size = name[2];
|
||||
elem_count = name[3];
|
||||
kelem_size = sizeof(kbuf->kproc2);
|
||||
}
|
||||
|
||||
sysctl_unlock();
|
||||
|
||||
kbuf = kmem_alloc(sizeof(*kbuf), KM_SLEEP);
|
||||
marker = kmem_alloc(sizeof(*marker), KM_SLEEP);
|
||||
marker->p_flag = PK_MARKER;
|
||||
|
||||
mutex_enter(proc_lock);
|
||||
mmmbrains = false;
|
||||
for (p = LIST_FIRST(&allproc);; p = next) {
|
||||
if (p == NULL) {
|
||||
if (!mmmbrains) {
|
||||
p = LIST_FIRST(&zombproc);
|
||||
mmmbrains = true;
|
||||
}
|
||||
if (p == NULL)
|
||||
break;
|
||||
}
|
||||
next = LIST_NEXT(p, p_list);
|
||||
if ((p->p_flag & PK_MARKER) != 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Skip embryonic processes.
|
||||
*/
|
||||
if (p->p_stat == SIDL)
|
||||
continue;
|
||||
|
||||
mutex_enter(p->p_lock);
|
||||
error = kauth_authorize_process(l->l_cred,
|
||||
KAUTH_PROCESS_CANSEE, p,
|
||||
KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL);
|
||||
if (error != 0) {
|
||||
mutex_exit(p->p_lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* TODO - make more efficient (see notes below).
|
||||
* do by session.
|
||||
*/
|
||||
switch (op) {
|
||||
case KERN_PROC_PID:
|
||||
/* could do this with just a lookup */
|
||||
match = (p->p_pid == (pid_t)arg);
|
||||
break;
|
||||
|
||||
case KERN_PROC_PGRP:
|
||||
/* could do this by traversing pgrp */
|
||||
match = (p->p_pgrp->pg_id == (pid_t)arg);
|
||||
break;
|
||||
|
||||
case KERN_PROC_SESSION:
|
||||
match = (p->p_session->s_sid == (pid_t)arg);
|
||||
break;
|
||||
|
||||
case KERN_PROC_TTY:
|
||||
match = true;
|
||||
if (arg == (int) KERN_PROC_TTY_REVOKE) {
|
||||
if ((p->p_lflag & PL_CONTROLT) == 0 ||
|
||||
p->p_session->s_ttyp == NULL ||
|
||||
p->p_session->s_ttyvp != NULL) {
|
||||
match = false;
|
||||
}
|
||||
} else if ((p->p_lflag & PL_CONTROLT) == 0 ||
|
||||
p->p_session->s_ttyp == NULL) {
|
||||
if ((dev_t)arg != KERN_PROC_TTY_NODEV) {
|
||||
match = false;
|
||||
}
|
||||
} else if (p->p_session->s_ttyp->t_dev != (dev_t)arg) {
|
||||
match = false;
|
||||
}
|
||||
break;
|
||||
|
||||
case KERN_PROC_UID:
|
||||
match = (kauth_cred_geteuid(p->p_cred) == (uid_t)arg);
|
||||
break;
|
||||
|
||||
case KERN_PROC_RUID:
|
||||
match = (kauth_cred_getuid(p->p_cred) == (uid_t)arg);
|
||||
break;
|
||||
|
||||
case KERN_PROC_GID:
|
||||
match = (kauth_cred_getegid(p->p_cred) == (uid_t)arg);
|
||||
break;
|
||||
|
||||
case KERN_PROC_RGID:
|
||||
match = (kauth_cred_getgid(p->p_cred) == (uid_t)arg);
|
||||
break;
|
||||
|
||||
case KERN_PROC_ALL:
|
||||
match = true;
|
||||
/* allow everything */
|
||||
break;
|
||||
|
||||
default:
|
||||
error = EINVAL;
|
||||
mutex_exit(p->p_lock);
|
||||
goto cleanup;
|
||||
}
|
||||
if (!match) {
|
||||
mutex_exit(p->p_lock);
|
||||
continue;
|
||||
}
|
||||
|
||||
/*
|
||||
* Grab a hold on the process.
|
||||
*/
|
||||
if (mmmbrains) {
|
||||
zombie = true;
|
||||
} else {
|
||||
zombie = !rw_tryenter(&p->p_reflock, RW_READER);
|
||||
}
|
||||
if (zombie) {
|
||||
LIST_INSERT_AFTER(p, marker, p_list);
|
||||
}
|
||||
|
||||
if (buflen >= elem_size &&
|
||||
(type == KERN_PROC || elem_count > 0)) {
|
||||
if (type == KERN_PROC) {
|
||||
kbuf->kproc.kp_proc = *p;
|
||||
fill_eproc(p, &kbuf->kproc.kp_eproc, zombie);
|
||||
} else {
|
||||
fill_kproc2(p, &kbuf->kproc2, zombie);
|
||||
elem_count--;
|
||||
}
|
||||
mutex_exit(p->p_lock);
|
||||
mutex_exit(proc_lock);
|
||||
/*
|
||||
* Copy out elem_size, but not larger than kelem_size
|
||||
*/
|
||||
error = sysctl_copyout(l, kbuf, dp,
|
||||
min(kelem_size, elem_size));
|
||||
mutex_enter(proc_lock);
|
||||
if (error) {
|
||||
goto bah;
|
||||
}
|
||||
dp += elem_size;
|
||||
buflen -= elem_size;
|
||||
} else {
|
||||
mutex_exit(p->p_lock);
|
||||
}
|
||||
needed += elem_size;
|
||||
|
||||
/*
|
||||
* Release reference to process.
|
||||
*/
|
||||
if (zombie) {
|
||||
next = LIST_NEXT(marker, p_list);
|
||||
LIST_REMOVE(marker, p_list);
|
||||
} else {
|
||||
rw_exit(&p->p_reflock);
|
||||
next = LIST_NEXT(p, p_list);
|
||||
}
|
||||
}
|
||||
mutex_exit(proc_lock);
|
||||
|
||||
if (where != NULL) {
|
||||
*oldlenp = dp - where;
|
||||
if (needed > *oldlenp) {
|
||||
error = ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
needed += KERN_PROCSLOP;
|
||||
*oldlenp = needed;
|
||||
}
|
||||
if (kbuf)
|
||||
kmem_free(kbuf, sizeof(*kbuf));
|
||||
if (marker)
|
||||
kmem_free(marker, sizeof(*marker));
|
||||
sysctl_relock();
|
||||
return 0;
|
||||
bah:
|
||||
if (zombie)
|
||||
LIST_REMOVE(marker, p_list);
|
||||
else
|
||||
rw_exit(&p->p_reflock);
|
||||
cleanup:
|
||||
mutex_exit(proc_lock);
|
||||
out:
|
||||
if (kbuf)
|
||||
kmem_free(kbuf, sizeof(*kbuf));
|
||||
if (marker)
|
||||
kmem_free(marker, sizeof(*marker));
|
||||
sysctl_relock();
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* sysctl helper routine for kern.proc_args pseudo-subtree.
|
||||
*/
|
||||
static int
|
||||
sysctl_kern_proc_args(SYSCTLFN_ARGS)
|
||||
{
|
||||
struct ps_strings pss;
|
||||
struct proc *p;
|
||||
size_t len, i;
|
||||
struct uio auio;
|
||||
struct iovec aiov;
|
||||
pid_t pid;
|
||||
int nargv, type, error, argvlen;
|
||||
char *arg;
|
||||
char **argv = NULL;
|
||||
char *tmp;
|
||||
struct vmspace *vmspace;
|
||||
vaddr_t psstr_addr;
|
||||
vaddr_t offsetn;
|
||||
vaddr_t offsetv;
|
||||
|
||||
if (namelen == 1 && name[0] == CTL_QUERY)
|
||||
return (sysctl_query(SYSCTLFN_CALL(rnode)));
|
||||
|
||||
if (newp != NULL || namelen != 2)
|
||||
return (EINVAL);
|
||||
pid = name[0];
|
||||
type = name[1];
|
||||
argv = NULL;
|
||||
argvlen = 0;
|
||||
|
||||
switch (type) {
|
||||
case KERN_PROC_ARGV:
|
||||
case KERN_PROC_NARGV:
|
||||
case KERN_PROC_ENV:
|
||||
case KERN_PROC_NENV:
|
||||
/* ok */
|
||||
break;
|
||||
default:
|
||||
return (EINVAL);
|
||||
}
|
||||
|
||||
sysctl_unlock();
|
||||
|
||||
/* check pid */
|
||||
mutex_enter(proc_lock);
|
||||
if ((p = proc_find(pid)) == NULL) {
|
||||
error = EINVAL;
|
||||
goto out_locked;
|
||||
}
|
||||
mutex_enter(p->p_lock);
|
||||
|
||||
/* Check permission. */
|
||||
if (type == KERN_PROC_ARGV || type == KERN_PROC_NARGV)
|
||||
error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE,
|
||||
p, KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ARGS), NULL, NULL);
|
||||
else if (type == KERN_PROC_ENV || type == KERN_PROC_NENV)
|
||||
error = kauth_authorize_process(l->l_cred, KAUTH_PROCESS_CANSEE,
|
||||
p, KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENV), NULL, NULL);
|
||||
else
|
||||
error = EINVAL; /* XXXGCC */
|
||||
if (error) {
|
||||
mutex_exit(p->p_lock);
|
||||
goto out_locked;
|
||||
}
|
||||
|
||||
if (oldp == NULL) {
|
||||
if (type == KERN_PROC_NARGV || type == KERN_PROC_NENV)
|
||||
*oldlenp = sizeof (int);
|
||||
else
|
||||
*oldlenp = ARG_MAX; /* XXX XXX XXX */
|
||||
error = 0;
|
||||
mutex_exit(p->p_lock);
|
||||
goto out_locked;
|
||||
}
|
||||
|
||||
/*
|
||||
* Zombies don't have a stack, so we can't read their psstrings.
|
||||
* System processes also don't have a user stack.
|
||||
*/
|
||||
if (P_ZOMBIE(p) || (p->p_flag & PK_SYSTEM) != 0) {
|
||||
error = EINVAL;
|
||||
mutex_exit(p->p_lock);
|
||||
goto out_locked;
|
||||
}
|
||||
|
||||
/*
|
||||
* Lock the process down in memory.
|
||||
*/
|
||||
psstr_addr = (vaddr_t)p->p_psstr;
|
||||
if (type == KERN_PROC_ARGV || type == KERN_PROC_NARGV) {
|
||||
offsetn = p->p_psnargv;
|
||||
offsetv = p->p_psargv;
|
||||
} else {
|
||||
offsetn = p->p_psnenv;
|
||||
offsetv = p->p_psenv;
|
||||
}
|
||||
vmspace = p->p_vmspace;
|
||||
uvmspace_addref(vmspace);
|
||||
mutex_exit(p->p_lock);
|
||||
mutex_exit(proc_lock);
|
||||
|
||||
/*
|
||||
* Allocate a temporary buffer to hold the arguments.
|
||||
*/
|
||||
arg = kmem_alloc(PAGE_SIZE, KM_SLEEP);
|
||||
|
||||
/*
|
||||
* Read in the ps_strings structure.
|
||||
*/
|
||||
aiov.iov_base = &pss;
|
||||
aiov.iov_len = sizeof(pss);
|
||||
auio.uio_iov = &aiov;
|
||||
auio.uio_iovcnt = 1;
|
||||
auio.uio_offset = psstr_addr;
|
||||
auio.uio_resid = sizeof(pss);
|
||||
auio.uio_rw = UIO_READ;
|
||||
UIO_SETUP_SYSSPACE(&auio);
|
||||
error = uvm_io(&vmspace->vm_map, &auio);
|
||||
if (error)
|
||||
goto done;
|
||||
|
||||
memcpy(&nargv, (char *)&pss + offsetn, sizeof(nargv));
|
||||
if (type == KERN_PROC_NARGV || type == KERN_PROC_NENV) {
|
||||
error = sysctl_copyout(l, &nargv, oldp, sizeof(nargv));
|
||||
*oldlenp = sizeof(nargv);
|
||||
goto done;
|
||||
}
|
||||
/*
|
||||
* Now read the address of the argument vector.
|
||||
*/
|
||||
switch (type) {
|
||||
case KERN_PROC_ARGV:
|
||||
/* FALLTHROUGH */
|
||||
case KERN_PROC_ENV:
|
||||
memcpy(&tmp, (char *)&pss + offsetv, sizeof(tmp));
|
||||
break;
|
||||
default:
|
||||
error = EINVAL;
|
||||
goto done;
|
||||
}
|
||||
|
||||
#ifdef COMPAT_NETBSD32
|
||||
if (p->p_flag & PK_32)
|
||||
len = sizeof(netbsd32_charp) * nargv;
|
||||
else
|
||||
#endif
|
||||
len = sizeof(char *) * nargv;
|
||||
|
||||
if ((argvlen = len) != 0)
|
||||
argv = kmem_alloc(len, KM_SLEEP);
|
||||
|
||||
aiov.iov_base = argv;
|
||||
aiov.iov_len = len;
|
||||
auio.uio_iov = &aiov;
|
||||
auio.uio_iovcnt = 1;
|
||||
auio.uio_offset = (off_t)(unsigned long)tmp;
|
||||
auio.uio_resid = len;
|
||||
auio.uio_rw = UIO_READ;
|
||||
UIO_SETUP_SYSSPACE(&auio);
|
||||
error = uvm_io(&vmspace->vm_map, &auio);
|
||||
if (error)
|
||||
goto done;
|
||||
|
||||
/*
|
||||
* Now copy each string.
|
||||
*/
|
||||
len = 0; /* bytes written to user buffer */
|
||||
for (i = 0; i < nargv; i++) {
|
||||
int finished = 0;
|
||||
vaddr_t base;
|
||||
size_t xlen;
|
||||
int j;
|
||||
|
||||
#ifdef COMPAT_NETBSD32
|
||||
if (p->p_flag & PK_32) {
|
||||
netbsd32_charp *argv32;
|
||||
|
||||
argv32 = (netbsd32_charp *)argv;
|
||||
base = (vaddr_t)NETBSD32PTR64(argv32[i]);
|
||||
} else
|
||||
#endif
|
||||
base = (vaddr_t)argv[i];
|
||||
|
||||
/*
|
||||
* The program has messed around with its arguments,
|
||||
* possibly deleting some, and replacing them with
|
||||
* NULL's. Treat this as the last argument and not
|
||||
* a failure.
|
||||
*/
|
||||
if (base == 0)
|
||||
break;
|
||||
|
||||
while (!finished) {
|
||||
xlen = PAGE_SIZE - (base & PAGE_MASK);
|
||||
|
||||
aiov.iov_base = arg;
|
||||
aiov.iov_len = PAGE_SIZE;
|
||||
auio.uio_iov = &aiov;
|
||||
auio.uio_iovcnt = 1;
|
||||
auio.uio_offset = base;
|
||||
auio.uio_resid = xlen;
|
||||
auio.uio_rw = UIO_READ;
|
||||
UIO_SETUP_SYSSPACE(&auio);
|
||||
error = uvm_io(&vmspace->vm_map, &auio);
|
||||
if (error)
|
||||
goto done;
|
||||
|
||||
/* Look for the end of the string */
|
||||
for (j = 0; j < xlen; j++) {
|
||||
if (arg[j] == '\0') {
|
||||
xlen = j + 1;
|
||||
finished = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for user buffer overflow */
|
||||
if (len + xlen > *oldlenp) {
|
||||
finished = 1;
|
||||
if (len > *oldlenp)
|
||||
xlen = 0;
|
||||
else
|
||||
xlen = *oldlenp - len;
|
||||
}
|
||||
|
||||
/* Copyout the page */
|
||||
error = sysctl_copyout(l, arg, (char*)oldp + len, xlen);
|
||||
if (error)
|
||||
goto done;
|
||||
|
||||
len += xlen;
|
||||
base += xlen;
|
||||
}
|
||||
}
|
||||
*oldlenp = len;
|
||||
|
||||
done:
|
||||
if (argvlen != 0)
|
||||
kmem_free(argv, argvlen);
|
||||
uvmspace_free(vmspace);
|
||||
kmem_free(arg, PAGE_SIZE);
|
||||
sysctl_relock();
|
||||
return error;
|
||||
|
||||
out_locked:
|
||||
mutex_exit(proc_lock);
|
||||
sysctl_relock();
|
||||
return error;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in an eproc structure for the specified process.
|
||||
*/
|
||||
void
|
||||
fill_eproc(struct proc *p, struct eproc *ep, bool zombie)
|
||||
{
|
||||
struct tty *tp;
|
||||
struct lwp *l;
|
||||
|
||||
KASSERT(mutex_owned(proc_lock));
|
||||
KASSERT(mutex_owned(p->p_lock));
|
||||
|
||||
memset(ep, 0, sizeof(*ep));
|
||||
|
||||
ep->e_paddr = p;
|
||||
ep->e_sess = p->p_session;
|
||||
if (p->p_cred) {
|
||||
kauth_cred_topcred(p->p_cred, &ep->e_pcred);
|
||||
kauth_cred_toucred(p->p_cred, &ep->e_ucred);
|
||||
}
|
||||
if (p->p_stat != SIDL && !P_ZOMBIE(p) && !zombie) {
|
||||
struct vmspace *vm = p->p_vmspace;
|
||||
|
||||
ep->e_vm.vm_rssize = vm_resident_count(vm);
|
||||
ep->e_vm.vm_tsize = vm->vm_tsize;
|
||||
ep->e_vm.vm_dsize = vm->vm_dsize;
|
||||
ep->e_vm.vm_ssize = vm->vm_ssize;
|
||||
ep->e_vm.vm_map.size = vm->vm_map.size;
|
||||
|
||||
/* Pick the primary (first) LWP */
|
||||
l = proc_active_lwp(p);
|
||||
KASSERT(l != NULL);
|
||||
lwp_lock(l);
|
||||
if (l->l_wchan)
|
||||
strncpy(ep->e_wmesg, l->l_wmesg, WMESGLEN);
|
||||
lwp_unlock(l);
|
||||
}
|
||||
if (p->p_pptr)
|
||||
ep->e_ppid = p->p_pptr->p_pid;
|
||||
if (p->p_pgrp && p->p_session) {
|
||||
ep->e_pgid = p->p_pgrp->pg_id;
|
||||
ep->e_jobc = p->p_pgrp->pg_jobc;
|
||||
ep->e_sid = p->p_session->s_sid;
|
||||
if ((p->p_lflag & PL_CONTROLT) &&
|
||||
(tp = ep->e_sess->s_ttyp)) {
|
||||
ep->e_tdev = tp->t_dev;
|
||||
ep->e_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PGID;
|
||||
ep->e_tsess = tp->t_session;
|
||||
} else
|
||||
ep->e_tdev = (uint32_t)NODEV;
|
||||
ep->e_flag = ep->e_sess->s_ttyvp ? EPROC_CTTY : 0;
|
||||
if (SESS_LEADER(p))
|
||||
ep->e_flag |= EPROC_SLEADER;
|
||||
strncpy(ep->e_login, ep->e_sess->s_login, MAXLOGNAME);
|
||||
}
|
||||
ep->e_xsize = ep->e_xrssize = 0;
|
||||
ep->e_xccount = ep->e_xswrss = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Fill in a kinfo_proc2 structure for the specified process.
|
||||
*/
|
||||
static void
|
||||
fill_kproc2(struct proc *p, struct kinfo_proc2 *ki, bool zombie)
|
||||
{
|
||||
struct tty *tp;
|
||||
struct lwp *l, *l2;
|
||||
struct timeval ut, st, rt;
|
||||
sigset_t ss1, ss2;
|
||||
struct rusage ru;
|
||||
struct vmspace *vm;
|
||||
|
||||
KASSERT(mutex_owned(proc_lock));
|
||||
KASSERT(mutex_owned(p->p_lock));
|
||||
|
||||
sigemptyset(&ss1);
|
||||
sigemptyset(&ss2);
|
||||
memset(ki, 0, sizeof(*ki));
|
||||
|
||||
ki->p_paddr = PTRTOUINT64(p);
|
||||
ki->p_fd = PTRTOUINT64(p->p_fd);
|
||||
ki->p_cwdi = PTRTOUINT64(p->p_cwdi);
|
||||
ki->p_stats = PTRTOUINT64(p->p_stats);
|
||||
ki->p_limit = PTRTOUINT64(p->p_limit);
|
||||
ki->p_vmspace = PTRTOUINT64(p->p_vmspace);
|
||||
ki->p_sigacts = PTRTOUINT64(p->p_sigacts);
|
||||
ki->p_sess = PTRTOUINT64(p->p_session);
|
||||
ki->p_tsess = 0; /* may be changed if controlling tty below */
|
||||
ki->p_ru = PTRTOUINT64(&p->p_stats->p_ru);
|
||||
ki->p_eflag = 0;
|
||||
ki->p_exitsig = p->p_exitsig;
|
||||
ki->p_flag = L_INMEM; /* Process never swapped out */
|
||||
ki->p_flag |= sysctl_map_flags(sysctl_flagmap, p->p_flag);
|
||||
ki->p_flag |= sysctl_map_flags(sysctl_sflagmap, p->p_sflag);
|
||||
ki->p_flag |= sysctl_map_flags(sysctl_slflagmap, p->p_slflag);
|
||||
ki->p_flag |= sysctl_map_flags(sysctl_lflagmap, p->p_lflag);
|
||||
ki->p_flag |= sysctl_map_flags(sysctl_stflagmap, p->p_stflag);
|
||||
ki->p_pid = p->p_pid;
|
||||
if (p->p_pptr)
|
||||
ki->p_ppid = p->p_pptr->p_pid;
|
||||
else
|
||||
ki->p_ppid = 0;
|
||||
ki->p_uid = kauth_cred_geteuid(p->p_cred);
|
||||
ki->p_ruid = kauth_cred_getuid(p->p_cred);
|
||||
ki->p_gid = kauth_cred_getegid(p->p_cred);
|
||||
ki->p_rgid = kauth_cred_getgid(p->p_cred);
|
||||
ki->p_svuid = kauth_cred_getsvuid(p->p_cred);
|
||||
ki->p_svgid = kauth_cred_getsvgid(p->p_cred);
|
||||
ki->p_ngroups = kauth_cred_ngroups(p->p_cred);
|
||||
kauth_cred_getgroups(p->p_cred, ki->p_groups,
|
||||
min(ki->p_ngroups, sizeof(ki->p_groups) / sizeof(ki->p_groups[0])),
|
||||
UIO_SYSSPACE);
|
||||
|
||||
ki->p_uticks = p->p_uticks;
|
||||
ki->p_sticks = p->p_sticks;
|
||||
ki->p_iticks = p->p_iticks;
|
||||
ki->p_tpgid = NO_PGID; /* may be changed if controlling tty below */
|
||||
ki->p_tracep = PTRTOUINT64(p->p_tracep);
|
||||
ki->p_traceflag = p->p_traceflag;
|
||||
|
||||
memcpy(&ki->p_sigignore, &p->p_sigctx.ps_sigignore,sizeof(ki_sigset_t));
|
||||
memcpy(&ki->p_sigcatch, &p->p_sigctx.ps_sigcatch, sizeof(ki_sigset_t));
|
||||
|
||||
ki->p_cpticks = 0;
|
||||
ki->p_pctcpu = p->p_pctcpu;
|
||||
ki->p_estcpu = 0;
|
||||
ki->p_stat = p->p_stat; /* Will likely be overridden by LWP status */
|
||||
ki->p_realstat = p->p_stat;
|
||||
ki->p_nice = p->p_nice;
|
||||
ki->p_xstat = p->p_xstat;
|
||||
ki->p_acflag = p->p_acflag;
|
||||
|
||||
strncpy(ki->p_comm, p->p_comm,
|
||||
min(sizeof(ki->p_comm), sizeof(p->p_comm)));
|
||||
strncpy(ki->p_ename, p->p_emul->e_name, sizeof(ki->p_ename));
|
||||
|
||||
ki->p_nlwps = p->p_nlwps;
|
||||
ki->p_realflag = ki->p_flag;
|
||||
|
||||
if (p->p_stat != SIDL && !P_ZOMBIE(p) && !zombie) {
|
||||
vm = p->p_vmspace;
|
||||
ki->p_vm_rssize = vm_resident_count(vm);
|
||||
ki->p_vm_tsize = vm->vm_tsize;
|
||||
ki->p_vm_dsize = vm->vm_dsize;
|
||||
ki->p_vm_ssize = vm->vm_ssize;
|
||||
ki->p_vm_vsize = vm->vm_map.size;
|
||||
/*
|
||||
* Since the stack is initially mapped mostly with
|
||||
* PROT_NONE and grown as needed, adjust the "mapped size"
|
||||
* to skip the unused stack portion.
|
||||
*/
|
||||
ki->p_vm_msize =
|
||||
atop(vm->vm_map.size) - vm->vm_issize + vm->vm_ssize;
|
||||
|
||||
/* Pick the primary (first) LWP */
|
||||
l = proc_active_lwp(p);
|
||||
KASSERT(l != NULL);
|
||||
lwp_lock(l);
|
||||
ki->p_nrlwps = p->p_nrlwps;
|
||||
ki->p_forw = 0;
|
||||
ki->p_back = 0;
|
||||
ki->p_addr = PTRTOUINT64(l->l_addr);
|
||||
ki->p_stat = l->l_stat;
|
||||
ki->p_flag |= sysctl_map_flags(sysctl_lwpflagmap, l->l_flag);
|
||||
ki->p_swtime = l->l_swtime;
|
||||
ki->p_slptime = l->l_slptime;
|
||||
if (l->l_stat == LSONPROC)
|
||||
ki->p_schedflags = l->l_cpu->ci_schedstate.spc_flags;
|
||||
else
|
||||
ki->p_schedflags = 0;
|
||||
ki->p_priority = lwp_eprio(l);
|
||||
ki->p_usrpri = l->l_priority;
|
||||
if (l->l_wchan)
|
||||
strncpy(ki->p_wmesg, l->l_wmesg, sizeof(ki->p_wmesg));
|
||||
ki->p_wchan = PTRTOUINT64(l->l_wchan);
|
||||
ki->p_cpuid = cpu_index(l->l_cpu);
|
||||
lwp_unlock(l);
|
||||
LIST_FOREACH(l, &p->p_lwps, l_sibling) {
|
||||
/* This is hardly correct, but... */
|
||||
sigplusset(&l->l_sigpend.sp_set, &ss1);
|
||||
sigplusset(&l->l_sigmask, &ss2);
|
||||
ki->p_cpticks += l->l_cpticks;
|
||||
ki->p_pctcpu += l->l_pctcpu;
|
||||
ki->p_estcpu += l->l_estcpu;
|
||||
}
|
||||
}
|
||||
sigplusset(&p->p_sigpend.sp_set, &ss2);
|
||||
memcpy(&ki->p_siglist, &ss1, sizeof(ki_sigset_t));
|
||||
memcpy(&ki->p_sigmask, &ss2, sizeof(ki_sigset_t));
|
||||
|
||||
if (p->p_session != NULL) {
|
||||
ki->p_sid = p->p_session->s_sid;
|
||||
ki->p__pgid = p->p_pgrp->pg_id;
|
||||
if (p->p_session->s_ttyvp)
|
||||
ki->p_eflag |= EPROC_CTTY;
|
||||
if (SESS_LEADER(p))
|
||||
ki->p_eflag |= EPROC_SLEADER;
|
||||
strncpy(ki->p_login, p->p_session->s_login,
|
||||
min(sizeof ki->p_login - 1, sizeof p->p_session->s_login));
|
||||
ki->p_jobc = p->p_pgrp->pg_jobc;
|
||||
if ((p->p_lflag & PL_CONTROLT) && (tp = p->p_session->s_ttyp)) {
|
||||
ki->p_tdev = tp->t_dev;
|
||||
ki->p_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PGID;
|
||||
ki->p_tsess = PTRTOUINT64(tp->t_session);
|
||||
} else {
|
||||
ki->p_tdev = (int32_t)NODEV;
|
||||
}
|
||||
}
|
||||
|
||||
if (!P_ZOMBIE(p) && !zombie) {
|
||||
ki->p_uvalid = 1;
|
||||
ki->p_ustart_sec = p->p_stats->p_start.tv_sec;
|
||||
ki->p_ustart_usec = p->p_stats->p_start.tv_usec;
|
||||
|
||||
calcru(p, &ut, &st, NULL, &rt);
|
||||
ki->p_rtime_sec = rt.tv_sec;
|
||||
ki->p_rtime_usec = rt.tv_usec;
|
||||
ki->p_uutime_sec = ut.tv_sec;
|
||||
ki->p_uutime_usec = ut.tv_usec;
|
||||
ki->p_ustime_sec = st.tv_sec;
|
||||
ki->p_ustime_usec = st.tv_usec;
|
||||
|
||||
memcpy(&ru, &p->p_stats->p_ru, sizeof(ru));
|
||||
ki->p_uru_nvcsw = 0;
|
||||
ki->p_uru_nivcsw = 0;
|
||||
LIST_FOREACH(l2, &p->p_lwps, l_sibling) {
|
||||
ki->p_uru_nvcsw += (l2->l_ncsw - l2->l_nivcsw);
|
||||
ki->p_uru_nivcsw += l2->l_nivcsw;
|
||||
ruadd(&ru, &l2->l_ru);
|
||||
}
|
||||
ki->p_uru_maxrss = ru.ru_maxrss;
|
||||
ki->p_uru_ixrss = ru.ru_ixrss;
|
||||
ki->p_uru_idrss = ru.ru_idrss;
|
||||
ki->p_uru_isrss = ru.ru_isrss;
|
||||
ki->p_uru_minflt = ru.ru_minflt;
|
||||
ki->p_uru_majflt = ru.ru_majflt;
|
||||
ki->p_uru_nswap = ru.ru_nswap;
|
||||
ki->p_uru_inblock = ru.ru_inblock;
|
||||
ki->p_uru_oublock = ru.ru_oublock;
|
||||
ki->p_uru_msgsnd = ru.ru_msgsnd;
|
||||
ki->p_uru_msgrcv = ru.ru_msgrcv;
|
||||
ki->p_uru_nsignals = ru.ru_nsignals;
|
||||
|
||||
timeradd(&p->p_stats->p_cru.ru_utime,
|
||||
&p->p_stats->p_cru.ru_stime, &ut);
|
||||
ki->p_uctime_sec = ut.tv_sec;
|
||||
ki->p_uctime_usec = ut.tv_usec;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: kern_sysctl.c,v 1.229 2010/04/11 01:50:25 mrg Exp $ */
|
||||
/* $NetBSD: kern_sysctl.c,v 1.230 2011/01/28 18:44:44 pooka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2003, 2007, 2008 The NetBSD Foundation, Inc.
|
||||
|
@ -68,7 +68,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_sysctl.c,v 1.229 2010/04/11 01:50:25 mrg Exp $");
|
||||
__KERNEL_RCSID(0, "$NetBSD: kern_sysctl.c,v 1.230 2011/01/28 18:44:44 pooka Exp $");
|
||||
|
||||
#include "opt_defcorename.h"
|
||||
#include "ksyms.h"
|
||||
|
@ -167,7 +167,7 @@ char defcorename[MAXPATHLEN] = DEFCORENAME;
|
|||
* stop caring about who's calling us and simplify some code a bunch.
|
||||
* ********************************************************************
|
||||
*/
|
||||
static inline int
|
||||
int
|
||||
sysctl_copyin(struct lwp *l, const void *uaddr, void *kaddr, size_t len)
|
||||
{
|
||||
int error;
|
||||
|
@ -182,7 +182,7 @@ sysctl_copyin(struct lwp *l, const void *uaddr, void *kaddr, size_t len)
|
|||
return error;
|
||||
}
|
||||
|
||||
static inline int
|
||||
int
|
||||
sysctl_copyout(struct lwp *l, const void *kaddr, void *uaddr, size_t len)
|
||||
{
|
||||
int error;
|
||||
|
@ -197,7 +197,7 @@ sysctl_copyout(struct lwp *l, const void *kaddr, void *uaddr, size_t len)
|
|||
return error;
|
||||
}
|
||||
|
||||
static inline int
|
||||
int
|
||||
sysctl_copyinstr(struct lwp *l, const void *uaddr, void *kaddr,
|
||||
size_t len, size_t *done)
|
||||
{
|
||||
|
@ -2581,6 +2581,18 @@ sysctl_null(SYSCTLFN_ARGS)
|
|||
return (0);
|
||||
}
|
||||
|
||||
u_int
|
||||
sysctl_map_flags(const u_int *map, u_int word)
|
||||
{
|
||||
u_int rv;
|
||||
|
||||
for (rv = 0; *map != 0; map += 2)
|
||||
if ((word & map[0]) != 0)
|
||||
rv |= map[1];
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/*
|
||||
* ********************************************************************
|
||||
* Section 5: The machinery that makes it all go
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: proc.h,v 1.299 2011/01/14 02:06:34 rmind Exp $ */
|
||||
/* $NetBSD: proc.h,v 1.300 2011/01/28 18:44:45 pooka Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
|
||||
|
@ -463,6 +463,7 @@ proc_t * proc_find(pid_t); /* Find process by ID */
|
|||
struct pgrp * pgrp_find(pid_t); /* Find process group by ID */
|
||||
|
||||
void procinit(void);
|
||||
void procinit_sysctl(void);
|
||||
int proc_enterpgrp(struct proc *, pid_t, pid_t, bool);
|
||||
void proc_leavepgrp(struct proc *);
|
||||
void proc_sesshold(struct session *);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: sysctl.h,v 1.190 2011/01/22 20:54:44 christos Exp $ */
|
||||
/* $NetBSD: sysctl.h,v 1.191 2011/01/28 18:44:45 pooka Exp $ */
|
||||
|
||||
/*
|
||||
* Copyright (c) 1989, 1993
|
||||
|
@ -1181,9 +1181,17 @@ int sysctl_needfunc(SYSCTLFN_PROTO);
|
|||
int sysctl_notavail(SYSCTLFN_PROTO);
|
||||
int sysctl_null(SYSCTLFN_PROTO);
|
||||
|
||||
int sysctl_copyin(struct lwp *, const void *, void *, size_t);
|
||||
int sysctl_copyout(struct lwp *, const void *, void *, size_t);
|
||||
int sysctl_copyinstr(struct lwp *, const void *, void *, size_t, size_t *);
|
||||
|
||||
u_int sysctl_map_flags(const u_int *, u_int);
|
||||
|
||||
MALLOC_DECLARE(M_SYSCTLNODE);
|
||||
MALLOC_DECLARE(M_SYSCTLDATA);
|
||||
|
||||
extern const u_int sysctl_lwpflagmap[];
|
||||
|
||||
#else /* !_KERNEL */
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
|
|
Loading…
Reference in New Issue