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)