lkml.org 
[lkml]   [1998]   [Oct]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH] Capabilities & Root Core dumps
This patch fixes the following _bugs_:

* Jakub Jelinek noted that on sparc, gcc won't inline the kernel_cap_t
structure when used as return value from an inlined function. This
patch therefore converts to using the same scheme used for pte_t's.

* Root core dumps works. Note that completely removing the isclear()
can be dangerous since it will be possible (with file-system
support) to have an executable "suid" without changing uids during
exec. This should be handeled even if this is an impossible case
today. A better fix is to check whether the new permitted set is a
subset of the old or not - so that's what I did.

astor

--
Alexander Kjeldaas, Guardian Networks AS, Trondheim, Norway
http://www.guardian.no/
diff -ur linux-2.1.125/fs/exec.c l125/fs/exec.c
--- linux-2.1.125/fs/exec.c Thu Aug 27 23:30:50 1998
+++ l125/fs/exec.c Mon Oct 19 10:24:27 1998
@@ -702,17 +702,17 @@

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));
+
/* 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) {
- int new_permitted = bprm->cap_permitted.cap |
- (bprm->cap_inheritable.cap &
- current->cap_inheritable.cap);
-
- current->cap_permitted.cap = new_permitted;
- current->cap_effective.cap = new_permitted &
- bprm->cap_effective.cap;
+ cap_t(current->cap_permitted) = new_permitted;
+ cap_t(current->cap_effective) = new_permitted &
+ cap_t(bprm->cap_effective);
}

/* AUD: Audit candidate if current->cap_effective is set */
@@ -720,7 +720,7 @@
current->suid = current->euid = current->fsuid = bprm->e_uid;
current->sgid = current->egid = current->fsgid = bprm->e_gid;
if (current->euid != current->uid || current->egid != current->gid ||
- !cap_isclear(current->cap_permitted))
+ !cap_issubset(new_permitted, current->cap_permitted))
current->dumpable = 0;
}

Only in l125/fs: exec.c~
diff -ur linux-2.1.125/fs/proc/array.c l125/fs/proc/array.c
--- linux-2.1.125/fs/proc/array.c Mon Oct 12 12:45:45 1998
+++ l125/fs/proc/array.c Mon Oct 19 09:35:48 1998
@@ -799,9 +799,9 @@
return buffer + sprintf(buffer, "CapInh:\t%016x\n"
"CapPrm:\t%016x\n"
"CapEff:\t%016x\n",
- p->cap_inheritable.cap,
- p->cap_permitted.cap,
- p->cap_effective.cap);
+ cap_t(p->cap_inheritable),
+ cap_t(p->cap_permitted),
+ cap_t(p->cap_effective));
}


diff -ur linux-2.1.125/include/linux/capability.h l125/include/linux/capability.h
--- linux-2.1.125/include/linux/capability.h Mon Oct 12 12:56:45 1998
+++ l125/include/linux/capability.h Mon Oct 19 10:25:01 1998
@@ -38,9 +38,19 @@

#ifdef __KERNEL__

+/* #define STRICT_CAP_T_TYPECHECKS */
+
+#ifdef STRICT_CAP_T_TYPECHECKS
+
typedef struct kernel_cap_struct {
__u32 cap;
} kernel_cap_t;
+
+#else
+
+typedef __u32 kernel_cap_t;
+
+#endif

#define _USER_CAP_HEADER_SIZE (2*sizeof(__u32))
#define _KERNEL_CAP_T_SIZE (sizeof(kernel_cap_t))
@@ -259,51 +269,63 @@
/*
* Internal kernel functions only
*/
+
+#ifdef STRICT_CAP_T_TYPECHECKS
+
+#define to_cap_t(x) { x }
+#define cap_t(x) (x).cap
+
+#else
+
+#define to_cap_t(x) (x)
+#define cap_t(x) (x)
+
+#endif

-#define CAP_EMPTY_SET { 0 }
-#define CAP_FULL_SET { ~0 }
-#define CAP_INIT_EFF_SET { ~0 & ~CAP_TO_MASK(CAP_SETPCAP) }
-#define CAP_INIT_INH_SET { ~0 & ~CAP_TO_MASK(CAP_SETPCAP) }
+#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_TO_MASK(x) (1 << (x))
-#define cap_raise(c, flag) ((c).cap |= CAP_TO_MASK(flag))
-#define cap_lower(c, flag) ((c).cap &= ~CAP_TO_MASK(flag))
-#define cap_raised(c, flag) ((c).cap & CAP_TO_MASK(flag))
+#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))

static inline kernel_cap_t cap_combine(kernel_cap_t a, kernel_cap_t b)
{
kernel_cap_t dest;
- dest.cap = a.cap | b.cap;
+ cap_t(dest) = cap_t(a) | cap_t(b);
return dest;
}

static inline kernel_cap_t cap_intersect(kernel_cap_t a, kernel_cap_t b)
{
kernel_cap_t dest;
- dest.cap = a.cap & b.cap;
+ cap_t(dest) = cap_t(a) & cap_t(b);
return dest;
}

static inline kernel_cap_t cap_drop(kernel_cap_t a, kernel_cap_t drop)
{
kernel_cap_t dest;
- dest.cap = a.cap & ~drop.cap;
+ cap_t(dest) = cap_t(a) & ~cap_t(drop);
return dest;
}

static inline kernel_cap_t cap_invert(kernel_cap_t c)
{
kernel_cap_t dest;
- dest.cap = ~c.cap;
+ cap_t(dest) = ~cap_t(c);
return dest;
}

-#define cap_isclear(c) (!(c).cap)
-#define cap_issubset(a,set) (!((a).cap & ~(set).cap))
+#define cap_isclear(c) (!cap_t(c))
+#define cap_issubset(a,set) (!(cap_t(a) & ~cap_t(set)))

-#define cap_clear(c) do { (c).cap = 0; } while(0)
-#define cap_set_full(c) do { (c).cap = ~0; } while(0)
-#define cap_mask(c,mask) do { (c).cap &= (mask).cap; } while(0)
+#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_is_fs_cap(c) (CAP_TO_MASK(c) & CAP_FS_MASK)

diff -ur linux-2.1.125/kernel/capability.c l125/kernel/capability.c
--- linux-2.1.125/kernel/capability.c Sun Aug 23 20:45:57 1998
+++ l125/kernel/capability.c Mon Oct 19 09:35:48 1998
@@ -61,9 +61,9 @@
}

if (!error) {
- data.permitted = target->cap_permitted.cap;
- data.inheritable = target->cap_inheritable.cap;
- data.effective = target->cap_effective.cap;
+ data.permitted = cap_t(target->cap_permitted);
+ data.inheritable = cap_t(target->cap_inheritable);
+ data.effective = cap_t(target->cap_effective);
}

if (target != current)
diff -ur linux-2.1.125/kernel/sys.c l125/kernel/sys.c
--- linux-2.1.125/kernel/sys.c Sun Aug 16 01:01:13 1998
+++ l125/kernel/sys.c Mon Oct 19 09:35:48 1998
@@ -586,11 +586,11 @@

if (!issecure(SECURE_NO_SETUID_FIXUP)) {
if (old_fsuid == 0 && current->fsuid != 0) {
- current->cap_effective.cap &= ~CAP_FS_MASK;
+ cap_t(current->cap_effective) &= ~CAP_FS_MASK;
}
if (old_fsuid != 0 && current->fsuid == 0) {
- current->cap_effective.cap |=
- (current->cap_permitted.cap & CAP_FS_MASK);
+ cap_t(current->cap_effective) |=
+ (cap_t(current->cap_permitted) & CAP_FS_MASK);
}
}
\
 
 \ /
  Last update: 2005-03-22 13:45    [W:0.126 / U:0.028 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site