summaryrefslogtreecommitdiff
path: root/sys/kern/kern_sysctl.c
diff options
context:
space:
mode:
authorNicholas Marriott <nicm@cvs.openbsd.org>2011-12-09 16:14:55 +0000
committerNicholas Marriott <nicm@cvs.openbsd.org>2011-12-09 16:14:55 +0000
commitecfc9ea17f4367f9c343158f113414a32b6239cd (patch)
tree8f80a882323bda5043462fe0d91f4e31b2d1cc87 /sys/kern/kern_sysctl.c
parent44703bd43ff60c01ccd8eb65be09de5d9ec38672 (diff)
Add new KERN_PROC_CWD sysctl to get the current working directory of a process.
ok guenther deraadt
Diffstat (limited to 'sys/kern/kern_sysctl.c')
-rw-r--r--sys/kern/kern_sysctl.c68
1 files changed, 67 insertions, 1 deletions
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c
index 780a79da71c..4e964d0008c 100644
--- a/sys/kern/kern_sysctl.c
+++ b/sys/kern/kern_sysctl.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sysctl.c,v 1.208 2011/09/18 13:23:38 miod Exp $ */
+/* $OpenBSD: kern_sysctl.c,v 1.209 2011/12/09 16:14:54 nicm Exp $ */
/* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */
/*-
@@ -117,6 +117,7 @@ extern void nmbclust_update(void);
int sysctl_diskinit(int, struct proc *);
int sysctl_proc_args(int *, u_int, void *, size_t *, struct proc *);
+int sysctl_proc_cwd(int *, u_int, void *, size_t *, struct proc *);
int sysctl_intrcnt(int *, u_int, void *, size_t *);
int sysctl_sensors(int *, u_int, void *, size_t *, void *, size_t);
int sysctl_emul(int *, u_int, void *, size_t *, void *, size_t);
@@ -282,6 +283,7 @@ kern_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
case KERN_TTY:
case KERN_POOL:
case KERN_PROC_ARGS:
+ case KERN_PROC_CWD:
case KERN_SYSVIPC_INFO:
case KERN_SEMINFO:
case KERN_SHMINFO:
@@ -367,6 +369,9 @@ kern_sysctl(int *name, u_int namelen, void *oldp, size_t *oldlenp, void *newp,
case KERN_PROC_ARGS:
return (sysctl_proc_args(name + 1, namelen - 1, oldp, oldlenp,
p));
+ case KERN_PROC_CWD:
+ return (sysctl_proc_cwd(name + 1, namelen - 1, oldp, oldlenp,
+ p));
case KERN_FILE2:
return (sysctl_file2(name + 1, namelen - 1, oldp, oldlenp, p));
#endif
@@ -1719,6 +1724,67 @@ out:
return (error);
}
+int
+sysctl_proc_cwd(int *name, u_int namelen, void *oldp, size_t *oldlenp,
+ struct proc *cp)
+{
+ struct proc *findp;
+ pid_t pid;
+ int error;
+ size_t lenused, len;
+ char *path, *bp, *bend;
+
+ if (namelen > 1)
+ return (ENOTDIR);
+ if (namelen < 1)
+ return (EINVAL);
+
+ pid = name[0];
+ if ((findp = pfind(pid)) == NULL)
+ return (ESRCH);
+
+ if (oldp == NULL) {
+ *oldlenp = MAXPATHLEN * 4;
+ return (0);
+ }
+
+ if (P_ZOMBIE(findp) || (findp->p_flag & P_SYSTEM))
+ return (EINVAL);
+
+ /* Only owner or root can get cwd */
+ if (findp->p_ucred->cr_uid != cp->p_ucred->cr_uid &&
+ (error = suser(cp, 0)) != 0)
+ return (error);
+
+ /* Exiting - don't bother, it will be gone soon anyway */
+ if (findp->p_flag & P_WEXIT)
+ return (ESRCH);
+
+ len = *oldlenp;
+ if (len > MAXPATHLEN * 4)
+ len = MAXPATHLEN * 4;
+ else if (len < 2)
+ return (ERANGE);
+ *oldlenp = 0;
+
+ path = malloc(len, M_TEMP, M_WAITOK);
+
+ bp = &path[len];
+ bend = bp;
+ *(--bp) = '\0';
+
+ /* Same as sys__getcwd */
+ error = vfs_getcwd_common(findp->p_fd->fd_cdir, NULL,
+ &bp, path, len / 2, GETCWD_CHECK_ACCESS, cp);
+ if (error == 0) {
+ *oldlenp = lenused = bend - bp;
+ error = copyout(bp, oldp, lenused);
+ }
+
+ free(path, M_TEMP);
+
+ return (error);
+}
#endif
/*