public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: Miloslav Semler <majkls@prepere.com>
To: Kyle Moffett <mrmacman_g4@mac.com>
Cc: David Newall <david@davidnewall.com>,
	Adrian Bunk <bunk@kernel.org>,
	Alan Cox <alan@lxorguk.ukuu.org.uk>,
	"Serge E. Hallyn" <serge@hallyn.com>,
	Bill Davidsen <davidsen@tmr.com>,
	Philipp Marek <philipp@marek.priv.at>,
	7eggert@gmx.de, bunk@fs.tum.de, linux-kernel@vger.kernel.org
Subject: Re: Chroot bug
Date: Wed, 26 Sep 2007 15:11:33 +0200	[thread overview]
Message-ID: <46FA5A85.20407@prepere.com> (raw)
In-Reply-To: <6BA6E9EE-B67B-4334-AC83-9B8E30527832@mac.com>

[-- Attachment #1: Type: text/plain, Size: 2407 bytes --]

Kyle Moffett napsal(a):
> On Sep 26, 2007, at 06:27:38, David Newall wrote:
>> Kyle Moffett wrote:
>>> David, please do tell myself and Adrian how "locking down" chroot() 
>>> the way you want will avoid letting root break out through any of 
>>> the above ways?
>>
>> As has been said, there are thousands of ways to break out of a 
>> chroot.  It's just that one of them should not be that chroot lets 
>> you walk out.  I can't explain it clearer than that.  If you don't 
>> see it now you probably never will.
>
> Let me put it this way:  You *CANNOT* enforce chroot() the way you 
> want to without a completely unacceptable performance penalty.  Let's 
> start with the simplest example of:
>
> fd = open("/", O_DIRECTORY);
> chroot("/foo");
> fchdir(fd);
> chroot(".");
>
> If you had ever actually looked at the Linux VFS, it is completely 
> *impossible* to tell whether "fd" at the time of the chroot is inside 
> or outside of "/foo" without tracking an enormous amount of extra state.
so there *is* solution. It is possible. I solved it. I have patch and it 
is working. So if you find some way how to break it I woud glad if you 
tell me it.
> Even then, any such determination may not be valid since an FD may be 
> opened to an inode which is hardlinked at multiple locations in the 
> directory tree.  It could also be bind-mounted at multiple locations, 
> or it may not even be mounted at all in this namespace (CDROM that was 
> lazy-unmounted).  That FD may be later passed over an open UNIX-domain 
> socket from another process.  Moreover, arbitrarily closing FDs would 
> break a huge number of programs.  Furthermore, since you can't fix the 
> "trivial" case of 'fchdir()', then there's no point in even 
> *attempting* to fix the "cwd is outside of chroot" problem, although 
> that is basically equivalent in difficulty to fixing the "dir-fd is 
> outside of chroot" problem.
>
> As for the nested-chroot() bit, the root user inside of a chroot is 
> always allowed to chroot().  This is necessary for test-suites for 
> various distro installers, chroot once to enter the installer playpen, 
> installer chroots again to configure the test-installed-system.  Once 
> you allow a second chroot, you're back at the "can't reliably and 
> efficiently track directory sub-tree members" problem.
>
> So if you think it can and should be fixed, then PROVIDE THE CODE.
Miloslav Semler

[-- Attachment #2: sys_chroot+sys_fchdir.patch --]
[-- Type: text/x-diff, Size: 3265 bytes --]

diff -Nrp linux-2.6.16.53/fs/namei.c linux-2.6.16.53-new/fs/namei.c
*** linux-2.6.16.53/fs/namei.c	2007-07-25 23:05:45.000000000 +0200
--- linux-2.6.16.53-new/fs/namei.c	2007-09-15 16:13:50.000000000 +0200
*************** static __always_inline void follow_dotdo
*** 728,733 ****
--- 728,772 ----
  	}
  	follow_mount(&nd->mnt, &nd->dentry);
  }
+ long directory_is_out(struct vfsmount *wdmnt, struct dentry *wdentry,
+ 		struct vfsmount *rootmnt, struct dentry *root)
+ {
+ 	struct nameidata oldentry, newentry;
+ 	long ret = 1;
+ 	
+         read_lock(&current->fs->lock);
+ 	oldentry.dentry = dget(wdentry);
+ 	oldentry.mnt = mntget(wdmnt);
+         read_unlock(&current->fs->lock);
+ 	newentry.dentry = oldentry.dentry;
+ 	newentry.mnt = oldentry.mnt;
+ 	
+ 	follow_dotdot(&newentry);
+ 	/* check it */
+ 	if(newentry.dentry == root && 
+ 		newentry.mnt == rootmnt){
+ 		ret = 0;
+ 		goto out;
+ 	}
+ 	
+ 	while(oldentry.mnt != newentry.mnt ||
+ 		oldentry.dentry != newentry.dentry){
+ 		
+ 		memcpy(&oldentry, &newentry, sizeof(struct nameidata));
+ 		follow_dotdot(&newentry);
+ 		
+ 		/* check it */
+ 		if(newentry.dentry == root && 
+ 			newentry.mnt == rootmnt){
+ 			ret = 0;
+ 			goto out;
+ 		}
+ 	}
+ out:
+ 	dput(newentry.dentry);
+ 	mntput(newentry.mnt);
+ 	return ret;
+ }
  
  /*
   *  It's more convoluted than I'd like it to be, but... it's still fairly
diff -Nrp linux-2.6.16.53/fs/open.c linux-2.6.16.53-new/fs/open.c
*** linux-2.6.16.53/fs/open.c	2007-07-25 23:05:45.000000000 +0200
--- linux-2.6.16.53-new/fs/open.c	2007-09-15 16:14:52.000000000 +0200
*************** dput_and_out:
*** 560,565 ****
--- 560,567 ----
  out:
  	return error;
  }
+ long directory_is_out(struct vfsmount *, struct dentry*, 
+ 		struct vfsmount *, struct dentry *);
  
  asmlinkage long sys_fchdir(unsigned int fd)
  {
*************** asmlinkage long sys_fchdir(unsigned int 
*** 581,586 ****
--- 583,591 ----
  	error = -ENOTDIR;
  	if (!S_ISDIR(inode->i_mode))
  		goto out_putf;
+ 	if (directory_is_out(mnt, dentry, current->fs->rootmnt, 
+ 				current->fs->root))
+ 		goto out_putf;
  
  	error = file_permission(file, MAY_EXEC);
  	if (!error)
*************** out:
*** 594,600 ****
  asmlinkage long sys_chroot(const char __user * filename)
  {
  	struct nameidata nd;
! 	int error;
  
  	error = __user_walk(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
  	if (error)
--- 599,605 ----
  asmlinkage long sys_chroot(const char __user * filename)
  {
  	struct nameidata nd;
! 	int error, set_wd = 0;
  
  	error = __user_walk(filename, LOOKUP_FOLLOW | LOOKUP_DIRECTORY | LOOKUP_NOALT, &nd);
  	if (error)
*************** asmlinkage long sys_chroot(const char __
*** 607,615 ****
--- 612,631 ----
  	error = -EPERM;
  	if (!capable(CAP_SYS_CHROOT))
  		goto dput_and_out;
+ 	error = -ENOTDIR;
+ 	/*
+ 	if (directory_is_out(nd.mnt, nd.dentry, current->fs->rootmnt,
+ 				current->fs->root))
+ 		goto dput_and_out;
+ 		*/
+ 	set_wd = directory_is_out(current->fs->pwdmnt, current->fs->pwd, 
+ 				nd.mnt, nd.dentry);
  
  	set_fs_root(current->fs, nd.mnt, nd.dentry);
  	set_fs_altroot();
+ 	/* if wd is out, reset it to . */
+ 	if(set_wd)
+ 		set_fs_pwd(current->fs, nd.mnt, nd.dentry);
  	error = 0;
  dput_and_out:
  	path_release(&nd);

  reply	other threads:[~2007-09-26 13:11 UTC|newest]

Thread overview: 63+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <952DN-83o-31@gated-at.bofh.it>
     [not found] ` <954cl-29C-3@gated-at.bofh.it>
     [not found]   ` <95ctn-74b-15@gated-at.bofh.it>
     [not found]     ` <95cMH-7um-19@gated-at.bofh.it>
     [not found]       ` <95gdA-4OZ-7@gated-at.bofh.it>
2007-09-20 11:13         ` sys_chroot+sys_fchdir Fix Bodo Eggert
2007-09-20 11:59           ` Philipp Marek
2007-09-20 12:52             ` majkls
2007-09-20 16:06             ` David Newall
2007-09-20 16:17               ` Philipp Marek
2007-09-20 18:02                 ` David Newall
2007-09-20 20:53                   ` Bill Davidsen
2007-09-21  8:29                     ` David Newall
2007-09-24 21:32                       ` Serge E. Hallyn
2007-09-24 22:04                         ` David Newall
2007-09-24 23:00                           ` Serge E. Hallyn
2007-09-25  7:45                             ` David Newall
2007-09-25 11:49                               ` Serge E. Hallyn
2007-09-25 13:58                                 ` David Newall
2007-09-25 15:10                                   ` Chroot bug (was: sys_chroot+sys_fchdir Fix) David Newall
2007-09-25 15:20                                     ` Jan Engelhardt
2007-09-25 15:39                                       ` Chroot bug Miloslav Semler
2007-09-25 15:41                                       ` David Newall
2007-09-25 15:48                                         ` Jan Engelhardt
2007-09-25 16:19                                           ` Miloslav Semler
2007-09-25 16:52                                             ` Jan Engelhardt
2007-09-25 17:00                                               ` Miloslav Semler
2007-09-25 17:05                                                 ` Jan Engelhardt
2007-09-25 17:09                                                   ` Miloslav Semler
2007-09-25 17:09                                                   ` Al Viro
2007-09-25 17:19                                                     ` Miloslav Semler
2007-09-25 16:53                                             ` Serge E. Hallyn
2007-09-25 20:51                                           ` David Newall
2007-09-25 15:30                                     ` Chroot bug (was: sys_chroot+sys_fchdir Fix) Alan Cox
2007-09-25 15:35                                       ` Chroot bug David Newall
2007-09-25 15:48                                         ` Alan Cox
2007-09-25 15:47                                           ` Jan Engelhardt
2007-09-25 23:50                                           ` David Newall
2007-09-26  0:18                                             ` Alan Cox
2007-09-26 10:24                                               ` David Newall
2007-09-26 10:47                                                 ` Alan Cox
2007-09-26 11:06                                                   ` David Newall
2007-09-26 11:20                                                     ` Alan Cox
     [not found]                                                       ` <46FA41B4.9040104@prepere.com>
     [not found]                                                         ` <20070926123522.54ffd56f@the-village.bc.nu>
2007-09-26 11:34                                                           ` Miloslav Semler
2007-09-26 14:09                                                             ` Alan Cox
2007-09-26 13:13                                                     ` Bongani Hlope
2007-09-26  0:55                                             ` Adrian Bunk
2007-09-26  5:21                                               ` Kyle Moffett
2007-09-26  5:25                                                 ` Willy Tarreau
2007-09-26 10:27                                                 ` David Newall
2007-09-26 10:45                                                   ` Olivier Galibert
2007-09-26 11:13                                                     ` David Newall
2007-09-26 13:18                                                       ` linux-os (Dick Johnson)
2007-09-26 15:02                                                       ` Olivier Galibert
2007-09-26 12:54                                                   ` Kyle Moffett
2007-09-26 13:11                                                     ` Miloslav Semler [this message]
2007-09-26 13:42                                                       ` Al Viro
2007-09-26 14:51                                                         ` Miloslav Semler
2007-09-26 14:02                                                       ` Kyle Moffett
2007-09-26 15:01                                                         ` Miloslav Semler
2007-09-27 13:49                                                           ` Jiri Kosina
2007-09-25 16:33                                         ` Arjan van de Ven
2007-09-25 15:32                                     ` Chroot bug (was: sys_chroot+sys_fchdir Fix) Adrian Bunk
2007-09-25 15:43                                       ` Chroot bug Miloslav Semler
2007-09-25 16:02                                         ` Adrian Bunk
2007-09-26 19:23                                     ` Chroot bug (was: sys_chroot+sys_fchdir Fix) Bodo Eggert
2007-09-24 23:02                           ` sys_chroot+sys_fchdir Fix Serge E. Hallyn
     [not found]         ` <95UE2-1oR-19@gated-at.bofh.it>
     [not found]           ` <95V72-2ly-17@gated-at.bofh.it>
     [not found]             ` <97pG8-3B5-47@gated-at.bofh.it>
     [not found]               ` <97sX2-p1-3@gated-at.bofh.it>
2007-09-26  9:38                 ` Nick Craig-Wood

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=46FA5A85.20407@prepere.com \
    --to=majkls@prepere.com \
    --cc=7eggert@gmx.de \
    --cc=alan@lxorguk.ukuu.org.uk \
    --cc=bunk@fs.tum.de \
    --cc=bunk@kernel.org \
    --cc=david@davidnewall.com \
    --cc=davidsen@tmr.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mrmacman_g4@mac.com \
    --cc=philipp@marek.priv.at \
    --cc=serge@hallyn.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox