Date: Sat, 16 Aug 2008 17:22:13 +0200 From: Jille Timmermans <jille@quis.cx> To: Kostik Belousov <kostikbel@gmail.com> Cc: Ed Schouten <ed@80386.nl>, FreeBSD Arch <freebsd-arch@freebsd.org> Subject: Re: [Reviews requested] kern/121073: chroot for non-root users Message-ID: <48A6F0A5.7070208@quis.cx> In-Reply-To: <20080816121049.GU1803@deviant.kiev.zoral.com.ua> References: <20080816111824.GL99951@hoeg.nl> <20080816121049.GU1803@deviant.kiev.zoral.com.ua>
next in thread | previous in thread | raw e-mail | index | archive | help
This is a multi-part message in MIME format. --------------080102010200070804050806 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Confirming Kostik, using rfork(RFPROC) instead of rfork(RFPROC|RFFDG) and chrooting in the child also chroot's the parent, without giving him the flag. An option might be to store the P_NOSUGID flag somewhere in the desc table ? Attached patch will show the difference between w/ and w/o RFFDG. jille@elvis:~$ cc -o chroot-rfork chroot-rfork.c jille@elvis:~$ sudo ./chroot-rfork /COPYRIGHT does not exist (chrooted) /COPYRIGHT does not exist (chrooted) jille@elvis:~$ cc -o chroot-rfork chroot-rfork.c -DWITH_RFFDG_FLAG jille@elvis:~$ sudo ./chroot-rfork /COPYRIGHT does not exist (chrooted) /COPYRIGHT exists (not chrooted) -- Jille Kostik Belousov wrote: > On Sat, Aug 16, 2008 at 01:18:24PM +0200, Ed Schouten wrote: > >> Hello everyone, >> >> When I visited FOSDEM back in February, I was talking with Jille >> Timmermans about the chroot() call. After discussing that the problem >> with chroot() is that it cannot be safely be executed by non-root users >> w.r.t. setuid binaries*, we wrote this patchset for the kernel to add >> something similar to `MNT_NOSUID' to the process flags. The result >> being: >> >> http://bugs.FreeBSD.org/121073 >> >> The patch even adds a small security improvement to the system. Say, >> you'd change the typical chroot() + setuid() order the other way around, >> you're guaranteed the chrooted process will never change users >> afterwards, because it won't honour set[ug]id binaries anymore. >> >> Our security officer was wise enough to add the following to the PR: >> >> +----------------------------------------------------------+ >> |UNDER NO CONDITIONS SHOULD THIS PATCH BE COMMITTED WITHOUT| >> |EXPLICIT APPROVAL FROM THE FREEBSD SECURITY OFFICER. | >> +----------------------------------------------------------+ >> >> After having a discussion with Colin on IRC, there are a couple of >> questions we would like to be answered (or discussed) before getting >> this in the tree: >> >> - Are there any comments on the patch itself? >> >> - Colin was concerned if turned on, would it be possible for the user to >> do things which it normally couldn't and shouldn't? >> >> It would be great to get many reviews on this before we'd land it in the >> source tree. I've attached the patch to this email as well. Thanks! >> >> -- >> Ed Schouten <ed@80386.nl> >> WWW: http://80386.nl/ >> >> * Hardlink a setuid binary to a directory containing a fake C library >> and executing it. >> > > I think that the patch gives instant root. FreeBSD provides a rfork(2) > system call. This call allows the processes to share filedesc table, that, > among other information, contains the root of the filesystem namespace > for the process. > > So, the scenario is to rfork() a process without RFFDG flag, and then > for one of the resulting processes to perform a chroot. Now, second one > has chrooted root, but no P_NOSUGID flag set. > --------------080102010200070804050806 Content-Type: text/plain; name="chroot-rfork.c" Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename="chroot-rfork.c" #include <err.h> #include <unistd.h> #include <sys/stat.h> #include <sys/types.h> #ifdef WITH_RFFDG_FLAG #define RFORK_FLAGS RFPROC|RFFDG #else #define RFORK_FLAGS RFPROC #endif int main(int argc, char **argv) { struct stat sb; switch(rfork(RFORK_FLAGS)) { case -1: err(1, "rfork()"); case 0: if(chroot("/tmp")!=0) err(1, "chroot()"); if(stat("/COPYRIGHT", &sb)==0) printf("/COPYRIGHT exists (not chrooted)\n"); else printf("/COPYRIGHT does not exist (chrooted)\n"); break; default: sleep(1); if(stat("/COPYRIGHT", &sb)==0) printf("/COPYRIGHT exists (not chrooted)\n"); else printf("/COPYRIGHT does not exist (chrooted)\n"); } } --------------080102010200070804050806--
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?48A6F0A5.7070208>