Module Name: src Committed By: christos Date: Thu Sep 24 14:33:01 UTC 2015
Modified Files: src/sys/kern: kern_proc.c Log Message: implementation of KERN_PROC_PATHNAME, some refactoring for KERN_PROC. To generate a diff of this commit: cvs rdiff -u -r1.193 -r1.194 src/sys/kern/kern_proc.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/kern/kern_proc.c diff -u src/sys/kern/kern_proc.c:1.193 src/sys/kern/kern_proc.c:1.194 --- src/sys/kern/kern_proc.c:1.193 Sat Jul 12 05:57:25 2014 +++ src/sys/kern/kern_proc.c Thu Sep 24 10:33:01 2015 @@ -1,4 +1,4 @@ -/* $NetBSD: kern_proc.c,v 1.193 2014/07/12 09:57:25 njoly Exp $ */ +/* $NetBSD: kern_proc.c,v 1.194 2015/09/24 14:33:01 christos 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.193 2014/07/12 09:57:25 njoly Exp $"); +__KERNEL_RCSID(0, "$NetBSD: kern_proc.c,v 1.194 2015/09/24 14:33:01 christos Exp $"); #ifdef _KERNEL_OPT #include "opt_kstack.h" @@ -95,12 +95,14 @@ __KERNEL_RCSID(0, "$NetBSD: kern_proc.c, #include <sys/sleepq.h> #include <sys/atomic.h> #include <sys/kmem.h> +#include <sys/namei.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.h> #ifdef COMPAT_NETBSD32 #include <compat/netbsd32/netbsd32.h> @@ -234,6 +236,8 @@ static pool_cache_t proc_cache; static kauth_listener_t proc_listener; +static int fill_pathname(struct lwp *, pid_t, void *, size_t *); + static int proc_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie, void *arg0, void *arg1, void *arg2, void *arg3) @@ -1633,18 +1637,25 @@ sysctl_doeproc(SYSCTLFN_ARGS) 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) + if (namelen == 0) + return EINVAL; + switch (op = name[0]) { + case KERN_PROC_ALL: + if (namelen != 1) + return EINVAL; + arg = 0; + break; + default: + if (namelen != 2) + return EINVAL; arg = name[1]; - else - arg = 0; /* Quell compiler warning */ + break; + } elem_count = 0; /* Ditto */ kelem_size = elem_size = sizeof(kbuf->kproc); } else { if (namelen != 4) - return (EINVAL); + return EINVAL; op = name[0]; arg = name[1]; elem_size = name[2]; @@ -1893,6 +1904,12 @@ sysctl_kern_proc_args(SYSCTLFN_ARGS) type = name[1]; switch (type) { + case KERN_PROC_PATHNAME: + sysctl_unlock(); + error = fill_pathname(l, pid, oldp, oldlenp); + sysctl_relock(); + return error; + case KERN_PROC_ARGV: case KERN_PROC_NARGV: case KERN_PROC_ENV: @@ -2386,3 +2403,74 @@ fill_kproc2(struct proc *p, struct kinfo ki->p_uctime_usec = ut.tv_usec; } } + + +int +proc_find_locked(struct lwp *l, struct proc **p, pid_t pid) +{ + int error; + + mutex_enter(proc_lock); + if (pid == -1) + *p = l->l_proc; + else + *p = proc_find(pid); + + if (*p == NULL) { + if (pid != -1) + mutex_exit(proc_lock); + return ESRCH; + } + if (pid != -1) + mutex_enter((*p)->p_lock); + mutex_exit(proc_lock); + + error = kauth_authorize_process(l->l_cred, + KAUTH_PROCESS_CANSEE, *p, + KAUTH_ARG(KAUTH_REQ_PROCESS_CANSEE_ENTRY), NULL, NULL); + if (error) { + if (pid != -1) + mutex_exit((*p)->p_lock); + } + return error; +} + +static int +fill_pathname(struct lwp *l, pid_t pid, void *oldp, size_t *oldlenp) +{ +#ifndef _RUMPKERNEL + int error; + struct proc *p; + char *path; + size_t len; + + if ((error = proc_find_locked(l, &p, pid)) != 0) + return error; + + if (p->p_textvp == NULL) { + if (pid != -1) + mutex_exit(p->p_lock); + return ENOENT; + } + + path = PNBUF_GET(); + error = vnode_to_path(path, MAXPATHLEN / 2, p->p_textvp, l, p); + if (error) + goto out; + + len = strlen(path) + 1; + if (oldp != NULL) { + error = sysctl_copyout(l, path, oldp, *oldlenp); + if (error == 0 && *oldlenp < len) + error = ENOSPC; + } + *oldlenp = len; +out: + PNBUF_PUT(path); + if (pid != -1) + mutex_exit(p->p_lock); + return error; +#else + return 0; +#endif +}