Skip site navigation (1)Skip section navigation (2)
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>