61 #include <sys/cdefs.h>
64 #include "opt_procdesc.h"
66 #include <sys/param.h>
67 #include <sys/capability.h>
68 #include <sys/fcntl.h>
70 #include <sys/filedesc.h>
71 #include <sys/kernel.h>
73 #include <sys/mutex.h>
76 #include <sys/procdesc.h>
77 #include <sys/resourcevar.h>
79 #include <sys/sysproto.h>
80 #include <sys/sysctl.h>
81 #include <sys/systm.h>
82 #include <sys/ucred.h>
84 #include <security/audit/audit.h>
90 FEATURE(process_descriptors,
"Process Descriptors");
92 static uma_zone_t procdesc_zone;
94 static fo_rdwr_t procdesc_read;
95 static fo_rdwr_t procdesc_write;
96 static fo_truncate_t procdesc_truncate;
97 static fo_ioctl_t procdesc_ioctl;
98 static fo_poll_t procdesc_poll;
99 static fo_kqfilter_t procdesc_kqfilter;
100 static fo_stat_t procdesc_stat;
101 static fo_close_t procdesc_close;
102 static fo_chmod_t procdesc_chmod;
103 static fo_chown_t procdesc_chown;
105 static struct fileops procdesc_ops = {
106 .fo_read = procdesc_read,
107 .fo_write = procdesc_write,
108 .fo_truncate = procdesc_truncate,
109 .fo_ioctl = procdesc_ioctl,
110 .fo_poll = procdesc_poll,
111 .fo_kqfilter = procdesc_kqfilter,
112 .fo_stat = procdesc_stat,
113 .fo_close = procdesc_close,
114 .fo_chmod = procdesc_chmod,
115 .fo_chown = procdesc_chown,
116 .fo_flags = DFLAG_PASSABLE,
125 procdesc_init(
void *
dummy __unused)
128 procdesc_zone = uma_zcreate(
"procdesc",
sizeof(
struct procdesc),
129 NULL, NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
130 if (procdesc_zone == NULL)
131 panic(
"procdesc_init: procdesc_zone not initialized");
133 SYSINIT(vfs, SI_SUB_VFS, SI_ORDER_ANY, procdesc_init, NULL);
140 procdesc_find(
struct thread *td,
int fd, cap_rights_t rights,
147 error =
fget(td, fd, rights, &fp);
150 if (fp->f_type != DTYPE_PROCDESC) {
156 if (pd->pd_proc != NULL) {
172 procdesc_pid(
struct file *fp_procdesc)
176 KASSERT(fp_procdesc->f_type == DTYPE_PROCDESC,
177 (
"procdesc_pid: !procdesc"));
179 pd = fp_procdesc->f_data;
187 kern_pdgetpid(
struct thread *td,
int fd, cap_rights_t rights, pid_t *pidp)
192 error =
fget(td, fd, rights, &fp);
195 if (fp->f_type != DTYPE_PROCDESC) {
199 *pidp = procdesc_pid(fp);
209 sys_pdgetpid(
struct thread *td,
struct pdgetpid_args *uap)
214 AUDIT_ARG_FD(uap->fd);
215 error = kern_pdgetpid(td, uap->fd, CAP_PDGETPID, &pid);
217 error = copyout(&pid, uap->pidp,
sizeof(pid));
228 procdesc_new(
struct proc *p,
int flags)
232 pd = uma_zalloc(procdesc_zone, M_WAITOK | M_ZERO);
234 pd->pd_pid = p->p_pid;
237 if (flags & PD_DAEMON)
238 pd->pd_flags |= PDF_DAEMON;
239 PROCDESC_LOCK_INIT(pd);
245 refcount_init(&pd->pd_refcount, 2);
252 procdesc_finit(
struct procdesc *pdp,
struct file *fp)
255 finit(fp, FREAD | FWRITE, DTYPE_PROCDESC, pdp, &procdesc_ops);
259 procdesc_free(
struct procdesc *pd)
268 if (refcount_release(&pd->pd_refcount)) {
269 KASSERT(pd->pd_proc == NULL,
270 (
"procdesc_free: pd_proc != NULL"));
271 KASSERT((pd->pd_flags & PDF_CLOSED),
272 (
"procdesc_free: !PDF_CLOSED"));
274 PROCDESC_LOCK_DESTROY(pd);
275 uma_zfree(procdesc_zone, pd);
285 procdesc_exit(
struct proc *p)
290 PROC_LOCK_ASSERT(p, MA_OWNED);
291 KASSERT(p->p_procdesc != NULL, (
"procdesc_exit: p_procdesc NULL"));
296 KASSERT((pd->pd_flags & PDF_CLOSED) == 0 || p->p_pptr ==
initproc,
297 (
"procdesc_exit: closed && parent not init"));
299 pd->pd_flags |= PDF_EXITED;
307 if (pd->pd_flags & PDF_CLOSED) {
310 p->p_procdesc = NULL;
314 if (pd->pd_flags & PDF_SELECTED) {
315 pd->pd_flags &= ~PDF_SELECTED;
327 procdesc_reap(
struct proc *p)
332 KASSERT(p->p_procdesc != NULL, (
"procdesc_reap: p_procdesc == NULL"));
345 procdesc_close(
struct file *fp,
struct thread *td)
350 KASSERT(fp->f_type == DTYPE_PROCDESC, (
"procdesc_close: !procdesc"));
358 pd->pd_flags |= PDF_CLOSED;
362 if (p->p_state == PRS_ZOMBIE) {
380 p->p_procdesc = NULL;
387 p->p_sigparent = SIGCHLD;
389 if ((pd->pd_flags & PD_DAEMON) == 0)
403 procdesc_read(
struct file *fp,
struct uio *uio,
struct ucred *active_cred,
404 int flags,
struct thread *td)
411 procdesc_write(
struct file *fp,
struct uio *uio,
struct ucred *active_cred,
412 int flags,
struct thread *td)
419 procdesc_truncate(
struct file *fp, off_t length,
struct ucred *active_cred,
427 procdesc_ioctl(
struct file *fp, u_long com,
void *data,
428 struct ucred *active_cred,
struct thread *td)
435 procdesc_poll(
struct file *fp,
int events,
struct ucred *active_cred,
444 if (pd->pd_flags & PDF_EXITED)
448 pd->pd_flags |= PDF_SELECTED;
455 procdesc_kqfilter(
struct file *fp,
struct knote *kn)
462 procdesc_stat(
struct file *fp,
struct stat *sb,
struct ucred *active_cred,
466 struct timeval pstart;
473 bzero(sb,
sizeof(*sb));
476 if (pd->pd_proc != NULL) {
477 PROC_LOCK(pd->pd_proc);
480 pstart = pd->pd_proc->p_stats->p_start;
482 TIMEVAL_TO_TIMESPEC(&pstart, &sb->st_birthtim);
483 sb->st_atim = sb->st_birthtim;
484 sb->st_ctim = sb->st_birthtim;
485 sb->st_mtim = sb->st_birthtim;
486 if (pd->pd_proc->p_state != PRS_ZOMBIE)
487 sb->st_mode = S_IFREG | S_IRWXU;
489 sb->st_mode = S_IFREG;
490 sb->st_uid = pd->pd_proc->p_ucred->cr_ruid;
491 sb->st_gid = pd->pd_proc->p_ucred->cr_rgid;
492 PROC_UNLOCK(pd->pd_proc);
494 sb->st_mode = S_IFREG;
500 procdesc_chmod(
struct file *fp, mode_t
mode,
struct ucred *active_cred,
508 procdesc_chown(
struct file *fp, uid_t uid, gid_t gid,
struct ucred *active_cred,
void selwakeup(struct selinfo *sip)
void selrecord(struct thread *selector, struct selinfo *sip)
void panic(const char *fmt,...)
SYSINIT(placeholder, SI_SUB_DUMMY, SI_ORDER_ANY, NULL, NULL)
void knote(struct knlist *list, long hint, int lockflags)
void kern_psignal(struct proc *p, int sig)
int fget(struct thread *td, int fd, cap_rights_t rights, struct file **fpp)
void timevaladd(struct timeval *t1, const struct timeval *t2)
void proc_reap(struct thread *td, struct proc *p, int *status, int options)
void finit(struct file *fp, u_int flag, short type, void *data, struct fileops *ops)
int sys_pdgetpid(struct thread *td, struct pdgetpid_args *uap)
void proc_reparent(struct proc *child, struct proc *parent)
FEATURE(kdtrace_hooks,"Kernel DTrace hooks which are required to load DTrace kernel modules")
struct fileops badfileops