From: Jorgen Cederlof <jc@lysator.liu.se>
To: linux-kernel@vger.kernel.org
Subject: [PATCH] User chroot
Date: Wed, 27 Jun 2001 01:45:34 +0200 [thread overview]
Message-ID: <20010627014534.B2654@ondska> (raw)
Hi,
Have you ever wondered why normal users are not allowed to chroot?
I have. The reasons I can figure out are:
* Changing root makes it trivial to trick suid/sgid binaries to do
nasty things.
* If root calls chroot and changes uid, he expects that the process
can not escape to the old root by calling chroot again.
If we only allow user chroots for processes that have never been
chrooted before, and if the suid/sgid bits won't have any effect under
the new root, it should be perfectly safe to allow any user to chroot.
Example:
user:~$ /usr/sbin/traceroute 127.1
traceroute to 127.1 (127.0.0.1), 30 hops max, 38 byte packets
1 localhost (127.0.0.1) 6.658 ms 0.764 ms 0.613 ms
user:~$ /usr/sbin/chroot /
user:/$ /usr/sbin/traceroute 127.1
traceroute: icmp socket: Operation not permitted
user:/$ /usr/sbin/chroot /
/usr/sbin/chroot: cannot change root directory to /: Operation not permitted
user:/$
Is there any reason why this could not be the default behavior for the
official kernel?
Jörgen
diff -urN -X dontdiff linux-2.4.6-pre5-vanilla/CREDITS linux-2.4.6-pre5-devel/CREDITS
--- linux-2.4.6-pre5-vanilla/CREDITS Sat Jun 23 02:00:54 2001
+++ linux-2.4.6-pre5-devel/CREDITS Sat Jun 23 02:04:31 2001
@@ -497,6 +497,13 @@
S: Fremont, California 94539
S: USA
+N: Jörgen Cederlöf
+E: jc@lysator.liu.se
+D: User capabilities, user chroot
+S: Rydsvägen 258 A.36
+S: 584 34 Linköping
+S: Sweden
+
N: Gordon Chaffee
E: chaffee@cs.berkeley.edu
W: http://bmrc.berkeley.edu/people/chaffee/
diff -urN -X dontdiff linux-2.4.6-pre5-vanilla/fs/exec.c linux-2.4.6-pre5-devel/fs/exec.c
--- linux-2.4.6-pre5-vanilla/fs/exec.c Thu Apr 26 23:11:29 2001
+++ linux-2.4.6-pre5-devel/fs/exec.c Sat Jun 23 02:04:31 2001
@@ -617,7 +617,7 @@
if(!IS_NOSUID(inode)) {
/* Set-uid? */
- if (mode & S_ISUID)
+ if (mode & S_ISUID && capable(CAP_EXECSUID))
bprm->e_uid = inode->i_uid;
/* Set-gid? */
@@ -626,14 +626,15 @@
* is a candidate for mandatory locking, not a setgid
* executable.
*/
- if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))
+ if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)
+ && capable(CAP_EXECSGID))
bprm->e_gid = inode->i_gid;
}
/* We don't have VFS support for capabilities yet */
- cap_clear(bprm->cap_inheritable);
+ cap_clear_set_user(bprm->cap_inheritable);
cap_clear(bprm->cap_permitted);
- cap_clear(bprm->cap_effective);
+ cap_clear_set_user(bprm->cap_effective);
/* To support inheritance of root-permissions and suid-root
* executables under compatibility mode, we raise all three
diff -urN -X dontdiff linux-2.4.6-pre5-vanilla/fs/open.c linux-2.4.6-pre5-devel/fs/open.c
--- linux-2.4.6-pre5-vanilla/fs/open.c Fri Feb 9 20:29:44 2001
+++ linux-2.4.6-pre5-devel/fs/open.c Sat Jun 23 02:04:32 2001
@@ -421,9 +421,22 @@
goto dput_and_out;
error = -EPERM;
- if (!capable(CAP_SYS_CHROOT))
+ if (!capable(CAP_SYS_CHROOT) && !capable(CAP_USER_CHROOT))
goto dput_and_out;
+ if (!capable(CAP_SYS_CHROOT)) {
+ cap_lower(current->cap_effective, CAP_EXECSUID);
+ cap_lower(current->cap_permitted, CAP_EXECSUID);
+ cap_lower(current->cap_inheritable, CAP_EXECSUID);
+ cap_lower(current->cap_effective, CAP_EXECSGID);
+ cap_lower(current->cap_permitted, CAP_EXECSGID);
+ cap_lower(current->cap_inheritable, CAP_EXECSGID);
+ }
+
+ cap_lower(current->cap_effective, CAP_USER_CHROOT);
+ cap_lower(current->cap_permitted, CAP_USER_CHROOT);
+ cap_lower(current->cap_inheritable, CAP_USER_CHROOT);
+
set_fs_root(current->fs, nd.mnt, nd.dentry);
set_fs_altroot();
error = 0;
diff -urN -X dontdiff linux-2.4.6-pre5-vanilla/include/linux/capability.h linux-2.4.6-pre5-devel/include/linux/capability.h
--- linux-2.4.6-pre5-vanilla/include/linux/capability.h Sat May 26 03:01:28 2001
+++ linux-2.4.6-pre5-devel/include/linux/capability.h Sat Jun 23 02:04:32 2001
@@ -3,7 +3,7 @@
*
* Andrew G. Morgan <morgan@transmeta.com>
* Alexander Kjeldaas <astor@guardian.no>
- * with help from Aleph1, Roland Buresund and Andrew Main.
+ * with help from Aleph1, Roland Buresund, Andrew Main and Jörgen Cederlöf.
*
* See here for the libcap library ("POSIX draft" compliance):
*
@@ -277,6 +277,36 @@
#define CAP_LEASE 28
+
+/**
+ ** Capabilities used by normal user processes
+ **
+ ** They are handled somewhat different from other capabilities -
+ ** they are not cleared unless you drop them by hand, and using them
+ ** doesn't set PF_SUPERPRIV.
+ **/
+
+/* Allow the suid bit on executables to have effect */
+
+#define CAP_EXECSUID 29
+
+/* Allow the sgid bit on executables to have effect */
+
+#define CAP_EXECSGID 30
+
+/* Allow user chroots. This should have no negative impact on system
+ security - using it drops CAP_EXECS{U,G}ID and CAP_USER_CHROOT.
+ CAP_USER_CHROOT is also dropped if you make a normal chroot, to
+ prevent a process with changed UID from breaking out. */
+
+#define CAP_USER_CHROOT 31
+
+
+#define CAP_USER_MASK (CAP_TO_MASK( CAP_EXECSUID ) | \
+ CAP_TO_MASK( CAP_EXECSGID ) | \
+ CAP_TO_MASK( CAP_USER_CHROOT ) )
+
+
#ifdef __KERNEL__
/*
* Bounding set
@@ -302,7 +332,7 @@
#define CAP_EMPTY_SET to_cap_t(0)
#define CAP_FULL_SET to_cap_t(~0)
#define CAP_INIT_EFF_SET to_cap_t(~0 & ~CAP_TO_MASK(CAP_SETPCAP))
-#define CAP_INIT_INH_SET to_cap_t(0)
+#define CAP_INIT_INH_SET to_cap_t(CAP_USER_MASK)
#define CAP_TO_MASK(x) (1 << (x))
#define cap_raise(c, flag) (cap_t(c) |= CAP_TO_MASK(flag))
@@ -337,12 +367,13 @@
return dest;
}
-#define cap_isclear(c) (!cap_t(c))
+#define cap_isclear(c) (!(cap_t(c) & ~CAP_USER_MASK))
#define cap_issubset(a,set) (!(cap_t(a) & ~cap_t(set)))
-#define cap_clear(c) do { cap_t(c) = 0; } while(0)
-#define cap_set_full(c) do { cap_t(c) = ~0; } while(0)
-#define cap_mask(c,mask) do { cap_t(c) &= cap_t(mask); } while(0)
+#define cap_clear(c) do { cap_t(c) &= CAP_USER_MASK; } while(0)
+#define cap_set_full(c) do { cap_t(c) = ~0; } while(0)
+#define cap_mask(c,mask) do { cap_t(c) &= cap_t(mask); } while(0)
+#define cap_clear_set_user(c) do { cap_t(c) = CAP_USER_MASK; } while(0)
#define cap_is_fs_cap(c) (CAP_TO_MASK(c) & CAP_FS_MASK)
diff -urN -X dontdiff linux-2.4.6-pre5-vanilla/include/linux/sched.h linux-2.4.6-pre5-devel/include/linux/sched.h
--- linux-2.4.6-pre5-vanilla/include/linux/sched.h Sat May 26 03:01:28 2001
+++ linux-2.4.6-pre5-devel/include/linux/sched.h Sat Jun 23 02:04:32 2001
@@ -701,7 +701,8 @@
if (cap_is_fs_cap(cap) ? current->fsuid == 0 : current->euid == 0)
#endif
{
- current->flags |= PF_SUPERPRIV;
+ if (!(CAP_TO_MASK(cap) & CAP_USER_MASK))
+ current->flags |= PF_SUPERPRIV;
return 1;
}
return 0;
next reply other threads:[~2001-06-26 23:34 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2001-06-26 23:45 Jorgen Cederlof [this message]
2001-06-26 23:46 ` [PATCH] User chroot H. Peter Anvin
2001-06-27 0:48 ` David Wagner
2001-06-27 12:56 ` Marco Colombo
2001-06-27 13:56 ` Admin Mailing Lists
2001-06-27 3:32 ` Albert D. Cahalan
2001-06-27 4:24 ` H. Peter Anvin
2001-06-27 6:31 ` Kai Henningsen
2001-06-27 20:55 ` Albert D. Cahalan
2001-06-27 21:03 ` H. Peter Anvin
2001-06-27 21:19 ` Albert D. Cahalan
2001-06-28 7:47 ` Sean Hunter
2001-06-28 18:25 ` Albert D. Cahalan
2001-06-27 15:39 ` Marcus Sundberg
2001-06-27 17:55 ` Jorgen Cederlof
2001-06-27 6:37 ` Kai Henningsen
2001-06-27 18:14 ` H. Peter Anvin
2001-06-28 6:54 ` Kai Henningsen
2001-06-29 13:46 ` Jorgen Cederlof
[not found] <0C01A29FBAE24448A792F5C68F5EA47D1205FB@nasdaq.ms.ensim.com>
2001-06-27 0:37 ` Paul Menage
2001-06-27 0:45 ` H. Peter Anvin
2001-06-27 0:53 ` David Wagner
2001-06-27 0:51 ` David Wagner
2001-06-27 1:08 ` Mohammad A. Haque
2001-06-27 1:24 ` Paul Menage
2001-06-27 1:40 ` Alexander Viro
2001-06-27 2:17 ` Paul Menage
2001-06-27 6:35 ` Kai Henningsen
2001-06-27 7:19 ` Chris Wedgwood
2001-06-27 7:43 ` Alexander Viro
2001-06-27 4:39 ` David Wagner
-- strict thread matches above, loose matches on Subject: below --
2001-06-27 13:57 Jesse Pollard
2001-06-27 17:42 ` David Wagner
2001-06-27 23:11 Andries.Brouwer
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=20010627014534.B2654@ondska \
--to=jc@lysator.liu.se \
--cc=linux-kernel@vger.kernel.org \
/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