5176669 2000-06-08 19:28 /197 rader/ Postmaster Mottagare: Bugtraq (import) <11204> Ärende: Sendmail 8.10.2, Linux 2.4.0 - capabilities ------------------------------------------------------------ Approved-By: aleph1@SECURITYFOCUS.COM Delivered-To: bugtraq@lists.securityfocus.com Delivered-To: bugtraq@securityfocus.com X-URL: http://black-ice.cc.vt.edu/~valdis/ X-Face-Viewer: See ftp://cs.indiana.edu/pub/faces/index.html to decode picture X-Face: 34C9$Ewd2zeX+\!i1BA\j{ex+$/V'JBG#;3_noWWYPa"|,I#`R"{n@w>#:{)FXyiAS7(8t ^*w5O*!8O9YTe[r{e%7(yVRb|qxsRYw`7J!`AM}m_SHaj}f8eb@d^L>BrX7iO[<!v4-0bVIpaxF#- %9#a9h6JXI|T|8o6t\V?kGl]Q!1V]GtNliUtz:3},0"hkPeBuu%E,j(:\iOX-P,t7lRR# Mime-Version: 1.0 Content-Type: multipart/mixed ; boundary="==_Exmh_13432841100" Message-ID: <200006081628.e58GSiL29316@black-ice.cc.vt.edu> Date: Thu, 8 Jun 2000 12:28:44 -0400 Reply-To: Valdis.Kletnieks@VT.EDU Sender: Bugtraq List <BUGTRAQ@SECURITYFOCUS.COM> From: Valdis Kletnieks <Valdis.Kletnieks@VT.EDU> X-To: sendmail-bugs@sendmail.org, sendmail-security@sendmail.org torvalds@transmeta.com, alan@redhat.com To: BUGTRAQ@SECURITYFOCUS.COM This is a multipart MIME message. --==_Exmh_13432841100 Content-Type: text/plain; charset=us-ascii The Linux 2.4.0-test1 kernel has the problem as well, as do (probably) some of the 2.3 kernels. Just a heads-up. Yes, I know they're development. Patch for 2.4.0-test1 attached, lightly tested. Code forward-ported from the 2.2.16 patch. My machine still boots. ;) My first shot at Linux kernel hacking - were there any other tweaks to close this hole? ;) -- Valdis Kletnieks Operating Systems Analyst Virginia Tech --==_Exmh_13432841100 Content-Type: text/plain ; name="2.4.0.patch"; charset=us-ascii Content-Description: 2.4.0.patch Content-Disposition: attachment; filename="2.4.0.patch" --- kernel/capability.c.dist Tue Dec 7 20:09:12 1999 +++ kernel/capability.c Thu Jun 8 11:37:02 2000 @@ -8,6 +8,8 @@ #include <linux/mm.h> #include <asm/uaccess.h> +kernel_cap_t cap_bset = CAP_INIT_EFF_SET; + /* Note: never hold tasklist_lock while spinning for this one */ spinlock_t task_capability_lock = SPIN_LOCK_UNLOCKED; @@ -16,8 +18,6 @@ * capability set pointers may be NULL -- indicating that that set is * uninteresting and/or not to be changed. */ - -kernel_cap_t cap_bset = CAP_FULL_SET; asmlinkage long sys_capget(cap_user_header_t header, cap_user_data_t dataptr) { --- include/linux/capability.h.dist Tue Jun 6 17:27:53 2000 +++ include/linux/capability.h Thu Jun 8 11:36:36 2000 @@ -4,13 +4,16 @@ * Andrew G. Morgan <morgan@transmeta.com> * Alexander Kjeldaas <astor@guardian.no> * with help from Aleph1, Roland Buresund and Andrew Main. + * + * See here for the libcap library ("POSIX draft" compliance): + * + * ftp://linux.kernel.org/pub/linux/libs/security/linux-privs/kernel-2.2/ */ #ifndef _LINUX_CAPABILITY_H #define _LINUX_CAPABILITY_H #include <linux/types.h> /* User-level do most of the mapping between kernel and user capabilities based on the version tag given by the kernel. The @@ -170,8 +174,8 @@ #define CAP_IPC_OWNER 15 -/* Insert and remove kernel modules */ - +/* Insert and remove kernel modules - modify kernel without limit */ +/* Modify cap_bset */ #define CAP_SYS_MODULE 16 /* Allow ioperm/iopl access */ @@ -294,12 +298,12 @@ #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 & ~CAP_TO_MASK(CAP_SETPCAP)) +#define CAP_INIT_INH_SET to_cap_t(0) #define CAP_TO_MASK(x) (1 << (x)) #define cap_raise(c, flag) (cap_t(c) |= CAP_TO_MASK(flag)) #define cap_lower(c, flag) (cap_t(c) &= ~CAP_TO_MASK(flag)) -#define cap_raised(c, flag) (cap_t(c) & CAP_TO_MASK(flag) & cap_bset) +#define cap_raised(c, flag) (cap_t(c) & CAP_TO_MASK(flag)) static inline kernel_cap_t cap_combine(kernel_cap_t a, kernel_cap_t b) { --- fs/exec.c.dist Sun May 21 14:38:47 2000 +++ fs/exec.c Thu Jun 8 11:43:18 2000 @@ -585,21 +585,18 @@ cap_clear(bprm->cap_effective); /* To support inheritance of root-permissions and suid-root - * executables under compatibility mode, we raise the - * effective and inherited bitmasks of the executable file - * (translation: we set the executable "capability dumb" and - * set the allowed set to maximum). We don't set any forced - * bits. + * executables under compatibility mode, we raise all three + * capability sets for the file. * * If only the real uid is 0, we only raise the inheritable - * bitmask of the executable file (translation: we set the - * allowed set to maximum and the application to "capability - * smart"). + * and permitted sets of the executable file. */ if (!issecure(SECURE_NOROOT)) { - if (bprm->e_uid == 0 || current->uid == 0) + if (bprm->e_uid == 0 || current->uid == 0) { cap_set_full(bprm->cap_inheritable); + cap_set_full(bprm->cap_permitted); + } if (bprm->e_uid == 0) cap_set_full(bprm->cap_effective); } @@ -610,10 +607,12 @@ * privilege does not go against other system constraints. * The new Permitted set is defined below -- see (***). */ { - kernel_cap_t working = - cap_combine(bprm->cap_permitted, - cap_intersect(bprm->cap_inheritable, - current->cap_inheritable)); + kernel_cap_t permitted, working; + + permitted = cap_intersect(bprm->cap_permitted, cap_bset); + working = cap_intersect(bprm->cap_inheritable, + current->cap_inheritable); + working = cap_combine(permitted, working); if (!cap_issubset(working, current->cap_permitted)) { cap_raised = 1; } @@ -646,26 +645,29 @@ * The formula used for evolving capabilities is: * * pI' = pI - * (***) pP' = fP | (fI & pI) + * (***) pP' = (fP & X) | (fI & pI) * pE' = pP' & fE [NB. fE is 0 or ~0] * * I=Inheritable, P=Permitted, E=Effective // p=process, f=file - * ' indicates post-exec(). + * ' indicates post-exec(), and X is the global 'cap_bset'. */ void compute_creds(struct linux_binprm *bprm) { - int new_permitted = cap_t(bprm->cap_permitted) | - (cap_t(bprm->cap_inheritable) & - cap_t(current->cap_inheritable)); + kernel_cap_t new_permitted, working; + + new_permitted = cap_intersect(bprm->cap_permitted, cap_bset); + working = cap_intersect(bprm->cap_inheritable, + current->cap_inheritable); + new_permitted = cap_combine(new_permitted, working); /* For init, we want to retain the capabilities set * in the init_task struct. Thus we skip the usual * capability rules */ if (current->pid != 1) { - cap_t(current->cap_permitted) = new_permitted; - cap_t(current->cap_effective) = new_permitted & - cap_t(bprm->cap_effective); + current->cap_permitted = new_permitted; + current->cap_effective = + cap_intersect(new_permitted, bprm->cap_effective); } /* AUD: Audit candidate if current->cap_effective is set */ --==_Exmh_13432841100-- (5176669) ------------------------------------------(Ombruten)