Linux 2.1.115 CAP_SYS_EXEC patch

Duncan Simpson (dps@io.stargate.co.uk)
Sun, 16 Aug 1998 01:48:39 +0100


Following various requests here is my patch that implements CAP_SYS_EXEC on
linux boxen. It also does a move that will be required when the VFS does support
capabalities. Other capabilities similar ilk may be nice, for example we could
take network capability from NT's book, and procfs only capability would be nice
for stopping trojan versions of things like ps, etc. I suppose fascists may feel
like taking some of these anyone from selected (ab)users.

In particular logic says I could change the masking to just setting the allowed
capabilities to CAP_SYS_EXEC because no other capabilites are not masked out
and without CAP_SYS_EXEC you never get to that code. The same logic does not
apply to capabilities that cut other things normally allowed (CAP_SYS_SOCKET
could make it harder to transfer rootkits to a cracked host; it would also have
"marketing value" as an internet nanny solution).

Duncan (-:

--- linux/fs/exec.c.dist Wed Aug 12 04:46:08 1998
+++ linux/fs/exec.c Wed Aug 12 20:32:34 1998
@@ -569,6 +569,7 @@
int mode;
int retval,id_change,cap_raised;
struct inode * inode = bprm->dentry->d_inode;
+ static const kernel_cap_t normal_caps={ CAP_KEEP_SET };

mode = inode->i_mode;
if (!S_ISREG(mode)) /* must be regular file */
@@ -609,9 +610,12 @@
}

/* We don't have VFS support for capabilities yet */
- cap_clear(bprm->cap_inheritable);
- cap_clear(bprm->cap_permitted);
- cap_clear(bprm->cap_effective);
+ bprm->cap_inheritable=current->cap_inheritable;
+ bprm->cap_permitted=current->cap_permitted;
+ bprm->cap_effective=current->cap_effective;
+ cap_mask(bprm->cap_inheritable, normal_caps);
+ cap_mask(bprm->cap_permitted, normal_caps);
+ cap_mask(bprm->cap_effective, normal_caps);

/* To support inheritance of root-permissions and suid-root
* executables under compatibility mode, we raise the
@@ -810,6 +814,13 @@
struct dentry * dentry;
int retval;
int i;
+
+ /* Nobody without CAP_SYS_EXEC can exec anything */
+ if (!capable(CAP_SYS_EXEC))
+ {
+ printk(KERN_INFO " exec denied for pid %d\n", current->pid);
+ return -EPERM;
+ }

bprm.p = PAGE_SIZE*MAX_ARG_PAGES-sizeof(void *);
for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
--- linux/kernel/sys.c.dist Wed Aug 12 04:56:54 1998
+++ linux/kernel/sys.c Wed Aug 12 20:33:16 1998
@@ -335,18 +335,28 @@
* fsuid is handled elsewhere. fsuid == 0 and {r,e,s}uid!= 0 should
* never happen.
*
- * -astor
+ * -astor
+ *
+ * keep is the set of capabilties preserved. This is fixed as CAP_KEEP_SET
+ * normally just CAP_SYS_EXEC() (the exec() system call). The idea is that
+ * daemons that do not need this capability should drop it so standard
+ * shellcode anywhere fails.
+ *
+ * Duncan (-:
+ *
*/
extern inline void cap_emulate_setxuid(int old_ruid, int old_euid,
int old_suid)
{
+ static const kernel_cap_t keep={ CAP_KEEP_SET };
+
if ((old_ruid == 0 || old_euid == 0 || old_suid == 0) &&
(current->uid != 0 && current->euid != 0 && current->suid != 0)) {
- cap_clear(current->cap_permitted);
- cap_clear(current->cap_effective);
+ cap_mask(current->cap_permitted, keep);
+ cap_mask(current->cap_effective, keep);
}
if (old_euid == 0 && current->euid != 0) {
- cap_clear(current->cap_effective);
+ cap_mask(current->cap_effective, keep);
}
if (old_euid != 0 && current->euid == 0) {
current->cap_effective = current->cap_permitted;
--- linux/include/linux/capability.h.dist Wed Aug 12 04:23:32 1998
+++ linux/include/linux/capability.h Wed Aug 12 05:14:37 1998
@@ -254,6 +254,10 @@

#define CAP_SYS_TTY_CONFIG 26

+/* Allow use of exec(). Anti-shellcode measure */
+
+#define CAP_SYS_EXEC 27
+
#ifdef __KERNEL__

/*
@@ -266,6 +270,7 @@
#define CAP_INIT_INH_SET { ~0 & ~CAP_TO_MASK(CAP_SETPCAP) }

#define CAP_TO_MASK(x) (1 << (x))
+#define CAP_KEEP_SET (CAP_TO_MASK(CAP_SYS_EXEC))
#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))

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.altern.org/andrebalsa/doc/lkml-faq.html