Date: Thu, 24 Dec 1998 17:34:02 +1030 (CST) From: Mark Newton <newton@atdot.dotat.org> To: FreeBSD-gnats-submit@FreeBSD.ORG Subject: kern/9183: enhancing the security provided by chroot(2) Message-ID: <199812240704.RAA00744@atdot.dotat.org>
next in thread | raw e-mail | index | archive | help
>Number: 9183 >Category: kern >Synopsis: chroot(2) can be broken by the superuser. this patch disables chroot() for processes which have already been chroot()'ed >Confidential: no >Severity: non-critical >Priority: low >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: change-request >Submitter-Id: current-users >Arrival-Date: Wed Dec 23 23:10:01 PST 1998 >Last-Modified: >Originator: Mark Newton >Organization: >Release: FreeBSD 3.0-RELEASE i386 >Environment: Any security-conscious site with a requirement to use chroot(). >Description: There are many techniques which can be used by a root user to break out of a "chroot()'ed" jail. Most of these techniques involve feeding a new directory into the chroot() call to set a process' root directory to something "outside" the jail, thereby allowing an attacker to access files outside the restricted area. Most of those techniques are rendered moot if the chroot() system call cannot be used by processes in the jail. This patch compares the root directory of processes which call chroot() against the root directory of PID 1. If they match, chroot() is permitted as per normal semantics. If they don't, chroot() will fail with EPERM. This breaks "traditional" chroot() semantics, so this patch implements the change under the control of a sysctl MIB variable called vfs.hard_chroot (to distinguish it from the normal "soft" chroot :-). If that variable is set to a non-zero value chroot will fail if it is used by "jailed" processes even if the caller is root. >How-To-Repeat: N/A >Fix: *** sys/kern/vfs_syscalls.c.981224 Thu Dec 24 17:01:07 1998 --- sys/kern/vfs_syscalls.c Thu Dec 24 17:08:24 1998 *************** *** 86,92 **** --- 86,99 ---- static int setutimes __P((struct proc *, struct vnode *, struct timeval *, int)); static int usermount = 0; /* if 1, non-root can mount fs. */ + /* + * hard_chroot - If 1, chroot() will fail with EPERM for any processes + * which are already chroot()ed. + */ + static int hard_chroot = 0; + SYSCTL_INT(_vfs, OID_AUTO, usermount, CTLFLAG_RW, &usermount, 0, ""); + SYSCTL_INT(_vfs, OID_AUTO, hard_chroot, CTLFLAG_RW, &hard_chroot, 0, ""); /* * Virtual File System System Calls *************** *** 831,836 **** --- 838,850 ---- register struct filedesc *fdp = p->p_fd; int error; struct nameidata nd; + register struct proc *init; + + if (hard_chroot) { + init = pfind((pid_t)1); /* locate init's proc structure */ + if (fdp->fd_rdir != init->p_fd->fd_rdir) + return(EPERM); + } error = suser(p->p_ucred, &p->p_acflag); if (error) *** lib/libc/sys/chroot.2.981224 Thu Dec 24 17:16:30 1998 --- lib/libc/sys/chroot.2 Thu Dec 24 17:23:15 1998 *************** *** 60,65 **** --- 60,73 ---- has no effect on the process's current directory. .Pp This call is restricted to the super-user. + .Sh MIB VARIABLES + .Fn chroot + observes the value of vfs.hard_chroot. A non-zero value in this variable + indicates that + .Fn chroot + should fail if the caller is already under the influence of a prior + .Fn chroot + operation. .Sh RETURN VALUES Upon successful completion, a value of 0 is returned. Otherwise, a value of -1 is returned and *************** *** 72,78 **** .It Bq Er ENOTDIR A component of the path name is not a directory. .It Bq Er EPERM ! The effective user ID is not the super-user. .It Bq Er ENAMETOOLONG A component of a pathname exceeded 255 characters, or an entire path name exceeded 1023 characters. --- 80,89 ---- .It Bq Er ENOTDIR A component of the path name is not a directory. .It Bq Er EPERM ! The effective user ID is not the super-user or vfs.hard_chroot is non-zero ! and the caller's root directory has been set by a previous ! .Fn chroot ! operation. .It Bq Er ENAMETOOLONG A component of a pathname exceeded 255 characters, or an entire path name exceeded 1023 characters. >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199812240704.RAA00744>