On Tue, 3 Feb 2015, Casey Schaufler wrote: > > (I wasn't going to ask bc I assumed not, but heck maybe you're bored > > on a desert island or snowed in and just looking for an excuse to hack :) > > Not at all bored, but I think this could be important.
Ok here is a draft of a patch that follows these ideas. It also adds an ambient field and sets the field if a new capability CAP_AMBIENT_MASK is set. The perm calcualtion is as suggested by Serge. If CAP_AMBIENT_MASK is set the inheritable caps become the ambient ones. If it is not set then the ambient caps are copied from the parent. DRAFT --- not a working patch: Index: linux/include/linux/capability.h =================================================================== --- linux.orig/include/linux/capability.h 2015-02-03 13:25:03.000000000 -0600 +++ linux/include/linux/capability.h 2015-02-03 13:39:23.385424676 -0600 @@ -29,6 +29,7 @@ struct cpu_vfs_cap_data { __u32 magic_etc; kernel_cap_t permitted; kernel_cap_t inheritable; + kernel_cap_t ambient; }; #define _USER_CAP_HEADER_SIZE (sizeof(struct __user_cap_header_struct)) Index: linux/include/uapi/linux/capability.h =================================================================== --- linux.orig/include/uapi/linux/capability.h 2014-07-10 16:10:29.814424392 -0500 +++ linux/include/uapi/linux/capability.h 2015-02-03 13:26:13.231081452 -0600 @@ -351,8 +351,10 @@ struct vfs_cap_data { #define CAP_AUDIT_READ 37 +/* Set the current inheritable mask as the ambient inheritable mask */ +#define CAP_AMBIENT_MASK 38 -#define CAP_LAST_CAP CAP_AUDIT_READ +#define CAP_LAST_CAP CAP_AMBIENT_MASK #define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP) Index: linux/security/commoncap.c =================================================================== --- linux.orig/security/commoncap.c 2015-02-03 13:25:03.000000000 -0600 +++ linux/security/commoncap.c 2015-02-03 13:43:16.317859741 -0600 @@ -349,17 +349,24 @@ static inline int bprm_caps_from_vfs_cap CAP_FOR_EACH_U32(i) { __u32 permitted = caps->permitted.cap[i]; __u32 inheritable = caps->inheritable.cap[i]; + __u32 ambient = caps->ambient.cap[i]; /* * pP' = (X & fP) | (pI & fI) */ new->cap_permitted.cap[i] = (new->cap_bset.cap[i] & permitted) | - (new->cap_inheritable.cap[i] & inheritable); + (new->cap_inheritable.cap[i] & inheritable) | + (ambient & inheritable); if (permitted & ~new->cap_permitted.cap[i]) /* insufficient to execute correctly */ ret = -EPERM; + + if (capable(CAP_AMBIENT_MASK)) + new->cap_ambient.cap[i] = inheritable; + else + new->cap_ambient.cap[i] = ambient; } /* Index: linux/include/linux/cred.h =================================================================== --- linux.orig/include/linux/cred.h 2014-12-18 11:17:49.731948737 -0600 +++ linux/include/linux/cred.h 2015-02-03 13:37:32.701019201 -0600 @@ -122,6 +122,7 @@ struct cred { kernel_cap_t cap_permitted; /* caps we're permitted */ kernel_cap_t cap_effective; /* caps we can actually use */ kernel_cap_t cap_bset; /* capability bounding set */ + kernel_cap_t cap_ambient; /* Ambient inherited caps */ #ifdef CONFIG_KEYS unsigned char jit_keyring; /* default keyring to attach requested * keys to */ -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/