summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_syscalls.c
diff options
context:
space:
mode:
authorphk <phk@FreeBSD.org>1999-03-23 14:26:40 +0000
committerphk <phk@FreeBSD.org>1999-03-23 14:26:40 +0000
commite1c9acedca824cb3a177d665495a51bcebd0763a (patch)
treee118eebefa3e4bc2de7c8493dee101fd9faa6490 /sys/kern/vfs_syscalls.c
parenta6cff8a40588e5200eaa3635409eaf799058be7d (diff)
downloadFreeBSD-src-e1c9acedca824cb3a177d665495a51bcebd0763a.zip
FreeBSD-src-e1c9acedca824cb3a177d665495a51bcebd0763a.tar.gz
Add a sysctl variable which can help stop chroot(2) escapes.
kern.chroot_allow_open_directories = 0 chroot(2) fails if there are open directories. kern.chroot_allow_open_directories = 1 (default) chroot(2) fails if there are open directories and the process is subject of a previous chroot(2). kern.chroot_allow_open_directories = anything else filedescriptors are not checked. (old behaviour). I'm very interested in reports about software which breaks when running with the default setting.
Diffstat (limited to 'sys/kern/vfs_syscalls.c')
-rw-r--r--sys/kern/vfs_syscalls.c46
1 files changed, 45 insertions, 1 deletions
diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c
index 54dc30c..e2c75c0 100644
--- a/sys/kern/vfs_syscalls.c
+++ b/sys/kern/vfs_syscalls.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)vfs_syscalls.c 8.13 (Berkeley) 4/15/94
- * $Id: vfs_syscalls.c,v 1.119 1999/02/27 07:06:05 julian Exp $
+ * $Id: vfs_syscalls.c,v 1.120 1999/03/03 02:35:51 julian Exp $
*/
/* For 4.3 integer FS ID compatibility */
@@ -71,6 +71,7 @@
static int change_dir __P((struct nameidata *ndp, struct proc *p));
static void checkdirs __P((struct vnode *olddp));
+static int chroot_refuse_vdir_fds __P((struct filedesc *fdp));
static int setfown __P((struct proc *, struct vnode *, uid_t, gid_t));
static int setfmode __P((struct proc *, struct vnode *, int));
static int setfflags __P((struct proc *, struct vnode *, int));
@@ -828,6 +829,44 @@ chdir(p, uap)
}
/*
+ * Helper function for raised chroot(2) security function: Refuse if
+ * any filedescriptors are open directories.
+ */
+static int
+chroot_refuse_vdir_fds(fdp)
+ struct filedesc *fdp;
+{
+ struct vnode *vp;
+ struct file *fp;
+ int error;
+ int fd;
+
+ for (fd = 0; fd < fdp->fd_nfiles ; fd++) {
+ error = getvnode(fdp, fd, &fp);
+ if (error)
+ continue;
+ vp = (struct vnode *)fp->f_data;
+ if (vp->v_type != VDIR)
+ continue;
+ return(EPERM);
+ }
+ return (0);
+}
+
+/*
+ * This sysctl determines if we will allow a process to chroot(2) if it
+ * has a directory open:
+ * 0: disallowed for all processes.
+ * 1: allowed for processes that were not already chroot(2)'ed.
+ * 2: allowed for all processes.
+ */
+
+static int chroot_allow_open_directories = 1;
+
+SYSCTL_INT(_kern, OID_AUTO, chroot_allow_open_directories, CTLFLAG_RW,
+ &chroot_allow_open_directories, 0, "");
+
+/*
* Change notion of root (``/'') directory.
*/
#ifndef _SYS_SYSPROTO_H_
@@ -850,6 +889,11 @@ chroot(p, uap)
error = suser(p->p_ucred, &p->p_acflag);
if (error)
return (error);
+ if (chroot_allow_open_directories == 0 ||
+ (chroot_allow_open_directories == 1 && fdp->fd_rdir != rootvnode))
+ error = chroot_refuse_vdir_fds(fdp);
+ if (error)
+ return (error);
NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF, UIO_USERSPACE,
SCARG(uap, path), p);
if ((error = change_dir(&nd, p)) != 0)
OpenPOWER on IntegriCloud