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 * Alexander Kjeldaas - * 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;