Andrew, James, Stephen, Chris, The following is all-but-untested (just compiles with relevant config combinations). But is each of you ok with the following approach for handling unknown capabilities?
KaiGai, the following does not require any immediate change from libcap, but does dictate how 64-bit capabilities would be formed. Please let me know if you have an objection. thanks, -serge >From 64284b5cff82a713d31247f37c2e8b393faa30d3 Mon Sep 17 00:00:00 2001 From: Serge E. Hallyn <[EMAIL PROTECTED]> Date: Mon, 6 Aug 2007 17:45:05 -0400 Subject: [PATCH 1/1] file capabilities: don't ensure we break with 64-bit caps We are currently using all 32 capability bits, so it seems all but certain that we will be using 64-bit capabilities soon. Meanwhile there is disagreement about whether the kernel should load binaries which have file capabilities for unknown kernels or not. This patch introduces a config variable, as well as a 64-bit file capability format. If SECURITY_FILE_CAPABILITIES_STRICTXATTR=y then any file with 64-bit capabilities will refuse to load. If SECURITY_FILE_CAPABILITIES_STRICTXATTR=n, then any file with 64-bit capabilities will load, ignoring unknown capabilities. The introduction of a 64-bit file capability format for the extended attributes must happen now to ensure that those who wish to use STRICTXATTR=n aren't foiled when the 33d capability bit is introduced. Signed-off-by: Serge E. Hallyn <[EMAIL PROTECTED]> --- include/linux/capability.h | 15 ++++++++++++++- security/Kconfig | 10 ++++++++++ security/commoncap.c | 42 ++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/include/linux/capability.h b/include/linux/capability.h index 8961e7f..390443a 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h @@ -46,8 +46,10 @@ typedef struct __user_cap_data_struct { #define XATTR_NAME_CAPS XATTR_SECURITY_PREFIX XATTR_CAPS_SUFFIX #define XATTR_CAPS_SZ (3*sizeof(__le32)) +#define XATTR_CAPS_SZ_64 (5*sizeof(__le32)) #define VFS_CAP_REVISION_MASK 0xFF000000 -#define VFS_CAP_REVISION_1 0x01000000 +#define VFS_CAP_REVISION_1 0x01000000 /* 32-bit caps */ +#define VFS_CAP_REVISION_2 0x02000000 /* 64-bit caps */ #define VFS_CAP_REVISION VFS_CAP_REVISION_1 @@ -62,6 +64,17 @@ struct vfs_cap_data { } data[1]; }; +#define VFS_CAP_HIBIT_MASK 0xFFFFFFFF +struct vfs_cap_data_v2 { + __u32 magic_etc; /* Little endian */ + struct { + __u32 permitted_lo; /* Little endian */ + __u32 permitted_hi; /* Little endian */ + __u32 inheritable_lo; /* Little endian */ + __u32 inheritable_hi; /* Little endian */ + } data[1]; +}; + #ifdef __KERNEL__ /* #define STRICT_CAP_T_TYPECHECKS */ diff --git a/security/Kconfig b/security/Kconfig index 8086e61..77e34de 100644 --- a/security/Kconfig +++ b/security/Kconfig @@ -90,6 +90,16 @@ config SECURITY_FILE_CAPABILITIES If in doubt, answer N. +config SECURITYFILE_CAPS_STRICT + bool "Refuse to run files with unknown capabilities" + depends on SECURITY_FILE_CAPABILITIES + default y + help + Refuse to run files which have unknown capabilities set + in the security.capability xattr. This could prevent + running important binaries from an updated distribution + on an older kernel. + config SECURITY_ROOTPLUG bool "Root Plug Support" depends on USB=y && SECURITY diff --git a/security/commoncap.c b/security/commoncap.c index aa6d929..25ac8ec 100644 --- a/security/commoncap.c +++ b/security/commoncap.c @@ -119,18 +119,50 @@ static inline void bprm_clear_caps(struct linux_binprm *bprm) #ifdef CONFIG_SECURITY_FILE_CAPABILITIES +#ifdef CONFIG_SECURITYFILE_CAPS_STRICT +static inline int read_v2_caps(__le32 *caps, struct linux_binprm *bprm) +{ + if ((le32_to_cpu(caps[2]) & VFS_CAP_HIBIT_MASK) || + (le32_to_cpu(caps[4]) & VFS_CAP_HIBIT_MASK)) + return -EINVAL; + + bprm->cap_permitted = to_cap_t( le32_to_cpu(caps[1]) ); + bprm->cap_inheritable = to_cap_t( le32_to_cpu(caps[3]) ); + return 0; +} +#else +static inline int read_v2_caps(__le32 *caps, struct linux_binprm *bprm) +{ + bprm->cap_permitted = to_cap_t( le32_to_cpu(caps[1]) ); + bprm->cap_inheritable = to_cap_t( le32_to_cpu(caps[3]) ); + return 0; +} +#endif + +static inline int cap_size_valid(int size) +{ + if (size == XATTR_CAPS_SZ) + return 1; +#ifndef CONFIG_SECURITYFILE_CAPS_STRICT + if (size == XATTR_CAPS_SZ) + return 1; +#endif + return 0; + +} + static inline int cap_from_disk(__le32 *caps, struct linux_binprm *bprm, int size) { __u32 magic_etc; - if (size != XATTR_CAPS_SZ) + if (!cap_size_valid(size)) return -EINVAL; magic_etc = le32_to_cpu(caps[0]); switch ((magic_etc & VFS_CAP_REVISION_MASK)) { - case VFS_CAP_REVISION: + case VFS_CAP_REVISION_1: if (magic_etc & VFS_CAP_FLAGS_EFFECTIVE) bprm->cap_effective = true; else @@ -138,6 +170,12 @@ static inline int cap_from_disk(__le32 *caps, struct linux_binprm *bprm, bprm->cap_permitted = to_cap_t( le32_to_cpu(caps[1]) ); bprm->cap_inheritable = to_cap_t( le32_to_cpu(caps[2]) ); return 0; + case VFS_CAP_REVISION_2: + if (magic_etc & VFS_CAP_FLAGS_EFFECTIVE) + bprm->cap_effective = true; + else + bprm->cap_effective = false; + return read_v2_caps(caps, bprm); default: return -EINVAL; } -- 1.5.1.1.GIT - To unsubscribe from this list: send the line "unsubscribe linux-security-module" in the body of a message to [EMAIL PROTECTED] More majordomo info at http://vger.kernel.org/majordomo-info.html