From 9090a2d5e3e6f1f1f1aabd44f9335ff873239b60 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Thu, 28 Jan 2016 14:59:16 +0200 Subject: selinux: use absolute path to include directory Compiler warns us a lot that it can't find include folder because it's provided in relative form. CC security/selinux/netlabel.o cc1: warning: security/selinux/include: No such file or directory cc1: warning: security/selinux/include: No such file or directory cc1: warning: security/selinux/include: No such file or directory cc1: warning: security/selinux/include: No such file or directory Add $(srctree) prefix to the path. Signed-off-by: Andy Shevchenko [PM: minor description edits to fit under 80char width] Signed-off-by: Paul Moore --- security/selinux/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'security') diff --git a/security/selinux/Makefile b/security/selinux/Makefile index ad5cd76ec231..3411c33e2a44 100644 --- a/security/selinux/Makefile +++ b/security/selinux/Makefile @@ -13,7 +13,7 @@ selinux-$(CONFIG_SECURITY_NETWORK_XFRM) += xfrm.o selinux-$(CONFIG_NETLABEL) += netlabel.o -ccflags-y := -Isecurity/selinux -Isecurity/selinux/include +ccflags-y := -I$(srctree)/security/selinux -I$(srctree)/security/selinux/include $(addprefix $(obj)/,$(selinux-y)): $(obj)/flask.h -- cgit v1.2.3 From c75d8e96f377b59b887a81b31adb00dd1957c3c8 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 20 Jan 2016 11:13:46 +0000 Subject: IMA: fix non-ANSI declaration of ima_check_policy() ima_check_policy() has no parameters, so use the normal void parameter convention to make it match the prototype in the header file security/integrity/ima/ima.h Signed-off-by: Colin Ian King Signed-off-by: Mimi Zohar --- security/integrity/ima/ima_policy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'security') diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 0a3b781f18e5..e0e18cc5930a 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -417,7 +417,7 @@ void __init ima_init_policy(void) } /* Make sure we have a valid policy, at least containing some rules. */ -int ima_check_policy() +int ima_check_policy(void) { if (list_empty(&ima_temp_rules)) return -EINVAL; -- cgit v1.2.3 From 5d2787cf0b210d2925e8d44e2e79241385249d6b Mon Sep 17 00:00:00 2001 From: David Howells Date: Tue, 9 Feb 2016 16:40:46 +0000 Subject: KEYS: Add an alloc flag to convey the builtinness of a key Add KEY_ALLOC_BUILT_IN to convey that a key should have KEY_FLAG_BUILTIN set rather than setting it after the fact. Signed-off-by: David Howells Acked-by: Mimi Zohar --- certs/system_keyring.c | 4 ++-- include/linux/key.h | 1 + security/keys/key.c | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) (limited to 'security') diff --git a/certs/system_keyring.c b/certs/system_keyring.c index 2570598b784d..f4180326c2e1 100644 --- a/certs/system_keyring.c +++ b/certs/system_keyring.c @@ -84,12 +84,12 @@ static __init int load_system_certificate_list(void) ((KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW | KEY_USR_READ), KEY_ALLOC_NOT_IN_QUOTA | - KEY_ALLOC_TRUSTED); + KEY_ALLOC_TRUSTED | + KEY_ALLOC_BUILT_IN); if (IS_ERR(key)) { pr_err("Problem loading in-kernel X.509 certificate (%ld)\n", PTR_ERR(key)); } else { - set_bit(KEY_FLAG_BUILTIN, &key_ref_to_ptr(key)->flags); pr_notice("Loaded X.509 cert '%s'\n", key_ref_to_ptr(key)->description); key_ref_put(key); diff --git a/include/linux/key.h b/include/linux/key.h index 7321ab8ef949..5f5b1129dc92 100644 --- a/include/linux/key.h +++ b/include/linux/key.h @@ -219,6 +219,7 @@ extern struct key *key_alloc(struct key_type *type, #define KEY_ALLOC_QUOTA_OVERRUN 0x0001 /* add to quota, permit even if overrun */ #define KEY_ALLOC_NOT_IN_QUOTA 0x0002 /* not in quota */ #define KEY_ALLOC_TRUSTED 0x0004 /* Key should be flagged as trusted */ +#define KEY_ALLOC_BUILT_IN 0x0008 /* Key is built into kernel */ extern void key_revoke(struct key *key); extern void key_invalidate(struct key *key); diff --git a/security/keys/key.c b/security/keys/key.c index 09ef276c4bdc..b28755131687 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -296,6 +296,8 @@ struct key *key_alloc(struct key_type *type, const char *desc, key->flags |= 1 << KEY_FLAG_IN_QUOTA; if (flags & KEY_ALLOC_TRUSTED) key->flags |= 1 << KEY_FLAG_TRUSTED; + if (flags & KEY_ALLOC_BUILT_IN) + key->flags |= 1 << KEY_FLAG_BUILTIN; #ifdef KEY_DEBUGGING key->magic = KEY_DEBUG_MAGIC; -- cgit v1.2.3 From f3c82ade7c59303167d56b0be3e0707751fc45e2 Mon Sep 17 00:00:00 2001 From: Jarkko Sakkinen Date: Wed, 6 Jan 2016 16:43:30 +0200 Subject: tpm: fix checks for policy digest existence in tpm2_seal_trusted() In my original patch sealing with policy was done with dynamically allocated buffer that I changed later into an array so the checks in tpm2-cmd.c became invalid. This patch fixes the issue. Fixes: 5beb0c435bdd ("keys, trusted: seal with a TPM2 authorization policy") Reported-by: Dan Carpenter Signed-off-by: Jarkko Sakkinen Acked-by: Peter Huewe --- drivers/char/tpm/tpm2-cmd.c | 12 ++++-------- include/keys/trusted-type.h | 2 +- security/keys/trusted.c | 11 +++++------ 3 files changed, 10 insertions(+), 15 deletions(-) (limited to 'security') diff --git a/drivers/char/tpm/tpm2-cmd.c b/drivers/char/tpm/tpm2-cmd.c index 45a634016f95..66e04b41a73d 100644 --- a/drivers/char/tpm/tpm2-cmd.c +++ b/drivers/char/tpm/tpm2-cmd.c @@ -478,20 +478,16 @@ int tpm2_seal_trusted(struct tpm_chip *chip, tpm_buf_append_u8(&buf, payload->migratable); /* public */ - if (options->policydigest) - tpm_buf_append_u16(&buf, 14 + options->digest_len); - else - tpm_buf_append_u16(&buf, 14); - + tpm_buf_append_u16(&buf, 14 + options->policydigest_len); tpm_buf_append_u16(&buf, TPM2_ALG_KEYEDHASH); tpm_buf_append_u16(&buf, hash); /* policy */ - if (options->policydigest) { + if (options->policydigest_len) { tpm_buf_append_u32(&buf, 0); - tpm_buf_append_u16(&buf, options->digest_len); + tpm_buf_append_u16(&buf, options->policydigest_len); tpm_buf_append(&buf, options->policydigest, - options->digest_len); + options->policydigest_len); } else { tpm_buf_append_u32(&buf, TPM2_ATTR_USER_WITH_AUTH); tpm_buf_append_u16(&buf, 0); diff --git a/include/keys/trusted-type.h b/include/keys/trusted-type.h index 42cf2d991bf4..4ea7e55f20b0 100644 --- a/include/keys/trusted-type.h +++ b/include/keys/trusted-type.h @@ -38,7 +38,7 @@ struct trusted_key_options { unsigned char pcrinfo[MAX_PCRINFO_SIZE]; int pcrlock; uint32_t hash; - uint32_t digest_len; + uint32_t policydigest_len; unsigned char policydigest[MAX_DIGEST_SIZE]; uint32_t policyhandle; }; diff --git a/security/keys/trusted.c b/security/keys/trusted.c index 0dcab20cdacd..90d61751ff12 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c @@ -744,6 +744,7 @@ static int getoptions(char *c, struct trusted_key_payload *pay, unsigned long handle; unsigned long lock; unsigned long token_mask = 0; + unsigned int digest_len; int i; int tpm2; @@ -752,7 +753,6 @@ static int getoptions(char *c, struct trusted_key_payload *pay, return tpm2; opt->hash = tpm2 ? HASH_ALGO_SHA256 : HASH_ALGO_SHA1; - opt->digest_len = hash_digest_size[opt->hash]; while ((p = strsep(&c, " \t"))) { if (*p == '\0' || *p == ' ' || *p == '\t') @@ -812,8 +812,6 @@ static int getoptions(char *c, struct trusted_key_payload *pay, for (i = 0; i < HASH_ALGO__LAST; i++) { if (!strcmp(args[0].from, hash_algo_name[i])) { opt->hash = i; - opt->digest_len = - hash_digest_size[opt->hash]; break; } } @@ -825,13 +823,14 @@ static int getoptions(char *c, struct trusted_key_payload *pay, } break; case Opt_policydigest: - if (!tpm2 || - strlen(args[0].from) != (2 * opt->digest_len)) + digest_len = hash_digest_size[opt->hash]; + if (!tpm2 || strlen(args[0].from) != (2 * digest_len)) return -EINVAL; res = hex2bin(opt->policydigest, args[0].from, - opt->digest_len); + digest_len); if (res < 0) return -EINVAL; + opt->policydigest_len = digest_len; break; case Opt_policyhandle: if (!tpm2) -- cgit v1.2.3 From 50d35015ff0c00a464e35b109231145d2beec1bd Mon Sep 17 00:00:00 2001 From: David Howells Date: Wed, 3 Feb 2016 15:04:40 +0000 Subject: KEYS: CONFIG_KEYS_DEBUG_PROC_KEYS is no longer an option CONFIG_KEYS_DEBUG_PROC_KEYS is no longer an option as /proc/keys is now mandatory if the keyrings facility is enabled (it's used by libkeyutils in userspace). The defconfig references were removed with: perl -p -i -e 's/CONFIG_KEYS_DEBUG_PROC_KEYS=y\n//' \ `git grep -l CONFIG_KEYS_DEBUG_PROC_KEYS=y` and the integrity Kconfig fixed by hand. Signed-off-by: David Howells cc: Andreas Ziegler cc: Dmitry Kasatkin --- arch/arm/configs/colibri_pxa270_defconfig | 1 - arch/arm/configs/iop13xx_defconfig | 1 - arch/arm/configs/iop32x_defconfig | 1 - arch/arm/configs/trizeps4_defconfig | 1 - arch/microblaze/configs/mmu_defconfig | 1 - arch/microblaze/configs/nommu_defconfig | 1 - arch/mips/configs/bigsur_defconfig | 1 - arch/mips/configs/ip22_defconfig | 1 - arch/mips/configs/ip27_defconfig | 1 - arch/mips/configs/ip32_defconfig | 1 - arch/mips/configs/jazz_defconfig | 1 - arch/mips/configs/lemote2f_defconfig | 1 - arch/mips/configs/rm200_defconfig | 1 - arch/mips/configs/sb1250_swarm_defconfig | 1 - arch/parisc/configs/712_defconfig | 1 - arch/parisc/configs/a500_defconfig | 1 - arch/parisc/configs/default_defconfig | 1 - arch/parisc/configs/generic-32bit_defconfig | 1 - arch/powerpc/configs/c2k_defconfig | 1 - arch/powerpc/configs/ppc6xx_defconfig | 1 - arch/score/configs/spct6600_defconfig | 1 - arch/tile/configs/tilegx_defconfig | 1 - arch/tile/configs/tilepro_defconfig | 1 - arch/x86/configs/i386_defconfig | 1 - arch/x86/configs/x86_64_defconfig | 1 - security/integrity/Kconfig | 1 - 26 files changed, 26 deletions(-) (limited to 'security') diff --git a/arch/arm/configs/colibri_pxa270_defconfig b/arch/arm/configs/colibri_pxa270_defconfig index 18c311ae1113..0b9211b2b73b 100644 --- a/arch/arm/configs/colibri_pxa270_defconfig +++ b/arch/arm/configs/colibri_pxa270_defconfig @@ -166,7 +166,6 @@ CONFIG_DEBUG_USER=y CONFIG_DEBUG_ERRORS=y CONFIG_DEBUG_LL=y CONFIG_KEYS=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_SECURITY=y CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_SHA1=m diff --git a/arch/arm/configs/iop13xx_defconfig b/arch/arm/configs/iop13xx_defconfig index 4fa94a1f115b..652b7bd9e544 100644 --- a/arch/arm/configs/iop13xx_defconfig +++ b/arch/arm/configs/iop13xx_defconfig @@ -95,7 +95,6 @@ CONFIG_PARTITION_ADVANCED=y CONFIG_NLS=y CONFIG_DEBUG_USER=y CONFIG_KEYS=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_CRYPTO_NULL=y CONFIG_CRYPTO_LRW=y CONFIG_CRYPTO_PCBC=m diff --git a/arch/arm/configs/iop32x_defconfig b/arch/arm/configs/iop32x_defconfig index c3058da631da..aa3af0a6b8f7 100644 --- a/arch/arm/configs/iop32x_defconfig +++ b/arch/arm/configs/iop32x_defconfig @@ -108,7 +108,6 @@ CONFIG_DEBUG_USER=y CONFIG_DEBUG_LL=y CONFIG_DEBUG_LL_UART_8250=y CONFIG_KEYS=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_CRYPTO_NULL=y CONFIG_CRYPTO_LRW=y CONFIG_CRYPTO_PCBC=m diff --git a/arch/arm/configs/trizeps4_defconfig b/arch/arm/configs/trizeps4_defconfig index 4bc870028035..0ada29d568ec 100644 --- a/arch/arm/configs/trizeps4_defconfig +++ b/arch/arm/configs/trizeps4_defconfig @@ -214,7 +214,6 @@ CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_FS=y CONFIG_DEBUG_USER=y CONFIG_KEYS=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_SECURITY=y CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_SHA256=m diff --git a/arch/microblaze/configs/mmu_defconfig b/arch/microblaze/configs/mmu_defconfig index e2f6543b91e7..dc5dd5b69fde 100644 --- a/arch/microblaze/configs/mmu_defconfig +++ b/arch/microblaze/configs/mmu_defconfig @@ -87,5 +87,4 @@ CONFIG_KGDB_KDB=y CONFIG_EARLY_PRINTK=y CONFIG_KEYS=y CONFIG_ENCRYPTED_KEYS=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y # CONFIG_CRYPTO_ANSI_CPRNG is not set diff --git a/arch/microblaze/configs/nommu_defconfig b/arch/microblaze/configs/nommu_defconfig index a29ebd4a9fcb..4cdaf565e638 100644 --- a/arch/microblaze/configs/nommu_defconfig +++ b/arch/microblaze/configs/nommu_defconfig @@ -92,7 +92,6 @@ CONFIG_DEBUG_INFO=y CONFIG_EARLY_PRINTK=y CONFIG_KEYS=y CONFIG_ENCRYPTED_KEYS=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_CRYPTO_ECB=y CONFIG_CRYPTO_MD4=y CONFIG_CRYPTO_MD5=y diff --git a/arch/mips/configs/bigsur_defconfig b/arch/mips/configs/bigsur_defconfig index b3e7a1b61220..e070dac071c8 100644 --- a/arch/mips/configs/bigsur_defconfig +++ b/arch/mips/configs/bigsur_defconfig @@ -247,7 +247,6 @@ CONFIG_DEBUG_SPINLOCK_SLEEP=y CONFIG_DEBUG_MEMORY_INIT=y CONFIG_DEBUG_LIST=y CONFIG_KEYS=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_SECURITY=y CONFIG_SECURITY_NETWORK=y CONFIG_SECURITY_NETWORK_XFRM=y diff --git a/arch/mips/configs/ip22_defconfig b/arch/mips/configs/ip22_defconfig index 57ed466e00db..6ba9ce9fcdd5 100644 --- a/arch/mips/configs/ip22_defconfig +++ b/arch/mips/configs/ip22_defconfig @@ -358,7 +358,6 @@ CONFIG_DLM=m CONFIG_DEBUG_MEMORY_INIT=y # CONFIG_RCU_CPU_STALL_DETECTOR is not set CONFIG_KEYS=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_CRYPTO_FIPS=y CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_CRYPTD=m diff --git a/arch/mips/configs/ip27_defconfig b/arch/mips/configs/ip27_defconfig index 48e16d98b2cc..77e9f505f5e4 100644 --- a/arch/mips/configs/ip27_defconfig +++ b/arch/mips/configs/ip27_defconfig @@ -346,7 +346,6 @@ CONFIG_PARTITION_ADVANCED=y CONFIG_DLM=m # CONFIG_RCU_CPU_STALL_DETECTOR is not set CONFIG_KEYS=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_SECURITYFS=y CONFIG_CRYPTO_FIPS=y CONFIG_CRYPTO_NULL=m diff --git a/arch/mips/configs/ip32_defconfig b/arch/mips/configs/ip32_defconfig index fe48220157a9..f9af98f63cff 100644 --- a/arch/mips/configs/ip32_defconfig +++ b/arch/mips/configs/ip32_defconfig @@ -181,7 +181,6 @@ CONFIG_MAGIC_SYSRQ=y # CONFIG_RCU_CPU_STALL_DETECTOR is not set CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_KEYS=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_CRYPTO_NULL=y CONFIG_CRYPTO_CBC=y CONFIG_CRYPTO_ECB=y diff --git a/arch/mips/configs/jazz_defconfig b/arch/mips/configs/jazz_defconfig index 4f37a5985459..a5e85e1ee5de 100644 --- a/arch/mips/configs/jazz_defconfig +++ b/arch/mips/configs/jazz_defconfig @@ -362,7 +362,6 @@ CONFIG_NLS_KOI8_R=m CONFIG_NLS_KOI8_U=m CONFIG_NLS_UTF8=m CONFIG_DLM=m -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_LRW=m diff --git a/arch/mips/configs/lemote2f_defconfig b/arch/mips/configs/lemote2f_defconfig index 004cf52d1b7d..d1f198b072a0 100644 --- a/arch/mips/configs/lemote2f_defconfig +++ b/arch/mips/configs/lemote2f_defconfig @@ -412,7 +412,6 @@ CONFIG_DEBUG_FS=y # CONFIG_RCU_CPU_STALL_DETECTOR is not set CONFIG_SYSCTL_SYSCALL_CHECK=y CONFIG_KEYS=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_CRYPTO_FIPS=y CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_CRYPTD=m diff --git a/arch/mips/configs/rm200_defconfig b/arch/mips/configs/rm200_defconfig index db029f4ff759..82db4e3e4cf1 100644 --- a/arch/mips/configs/rm200_defconfig +++ b/arch/mips/configs/rm200_defconfig @@ -453,7 +453,6 @@ CONFIG_NLS_KOI8_R=m CONFIG_NLS_KOI8_U=m CONFIG_NLS_UTF8=m CONFIG_DLM=m -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_LRW=m diff --git a/arch/mips/configs/sb1250_swarm_defconfig b/arch/mips/configs/sb1250_swarm_defconfig index 51bab13ef6f8..7fca09fedb59 100644 --- a/arch/mips/configs/sb1250_swarm_defconfig +++ b/arch/mips/configs/sb1250_swarm_defconfig @@ -87,7 +87,6 @@ CONFIG_NFS_V3=y CONFIG_ROOT_NFS=y CONFIG_DLM=m CONFIG_KEYS=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_CRYPTD=m CONFIG_CRYPTO_AUTHENC=m diff --git a/arch/parisc/configs/712_defconfig b/arch/parisc/configs/712_defconfig index 9387cc2693f6..db8f56bf3883 100644 --- a/arch/parisc/configs/712_defconfig +++ b/arch/parisc/configs/712_defconfig @@ -183,7 +183,6 @@ CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_MUTEXES=y # CONFIG_RCU_CPU_STALL_DETECTOR is not set CONFIG_DEBUG_RODATA=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_HMAC=y diff --git a/arch/parisc/configs/a500_defconfig b/arch/parisc/configs/a500_defconfig index 0490199d7b15..1a4f776b49b8 100644 --- a/arch/parisc/configs/a500_defconfig +++ b/arch/parisc/configs/a500_defconfig @@ -193,7 +193,6 @@ CONFIG_HEADERS_CHECK=y CONFIG_DEBUG_KERNEL=y # CONFIG_DEBUG_BUGVERBOSE is not set # CONFIG_RCU_CPU_STALL_DETECTOR is not set -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_HMAC=y diff --git a/arch/parisc/configs/default_defconfig b/arch/parisc/configs/default_defconfig index 4d8127e8428a..310b6657e4ac 100644 --- a/arch/parisc/configs/default_defconfig +++ b/arch/parisc/configs/default_defconfig @@ -211,7 +211,6 @@ CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_MUTEXES=y # CONFIG_RCU_CPU_STALL_DETECTOR is not set CONFIG_KEYS=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_MD4=m diff --git a/arch/parisc/configs/generic-32bit_defconfig b/arch/parisc/configs/generic-32bit_defconfig index 0ffb08ff5125..5b04d703a924 100644 --- a/arch/parisc/configs/generic-32bit_defconfig +++ b/arch/parisc/configs/generic-32bit_defconfig @@ -301,7 +301,6 @@ CONFIG_RCU_CPU_STALL_INFO=y CONFIG_LATENCYTOP=y CONFIG_LKDTM=m CONFIG_KEYS=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_CRYPTO_NULL=m CONFIG_CRYPTO_TEST=m CONFIG_CRYPTO_HMAC=y diff --git a/arch/powerpc/configs/c2k_defconfig b/arch/powerpc/configs/c2k_defconfig index 91862292cd55..340685caa7b8 100644 --- a/arch/powerpc/configs/c2k_defconfig +++ b/arch/powerpc/configs/c2k_defconfig @@ -387,7 +387,6 @@ CONFIG_DETECT_HUNG_TASK=y CONFIG_DEBUG_SPINLOCK=y CONFIG_BOOTX_TEXT=y CONFIG_PPC_EARLY_DEBUG=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_SECURITY=y CONFIG_SECURITY_NETWORK=y CONFIG_SECURITY_SELINUX=y diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig index e5d2c3dc07f1..99ccbebabfd3 100644 --- a/arch/powerpc/configs/ppc6xx_defconfig +++ b/arch/powerpc/configs/ppc6xx_defconfig @@ -1175,7 +1175,6 @@ CONFIG_BLK_DEV_IO_TRACE=y CONFIG_XMON=y CONFIG_BOOTX_TEXT=y CONFIG_PPC_EARLY_DEBUG=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_SECURITY=y CONFIG_SECURITY_NETWORK=y CONFIG_SECURITY_NETWORK_XFRM=y diff --git a/arch/score/configs/spct6600_defconfig b/arch/score/configs/spct6600_defconfig index df1edbf507a2..b2d8802f43b4 100644 --- a/arch/score/configs/spct6600_defconfig +++ b/arch/score/configs/spct6600_defconfig @@ -70,7 +70,6 @@ CONFIG_NFSD=y CONFIG_NFSD_V3_ACL=y CONFIG_NFSD_V4=y # CONFIG_RCU_CPU_STALL_DETECTOR is not set -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_SECURITY=y CONFIG_SECURITY_NETWORK=y CONFIG_CRYPTO_NULL=y diff --git a/arch/tile/configs/tilegx_defconfig b/arch/tile/configs/tilegx_defconfig index 37dc9364c4a1..c1387b7f447d 100644 --- a/arch/tile/configs/tilegx_defconfig +++ b/arch/tile/configs/tilegx_defconfig @@ -374,7 +374,6 @@ CONFIG_DEBUG_CREDENTIALS=y CONFIG_RCU_CPU_STALL_TIMEOUT=60 CONFIG_ASYNC_RAID6_TEST=m CONFIG_KGDB=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_SECURITY=y CONFIG_SECURITYFS=y CONFIG_SECURITY_NETWORK=y diff --git a/arch/tile/configs/tilepro_defconfig b/arch/tile/configs/tilepro_defconfig index 76a2781dec2c..6d9ce8af1107 100644 --- a/arch/tile/configs/tilepro_defconfig +++ b/arch/tile/configs/tilepro_defconfig @@ -486,7 +486,6 @@ CONFIG_DEBUG_LIST=y CONFIG_DEBUG_CREDENTIALS=y CONFIG_RCU_CPU_STALL_TIMEOUT=60 CONFIG_ASYNC_RAID6_TEST=m -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_SECURITY=y CONFIG_SECURITYFS=y CONFIG_SECURITY_NETWORK=y diff --git a/arch/x86/configs/i386_defconfig b/arch/x86/configs/i386_defconfig index 028be48c8839..a212b68a4909 100644 --- a/arch/x86/configs/i386_defconfig +++ b/arch/x86/configs/i386_defconfig @@ -303,7 +303,6 @@ CONFIG_DEBUG_STACKOVERFLOW=y # CONFIG_DEBUG_RODATA_TEST is not set CONFIG_DEBUG_BOOT_PARAMS=y CONFIG_OPTIMIZE_INLINING=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_SECURITY=y CONFIG_SECURITY_NETWORK=y CONFIG_SECURITY_SELINUX=y diff --git a/arch/x86/configs/x86_64_defconfig b/arch/x86/configs/x86_64_defconfig index cb5b3ab5beec..4f404a64681b 100644 --- a/arch/x86/configs/x86_64_defconfig +++ b/arch/x86/configs/x86_64_defconfig @@ -300,7 +300,6 @@ CONFIG_DEBUG_STACKOVERFLOW=y # CONFIG_DEBUG_RODATA_TEST is not set CONFIG_DEBUG_BOOT_PARAMS=y CONFIG_OPTIMIZE_INLINING=y -CONFIG_KEYS_DEBUG_PROC_KEYS=y CONFIG_SECURITY=y CONFIG_SECURITY_NETWORK=y CONFIG_SECURITY_SELINUX=y diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig index 21d756832b75..7543398b79e3 100644 --- a/security/integrity/Kconfig +++ b/security/integrity/Kconfig @@ -45,7 +45,6 @@ config INTEGRITY_TRUSTED_KEYRING bool "Require all keys on the integrity keyrings be signed" depends on SYSTEM_TRUSTED_KEYRING depends on INTEGRITY_ASYMMETRIC_KEYS - select KEYS_DEBUG_PROC_KEYS default y help This option requires that all keys added to the .ima and -- cgit v1.2.3 From 491a0b08d38e7f0961a1850d43d0dea02f918d66 Mon Sep 17 00:00:00 2001 From: Casey Schaufler Date: Tue, 26 Jan 2016 15:08:35 -0800 Subject: Smack: Remove pointless hooks Prior to the 4.2 kernel there no no harm in providing a security module hook that does nothing, as the default hook would get called if the module did not supply one. With the list based infrastructure an empty hook adds overhead. This patch removes the three Smack hooks that don't actually do anything. Signed-off-by: Casey Schaufler --- security/smack/smack_lsm.c | 38 ++++++++------------------------------ 1 file changed, 8 insertions(+), 30 deletions(-) (limited to 'security') diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 2d6e9bdea398..2775d658b767 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1545,12 +1545,8 @@ static void smack_inode_getsecid(struct inode *inode, u32 *secid) * File Hooks */ -/** - * smack_file_permission - Smack check on file operations - * @file: unused - * @mask: unused - * - * Returns 0 +/* + * There is no smack_file_permission hook * * Should access checks be done on each read or write? * UNICOS and SELinux say yes. @@ -1559,10 +1555,6 @@ static void smack_inode_getsecid(struct inode *inode, u32 *secid) * I'll say no for now. Smack does not do the frequent * label changing that SELinux does. */ -static int smack_file_permission(struct file *file, int mask) -{ - return 0; -} /** * smack_file_alloc_security - assign a file security blob @@ -4503,16 +4495,10 @@ static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule, return 0; } -/** - * smack_audit_rule_free - free smack rule representation - * @vrule: rule to be freed. - * +/* + * There is no need for a smack_audit_rule_free hook. * No memory was allocated. */ -static void smack_audit_rule_free(void *vrule) -{ - /* No-op */ -} #endif /* CONFIG_AUDIT */ @@ -4563,16 +4549,11 @@ static int smack_secctx_to_secid(const char *secdata, u32 seclen, u32 *secid) return 0; } -/** - * smack_release_secctx - don't do anything. - * @secdata: unused - * @seclen: unused - * - * Exists to make sure nothing gets done, and properly +/* + * There used to be a smack_release_secctx hook + * that did nothing back when hooks were in a vector. + * Now that there's a list such a hook adds cost. */ -static void smack_release_secctx(char *secdata, u32 seclen) -{ -} static int smack_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen) { @@ -4631,7 +4612,6 @@ static struct security_hook_list smack_hooks[] = { LSM_HOOK_INIT(inode_listsecurity, smack_inode_listsecurity), LSM_HOOK_INIT(inode_getsecid, smack_inode_getsecid), - LSM_HOOK_INIT(file_permission, smack_file_permission), LSM_HOOK_INIT(file_alloc_security, smack_file_alloc_security), LSM_HOOK_INIT(file_free_security, smack_file_free_security), LSM_HOOK_INIT(file_ioctl, smack_file_ioctl), @@ -4726,13 +4706,11 @@ static struct security_hook_list smack_hooks[] = { LSM_HOOK_INIT(audit_rule_init, smack_audit_rule_init), LSM_HOOK_INIT(audit_rule_known, smack_audit_rule_known), LSM_HOOK_INIT(audit_rule_match, smack_audit_rule_match), - LSM_HOOK_INIT(audit_rule_free, smack_audit_rule_free), #endif /* CONFIG_AUDIT */ LSM_HOOK_INIT(ismaclabel, smack_ismaclabel), LSM_HOOK_INIT(secid_to_secctx, smack_secid_to_secctx), LSM_HOOK_INIT(secctx_to_secid, smack_secctx_to_secid), - LSM_HOOK_INIT(release_secctx, smack_release_secctx), LSM_HOOK_INIT(inode_notifysecctx, smack_inode_notifysecctx), LSM_HOOK_INIT(inode_setsecctx, smack_inode_setsecctx), LSM_HOOK_INIT(inode_getsecctx, smack_inode_getsecctx), -- cgit v1.2.3 From 8012495e177bbf67eba8915e266a6f897bedbd53 Mon Sep 17 00:00:00 2001 From: José Bollo Date: Tue, 12 Jan 2016 21:23:40 +0100 Subject: smack: fix cache of access labels MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Before this commit, removing the access property of a file, aka, the extended attribute security.SMACK64 was not effictive until the cache had been cleaned. This patch fixes that problem. Signed-off-by: José Bollo Acked-by: Casey Schaufler --- security/smack/smack_lsm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'security') diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c index 2775d658b767..11f79013ae1f 100644 --- a/security/smack/smack_lsm.c +++ b/security/smack/smack_lsm.c @@ -1442,9 +1442,13 @@ static int smack_inode_removexattr(struct dentry *dentry, const char *name) * Don't do anything special for these. * XATTR_NAME_SMACKIPIN * XATTR_NAME_SMACKIPOUT - * XATTR_NAME_SMACKEXEC */ - if (strcmp(name, XATTR_NAME_SMACK) == 0) + if (strcmp(name, XATTR_NAME_SMACK) == 0) { + struct super_block *sbp = d_backing_inode(dentry)->i_sb; + struct superblock_smack *sbsp = sbp->s_security; + + isp->smk_inode = sbsp->smk_default; + } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0) isp->smk_task = NULL; else if (strcmp(name, XATTR_NAME_SMACKMMAP) == 0) isp->smk_mmap = NULL; -- cgit v1.2.3 From eb5798f2e28f3b43091cecc71c84c3f6fb35c7de Mon Sep 17 00:00:00 2001 From: Tadeusz Struk Date: Tue, 2 Feb 2016 10:08:58 -0800 Subject: integrity: convert digsig to akcipher api Convert asymmetric_verify to akcipher api. Signed-off-by: Tadeusz Struk Acked-by: Herbert Xu Signed-off-by: David Howells --- security/integrity/Kconfig | 1 + security/integrity/digsig_asymmetric.c | 10 +++------- 2 files changed, 4 insertions(+), 7 deletions(-) (limited to 'security') diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig index 7543398b79e3..979be65d22c4 100644 --- a/security/integrity/Kconfig +++ b/security/integrity/Kconfig @@ -36,6 +36,7 @@ config INTEGRITY_ASYMMETRIC_KEYS select ASYMMETRIC_KEY_TYPE select ASYMMETRIC_PUBLIC_KEY_SUBTYPE select PUBLIC_KEY_ALGO_RSA + select CRYPTO_RSA select X509_CERTIFICATE_PARSER help This option enables digital signature verification using diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c index 5ade2a7517a6..2fa3bc681a1b 100644 --- a/security/integrity/digsig_asymmetric.c +++ b/security/integrity/digsig_asymmetric.c @@ -106,13 +106,9 @@ int asymmetric_verify(struct key *keyring, const char *sig, pks.pkey_hash_algo = hdr->hash_algo; pks.digest = (u8 *)data; pks.digest_size = datalen; - pks.nr_mpi = 1; - pks.rsa.s = mpi_read_raw_data(hdr->sig, siglen); - - if (pks.rsa.s) - ret = verify_signature(key, &pks); - - mpi_free(pks.rsa.s); + pks.s = hdr->sig; + pks.s_size = siglen; + ret = verify_signature(key, &pks); key_put(key); pr_debug("%s() = %d\n", __func__, ret); return ret; -- cgit v1.2.3 From a1f2bdf338f15dbad10ee6362891ebf79244858b Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Wed, 9 Dec 2015 17:37:15 -0500 Subject: security/keys: make big_key.c explicitly non-modular The Kconfig currently controlling compilation of this code is: config BIG_KEYS bool "Large payload keys" ...meaning that it currently is not being built as a module by anyone. Lets remove the modular code that is essentially orphaned, so that when reading the driver there is no doubt it is builtin-only. Since module_init translates to device_initcall in the non-modular case, the init ordering remains unchanged with this commit. We also delete the MODULE_LICENSE tag since all that information is already contained at the top of the file in the comments. Cc: James Morris Cc: "Serge E. Hallyn" Cc: keyrings@vger.kernel.org Cc: linux-security-module@vger.kernel.org Signed-off-by: Paul Gortmaker Signed-off-by: David Howells --- security/keys/big_key.c | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) (limited to 'security') diff --git a/security/keys/big_key.c b/security/keys/big_key.c index 907c1522ee46..c721e398893a 100644 --- a/security/keys/big_key.c +++ b/security/keys/big_key.c @@ -9,7 +9,6 @@ * 2 of the Licence, or (at your option) any later version. */ -#include #include #include #include @@ -18,8 +17,6 @@ #include #include -MODULE_LICENSE("GPL"); - /* * Layout of key payload words. */ @@ -212,18 +209,8 @@ long big_key_read(const struct key *key, char __user *buffer, size_t buflen) return ret; } -/* - * Module stuff - */ static int __init big_key_init(void) { return register_key_type(&key_type_big_key); } - -static void __exit big_key_cleanup(void) -{ - unregister_key_type(&key_type_big_key); -} - -module_init(big_key_init); -module_exit(big_key_cleanup); +device_initcall(big_key_init); -- cgit v1.2.3 From 1525b06d99b117198ea8d6c128ee5bf28ceb6723 Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Thu, 30 Oct 2014 12:39:39 +0200 Subject: ima: separate 'security.ima' reading functionality from collect Instead of passing pointers to pointers to ima_collect_measurent() to read and return the 'security.ima' xattr value, this patch moves the functionality to the calling process_measurement() to directly read the xattr and pass only the hash algo to the ima_collect_measurement(). Signed-off-by: Dmitry Kasatkin Signed-off-by: Mimi Zohar --- security/integrity/ima/ima.h | 15 +++++++-------- security/integrity/ima/ima_api.c | 15 +++------------ security/integrity/ima/ima_appraise.c | 25 ++++++++++++++----------- security/integrity/ima/ima_crypto.c | 2 +- security/integrity/ima/ima_init.c | 2 +- security/integrity/ima/ima_main.c | 11 +++++++---- security/integrity/ima/ima_template.c | 2 -- security/integrity/ima/ima_template_lib.c | 1 - 8 files changed, 33 insertions(+), 40 deletions(-) (limited to 'security') diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 585af61ed399..fb8da36b1d86 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -23,6 +23,7 @@ #include #include #include +#include #include "../integrity.h" @@ -140,9 +141,7 @@ static inline unsigned long ima_hash_key(u8 *digest) int ima_get_action(struct inode *inode, int mask, int function); int ima_must_measure(struct inode *inode, int mask, int function); int ima_collect_measurement(struct integrity_iint_cache *iint, - struct file *file, - struct evm_ima_xattr_data **xattr_value, - int *xattr_len); + struct file *file, enum hash_algo algo); void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file, const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, @@ -188,8 +187,8 @@ int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func); void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file); enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, int func); -void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len, - struct ima_digest_data *hash); +enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, + int xattr_len); int ima_read_xattr(struct dentry *dentry, struct evm_ima_xattr_data **xattr_value); @@ -221,10 +220,10 @@ static inline enum integrity_status ima_get_cache_status(struct integrity_iint_c return INTEGRITY_UNKNOWN; } -static inline void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, - int xattr_len, - struct ima_digest_data *hash) +static inline enum hash_algo +ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len) { + return ima_hash_algo; } static inline int ima_read_xattr(struct dentry *dentry, diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 1d950fbb2aec..e7c7a5d41413 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -18,7 +18,7 @@ #include #include #include -#include + #include "ima.h" /* @@ -188,9 +188,7 @@ int ima_get_action(struct inode *inode, int mask, int function) * Return 0 on success, error code otherwise */ int ima_collect_measurement(struct integrity_iint_cache *iint, - struct file *file, - struct evm_ima_xattr_data **xattr_value, - int *xattr_len) + struct file *file, enum hash_algo algo) { const char *audit_cause = "failed"; struct inode *inode = file_inode(file); @@ -201,9 +199,6 @@ int ima_collect_measurement(struct integrity_iint_cache *iint, char digest[IMA_MAX_DIGEST_SIZE]; } hash; - if (xattr_value) - *xattr_len = ima_read_xattr(file->f_path.dentry, xattr_value); - if (!(iint->flags & IMA_COLLECTED)) { u64 i_version = file_inode(file)->i_version; @@ -213,11 +208,7 @@ int ima_collect_measurement(struct integrity_iint_cache *iint, goto out; } - /* use default hash algorithm */ - hash.hdr.algo = ima_hash_algo; - - if (xattr_value) - ima_get_hash_algo(*xattr_value, *xattr_len, &hash.hdr); + hash.hdr.algo = algo; result = ima_calc_file_hash(file, &hash.hdr); if (!result) { diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 1873b5536f80..9c2b46b90be8 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -15,7 +15,6 @@ #include #include #include -#include #include "ima.h" @@ -130,36 +129,40 @@ static void ima_cache_flags(struct integrity_iint_cache *iint, int func) } } -void ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len, - struct ima_digest_data *hash) +enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, + int xattr_len) { struct signature_v2_hdr *sig; if (!xattr_value || xattr_len < 2) - return; + /* return default hash algo */ + return ima_hash_algo; switch (xattr_value->type) { case EVM_IMA_XATTR_DIGSIG: sig = (typeof(sig))xattr_value; if (sig->version != 2 || xattr_len <= sizeof(*sig)) - return; - hash->algo = sig->hash_algo; + return ima_hash_algo; + return sig->hash_algo; break; case IMA_XATTR_DIGEST_NG: - hash->algo = xattr_value->digest[0]; + return xattr_value->digest[0]; break; case IMA_XATTR_DIGEST: /* this is for backward compatibility */ if (xattr_len == 21) { unsigned int zero = 0; if (!memcmp(&xattr_value->digest[16], &zero, 4)) - hash->algo = HASH_ALGO_MD5; + return HASH_ALGO_MD5; else - hash->algo = HASH_ALGO_SHA1; + return HASH_ALGO_SHA1; } else if (xattr_len == 17) - hash->algo = HASH_ALGO_MD5; + return HASH_ALGO_MD5; break; } + + /* return default hash algo */ + return ima_hash_algo; } int ima_read_xattr(struct dentry *dentry, @@ -296,7 +299,7 @@ void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file) if (iint->flags & IMA_DIGSIG) return; - rc = ima_collect_measurement(iint, file, NULL, NULL); + rc = ima_collect_measurement(iint, file, ima_hash_algo); if (rc < 0) return; diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index 6eb62936c672..fb30ce406af4 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -24,7 +24,7 @@ #include #include #include -#include + #include "ima.h" struct ahash_completion { diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c index bd79f254d204..5d679a685616 100644 --- a/security/integrity/ima/ima_init.c +++ b/security/integrity/ima/ima_init.c @@ -21,7 +21,7 @@ #include #include #include -#include + #include "ima.h" /* name for boot aggregate entry */ diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 9d96551d0196..af4c3c1700b5 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -24,7 +24,6 @@ #include #include #include -#include #include "ima.h" @@ -163,9 +162,10 @@ static int process_measurement(struct file *file, int mask, int function, char *pathbuf = NULL; const char *pathname = NULL; int rc = -ENOMEM, action, must_appraise; - struct evm_ima_xattr_data *xattr_value = NULL, **xattr_ptr = NULL; + struct evm_ima_xattr_data *xattr_value = NULL; int xattr_len = 0; bool violation_check; + enum hash_algo hash_algo; if (!ima_policy_flag || !S_ISREG(inode->i_mode)) return 0; @@ -221,9 +221,12 @@ static int process_measurement(struct file *file, int mask, int function, template_desc = ima_template_desc_current(); if ((action & IMA_APPRAISE_SUBMASK) || strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0) - xattr_ptr = &xattr_value; + /* read 'security.ima' */ + xattr_len = ima_read_xattr(file->f_path.dentry, &xattr_value); - rc = ima_collect_measurement(iint, file, xattr_ptr, &xattr_len); + hash_algo = ima_get_hash_algo(xattr_value, xattr_len); + + rc = ima_collect_measurement(iint, file, hash_algo); if (rc != 0) { if (file->f_flags & O_DIRECT) rc = (iint->flags & IMA_PERMIT_DIRECTIO) ? 0 : -EACCES; diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c index 0b7404ebfa80..febd12ed9b55 100644 --- a/security/integrity/ima/ima_template.c +++ b/security/integrity/ima/ima_template.c @@ -15,8 +15,6 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include - #include "ima.h" #include "ima_template_lib.h" diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c index 2934e3d377f1..f9bae04ba176 100644 --- a/security/integrity/ima/ima_template_lib.c +++ b/security/integrity/ima/ima_template_lib.c @@ -12,7 +12,6 @@ * File: ima_template_lib.c * Library of supported template fields. */ -#include #include "ima_template_lib.h" -- cgit v1.2.3 From b5269ab3e29b17e3419c65986bcc1b54b798acc2 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Thu, 28 Jan 2016 13:10:36 -0500 Subject: ima: refactor ima_policy_show() to display "ima_hooks" rules Define and call a function to display the "ima_hooks" rules. Signed-off-by: Mimi Zohar Acked-by: Petko Manolov Acked-by: Dmitry Kasatkin --- security/integrity/ima/ima_policy.c | 63 +++++++++++++++++++++---------------- 1 file changed, 36 insertions(+), 27 deletions(-) (limited to 'security') diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index e0e18cc5930a..43b642557d6c 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -903,6 +903,40 @@ void ima_policy_stop(struct seq_file *m, void *v) #define mt(token) mask_tokens[token] #define ft(token) func_tokens[token] +/* + * policy_func_show - display the ima_hooks policy rule + */ +static void policy_func_show(struct seq_file *m, enum ima_hooks func) +{ + char tbuf[64] = {0,}; + + switch (func) { + case FILE_CHECK: + seq_printf(m, pt(Opt_func), ft(func_file)); + break; + case MMAP_CHECK: + seq_printf(m, pt(Opt_func), ft(func_mmap)); + break; + case BPRM_CHECK: + seq_printf(m, pt(Opt_func), ft(func_bprm)); + break; + case MODULE_CHECK: + seq_printf(m, pt(Opt_func), ft(func_module)); + break; + case FIRMWARE_CHECK: + seq_printf(m, pt(Opt_func), ft(func_firmware)); + break; + case POST_SETATTR: + seq_printf(m, pt(Opt_func), ft(func_post)); + break; + default: + snprintf(tbuf, sizeof(tbuf), "%d", func); + seq_printf(m, pt(Opt_func), tbuf); + break; + } + seq_puts(m, " "); +} + int ima_policy_show(struct seq_file *m, void *v) { struct ima_rule_entry *entry = v; @@ -924,33 +958,8 @@ int ima_policy_show(struct seq_file *m, void *v) seq_puts(m, " "); - if (entry->flags & IMA_FUNC) { - switch (entry->func) { - case FILE_CHECK: - seq_printf(m, pt(Opt_func), ft(func_file)); - break; - case MMAP_CHECK: - seq_printf(m, pt(Opt_func), ft(func_mmap)); - break; - case BPRM_CHECK: - seq_printf(m, pt(Opt_func), ft(func_bprm)); - break; - case MODULE_CHECK: - seq_printf(m, pt(Opt_func), ft(func_module)); - break; - case FIRMWARE_CHECK: - seq_printf(m, pt(Opt_func), ft(func_firmware)); - break; - case POST_SETATTR: - seq_printf(m, pt(Opt_func), ft(func_post)); - break; - default: - snprintf(tbuf, sizeof(tbuf), "%d", entry->func); - seq_printf(m, pt(Opt_func), tbuf); - break; - } - seq_puts(m, " "); - } + if (entry->flags & IMA_FUNC) + policy_func_show(m, entry->func); if (entry->flags & IMA_MASK) { if (entry->mask & MAY_EXEC) -- cgit v1.2.3 From 4ad87a3d7444de08858e9dc8014e948670945b6c Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Thu, 14 Jan 2016 20:59:14 -0500 Subject: ima: use "ima_hooks" enum as function argument Cleanup the function arguments by using "ima_hooks" enumerator as needed. Signed-off-by: Mimi Zohar Acked-by: Petko Manolov Acked-by: Dmitry Kasatkin --- security/integrity/ima/ima.h | 25 +++++++++++++++++-------- security/integrity/ima/ima_api.c | 6 +++--- security/integrity/ima/ima_appraise.c | 13 +++++++------ security/integrity/ima/ima_main.c | 14 +++++++------- security/integrity/ima/ima_policy.c | 6 +++--- 5 files changed, 37 insertions(+), 27 deletions(-) (limited to 'security') diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index fb8da36b1d86..b7e793501bdb 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -137,9 +137,18 @@ static inline unsigned long ima_hash_key(u8 *digest) return hash_long(*digest, IMA_HASH_BITS); } +enum ima_hooks { + FILE_CHECK = 1, + MMAP_CHECK, + BPRM_CHECK, + MODULE_CHECK, + FIRMWARE_CHECK, + POST_SETATTR +}; + /* LIM API function definitions */ -int ima_get_action(struct inode *inode, int mask, int function); -int ima_must_measure(struct inode *inode, int mask, int function); +int ima_get_action(struct inode *inode, int mask, enum ima_hooks func); +int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func); int ima_collect_measurement(struct integrity_iint_cache *iint, struct file *file, enum hash_algo algo); void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file, @@ -156,8 +165,6 @@ void ima_free_template_entry(struct ima_template_entry *entry); const char *ima_d_path(struct path *path, char **pathbuf); /* IMA policy related functions */ -enum ima_hooks { FILE_CHECK = 1, MMAP_CHECK, BPRM_CHECK, MODULE_CHECK, FIRMWARE_CHECK, POST_SETATTR }; - int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask, int flags); void ima_init_policy(void); @@ -179,21 +186,22 @@ int ima_policy_show(struct seq_file *m, void *v); #define IMA_APPRAISE_FIRMWARE 0x10 #ifdef CONFIG_IMA_APPRAISE -int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, +int ima_appraise_measurement(enum ima_hooks func, + struct integrity_iint_cache *iint, struct file *file, const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, int xattr_len, int opened); int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func); void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file); enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, - int func); + enum ima_hooks func); enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value, int xattr_len); int ima_read_xattr(struct dentry *dentry, struct evm_ima_xattr_data **xattr_value); #else -static inline int ima_appraise_measurement(int func, +static inline int ima_appraise_measurement(enum ima_hooks func, struct integrity_iint_cache *iint, struct file *file, const unsigned char *filename, @@ -215,7 +223,8 @@ static inline void ima_update_xattr(struct integrity_iint_cache *iint, } static inline enum integrity_status ima_get_cache_status(struct integrity_iint_cache - *iint, int func) + *iint, + enum ima_hooks func) { return INTEGRITY_UNKNOWN; } diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index e7c7a5d41413..8750254506a9 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -156,7 +156,7 @@ err_out: * ima_get_action - appraise & measure decision based on policy. * @inode: pointer to inode to measure * @mask: contains the permission mask (MAY_READ, MAY_WRITE, MAY_EXECUTE) - * @function: calling function (FILE_CHECK, BPRM_CHECK, MMAP_CHECK, MODULE_CHECK) + * @func: caller identifier * * The policy is defined in terms of keypairs: * subj=, obj=, type=, func=, mask=, fsmagic= @@ -168,13 +168,13 @@ err_out: * Returns IMA_MEASURE, IMA_APPRAISE mask. * */ -int ima_get_action(struct inode *inode, int mask, int function) +int ima_get_action(struct inode *inode, int mask, enum ima_hooks func) { int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE; flags &= ima_policy_flag; - return ima_match_policy(inode, function, mask, flags); + return ima_match_policy(inode, func, mask, flags); } /* diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 9c2b46b90be8..288844908788 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -67,7 +67,7 @@ static int ima_fix_xattr(struct dentry *dentry, /* Return specific func appraised cached result */ enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, - int func) + enum ima_hooks func) { switch (func) { case MMAP_CHECK: @@ -85,7 +85,8 @@ enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, } static void ima_set_cache_status(struct integrity_iint_cache *iint, - int func, enum integrity_status status) + enum ima_hooks func, + enum integrity_status status) { switch (func) { case MMAP_CHECK: @@ -103,11 +104,11 @@ static void ima_set_cache_status(struct integrity_iint_cache *iint, case FILE_CHECK: default: iint->ima_file_status = status; - break; } } -static void ima_cache_flags(struct integrity_iint_cache *iint, int func) +static void ima_cache_flags(struct integrity_iint_cache *iint, + enum ima_hooks func) { switch (func) { case MMAP_CHECK: @@ -125,7 +126,6 @@ static void ima_cache_flags(struct integrity_iint_cache *iint, int func) case FILE_CHECK: default: iint->flags |= (IMA_FILE_APPRAISED | IMA_APPRAISED); - break; } } @@ -185,7 +185,8 @@ int ima_read_xattr(struct dentry *dentry, * * Return 0 on success, error code otherwise */ -int ima_appraise_measurement(int func, struct integrity_iint_cache *iint, +int ima_appraise_measurement(enum ima_hooks func, + struct integrity_iint_cache *iint, struct file *file, const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, int xattr_len, int opened) diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index af4c3c1700b5..1be99a27a7f3 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -153,8 +153,8 @@ void ima_file_free(struct file *file) ima_check_last_writer(iint, inode, file); } -static int process_measurement(struct file *file, int mask, int function, - int opened) +static int process_measurement(struct file *file, int mask, + enum ima_hooks func, int opened) { struct inode *inode = file_inode(file); struct integrity_iint_cache *iint = NULL; @@ -174,8 +174,8 @@ static int process_measurement(struct file *file, int mask, int function, * bitmask based on the appraise/audit/measurement policy. * Included is the appraise submask. */ - action = ima_get_action(inode, mask, function); - violation_check = ((function == FILE_CHECK || function == MMAP_CHECK) && + action = ima_get_action(inode, mask, func); + violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) && (ima_policy_flag & IMA_MEASURE)); if (!action && !violation_check) return 0; @@ -184,7 +184,7 @@ static int process_measurement(struct file *file, int mask, int function, /* Is the appraise rule hook specific? */ if (action & IMA_FILE_APPRAISE) - function = FILE_CHECK; + func = FILE_CHECK; inode_lock(inode); @@ -214,7 +214,7 @@ static int process_measurement(struct file *file, int mask, int function, /* Nothing to do, just return existing appraised status */ if (!action) { if (must_appraise) - rc = ima_get_cache_status(iint, function); + rc = ima_get_cache_status(iint, func); goto out_digsig; } @@ -240,7 +240,7 @@ static int process_measurement(struct file *file, int mask, int function, ima_store_measurement(iint, file, pathname, xattr_value, xattr_len); if (action & IMA_APPRAISE_SUBMASK) - rc = ima_appraise_measurement(function, iint, file, pathname, + rc = ima_appraise_measurement(func, iint, file, pathname, xattr_value, xattr_len, opened); if (action & IMA_AUDIT) ima_audit_measurement(iint, pathname); diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 43b642557d6c..b089ebef6648 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -207,8 +207,8 @@ static void ima_lsm_update_rules(void) * * Returns true on rule match, false on failure. */ -static bool ima_match_rules(struct ima_rule_entry *rule, - struct inode *inode, enum ima_hooks func, int mask) +static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode, + enum ima_hooks func, int mask) { struct task_struct *tsk = current; const struct cred *cred = current_cred(); @@ -289,7 +289,7 @@ retry: * In addition to knowing that we need to appraise the file in general, * we need to differentiate between calling hooks, for hook specific rules. */ -static int get_subaction(struct ima_rule_entry *rule, int func) +static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func) { if (!(rule->flags & IMA_FUNC)) return IMA_FILE_APPRAISE; -- cgit v1.2.3 From b44a7dfc6fa16e01f2497c9fa62c3926f94be174 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Mon, 28 Dec 2015 16:02:29 -0500 Subject: vfs: define a generic function to read a file from the kernel For a while it was looked down upon to directly read files from Linux. These days there exists a few mechanisms in the kernel that do just this though to load a file into a local buffer. There are minor but important checks differences on each. This patch set is the first attempt at resolving some of these differences. This patch introduces a common function for reading files from the kernel with the corresponding security post-read hook and function. Changelog v4+: - export security_kernel_post_read_file() - Fengguang Wu v3: - additional bounds checking - Luis v2: - To simplify patch review, re-ordered patches Signed-off-by: Mimi Zohar Reviewed-by: Luis R. Rodriguez Acked-by: Kees Cook Cc: Al Viro --- fs/exec.c | 53 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/fs.h | 1 + include/linux/lsm_hooks.h | 9 ++++++++ include/linux/security.h | 7 +++++++ security/security.c | 8 +++++++ 5 files changed, 78 insertions(+) (limited to 'security') diff --git a/fs/exec.c b/fs/exec.c index dcd4ac7d3f1e..6b6668baa44a 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -56,6 +56,7 @@ #include #include #include +#include #include #include @@ -831,6 +832,58 @@ int kernel_read(struct file *file, loff_t offset, EXPORT_SYMBOL(kernel_read); +int kernel_read_file(struct file *file, void **buf, loff_t *size, + loff_t max_size) +{ + loff_t i_size, pos; + ssize_t bytes = 0; + int ret; + + if (!S_ISREG(file_inode(file)->i_mode) || max_size < 0) + return -EINVAL; + + i_size = i_size_read(file_inode(file)); + if (max_size > 0 && i_size > max_size) + return -EFBIG; + if (i_size <= 0) + return -EINVAL; + + *buf = vmalloc(i_size); + if (!*buf) + return -ENOMEM; + + pos = 0; + while (pos < i_size) { + bytes = kernel_read(file, pos, (char *)(*buf) + pos, + i_size - pos); + if (bytes < 0) { + ret = bytes; + goto out; + } + + if (bytes == 0) + break; + pos += bytes; + } + + if (pos != i_size) { + ret = -EIO; + goto out; + } + + ret = security_kernel_post_read_file(file, *buf, i_size); + if (!ret) + *size = pos; + +out: + if (ret < 0) { + vfree(*buf); + *buf = NULL; + } + return ret; +} +EXPORT_SYMBOL_GPL(kernel_read_file); + ssize_t read_code(struct file *file, unsigned long addr, loff_t pos, size_t len) { ssize_t res = vfs_read(file, (void __user *)addr, len, &pos); diff --git a/include/linux/fs.h b/include/linux/fs.h index ae681002100a..9a83d82b61ac 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2577,6 +2577,7 @@ static inline void i_readcount_inc(struct inode *inode) extern int do_pipe_flags(int *, int); extern int kernel_read(struct file *, loff_t, char *, unsigned long); +extern int kernel_read_file(struct file *, void **, loff_t *, loff_t); extern ssize_t kernel_write(struct file *, const char *, size_t, loff_t); extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *); extern struct file * open_exec(const char *); diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 71969de4058c..f82631cc7248 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -561,6 +561,13 @@ * the kernel module to load. If the module is being loaded from a blob, * this argument will be NULL. * Return 0 if permission is granted. + * @kernel_post_read_file: + * Read a file specified by userspace. + * @file contains the file structure pointing to the file being read + * by the kernel. + * @buf pointer to buffer containing the file contents. + * @size length of the file contents. + * Return 0 if permission is granted. * @task_fix_setuid: * Update the module's state after setting one or more of the user * identity attributes of the current process. The @flags parameter @@ -1457,6 +1464,7 @@ union security_list_options { int (*kernel_fw_from_file)(struct file *file, char *buf, size_t size); int (*kernel_module_request)(char *kmod_name); int (*kernel_module_from_file)(struct file *file); + int (*kernel_post_read_file)(struct file *file, char *buf, loff_t size); int (*task_fix_setuid)(struct cred *new, const struct cred *old, int flags); int (*task_setpgid)(struct task_struct *p, pid_t pgid); @@ -1716,6 +1724,7 @@ struct security_hook_heads { struct list_head kernel_act_as; struct list_head kernel_create_files_as; struct list_head kernel_fw_from_file; + struct list_head kernel_post_read_file; struct list_head kernel_module_request; struct list_head kernel_module_from_file; struct list_head task_fix_setuid; diff --git a/include/linux/security.h b/include/linux/security.h index 4824a4ccaf1c..f30f5647d1e1 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -301,6 +301,7 @@ int security_kernel_create_files_as(struct cred *new, struct inode *inode); int security_kernel_fw_from_file(struct file *file, char *buf, size_t size); int security_kernel_module_request(char *kmod_name); int security_kernel_module_from_file(struct file *file); +int security_kernel_post_read_file(struct file *file, char *buf, loff_t size); int security_task_fix_setuid(struct cred *new, const struct cred *old, int flags); int security_task_setpgid(struct task_struct *p, pid_t pgid); @@ -866,6 +867,12 @@ static inline int security_kernel_module_from_file(struct file *file) return 0; } +static inline int security_kernel_post_read_file(struct file *file, + char *buf, loff_t size) +{ + return 0; +} + static inline int security_task_fix_setuid(struct cred *new, const struct cred *old, int flags) diff --git a/security/security.c b/security/security.c index e8ffd92ae2eb..c98dd6bf4ebd 100644 --- a/security/security.c +++ b/security/security.c @@ -910,6 +910,12 @@ int security_kernel_module_from_file(struct file *file) return ima_module_check(file); } +int security_kernel_post_read_file(struct file *file, char *buf, loff_t size) +{ + return call_int_hook(kernel_post_read_file, 0, file, buf, size); +} +EXPORT_SYMBOL_GPL(security_kernel_post_read_file); + int security_task_fix_setuid(struct cred *new, const struct cred *old, int flags) { @@ -1697,6 +1703,8 @@ struct security_hook_heads security_hook_heads = { LIST_HEAD_INIT(security_hook_heads.kernel_module_request), .kernel_module_from_file = LIST_HEAD_INIT(security_hook_heads.kernel_module_from_file), + .kernel_post_read_file = + LIST_HEAD_INIT(security_hook_heads.kernel_post_read_file), .task_fix_setuid = LIST_HEAD_INIT(security_hook_heads.task_fix_setuid), .task_setpgid = LIST_HEAD_INIT(security_hook_heads.task_setpgid), -- cgit v1.2.3 From bc8ca5b92d54f6f005fa73ad546f02fca26ddd85 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Sun, 24 Jan 2016 10:07:32 -0500 Subject: vfs: define kernel_read_file_id enumeration To differentiate between the kernel_read_file() callers, this patch defines a new enumeration named kernel_read_file_id and includes the caller identifier as an argument. Subsequent patches define READING_KEXEC_IMAGE, READING_KEXEC_INITRAMFS, READING_FIRMWARE, READING_MODULE, and READING_POLICY. Changelog v3: - Replace the IMA specific enumeration with a generic one. Signed-off-by: Mimi Zohar Acked-by: Kees Cook Acked-by: Luis R. Rodriguez Cc: Al Viro --- fs/exec.c | 4 ++-- include/linux/fs.h | 7 ++++++- include/linux/lsm_hooks.h | 4 +++- include/linux/security.h | 7 +++++-- security/security.c | 5 +++-- 5 files changed, 19 insertions(+), 8 deletions(-) (limited to 'security') diff --git a/fs/exec.c b/fs/exec.c index 6b6668baa44a..1138dc502c77 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -833,7 +833,7 @@ int kernel_read(struct file *file, loff_t offset, EXPORT_SYMBOL(kernel_read); int kernel_read_file(struct file *file, void **buf, loff_t *size, - loff_t max_size) + loff_t max_size, enum kernel_read_file_id id) { loff_t i_size, pos; ssize_t bytes = 0; @@ -871,7 +871,7 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size, goto out; } - ret = security_kernel_post_read_file(file, *buf, i_size); + ret = security_kernel_post_read_file(file, *buf, i_size, id); if (!ret) *size = pos; diff --git a/include/linux/fs.h b/include/linux/fs.h index 9a83d82b61ac..aa84bcb9c368 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2576,8 +2576,13 @@ static inline void i_readcount_inc(struct inode *inode) #endif extern int do_pipe_flags(int *, int); +enum kernel_read_file_id { + READING_MAX_ID +}; + extern int kernel_read(struct file *, loff_t, char *, unsigned long); -extern int kernel_read_file(struct file *, void **, loff_t *, loff_t); +extern int kernel_read_file(struct file *, void **, loff_t *, loff_t, + enum kernel_read_file_id); extern ssize_t kernel_write(struct file *, const char *, size_t, loff_t); extern ssize_t __kernel_write(struct file *, const char *, size_t, loff_t *); extern struct file * open_exec(const char *); diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index f82631cc7248..2337f33913c1 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -567,6 +567,7 @@ * by the kernel. * @buf pointer to buffer containing the file contents. * @size length of the file contents. + * @id kernel read file identifier * Return 0 if permission is granted. * @task_fix_setuid: * Update the module's state after setting one or more of the user @@ -1464,7 +1465,8 @@ union security_list_options { int (*kernel_fw_from_file)(struct file *file, char *buf, size_t size); int (*kernel_module_request)(char *kmod_name); int (*kernel_module_from_file)(struct file *file); - int (*kernel_post_read_file)(struct file *file, char *buf, loff_t size); + int (*kernel_post_read_file)(struct file *file, char *buf, loff_t size, + enum kernel_read_file_id id); int (*task_fix_setuid)(struct cred *new, const struct cred *old, int flags); int (*task_setpgid)(struct task_struct *p, pid_t pgid); diff --git a/include/linux/security.h b/include/linux/security.h index f30f5647d1e1..b68ce94e4e00 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -28,6 +28,7 @@ #include #include #include +#include struct linux_binprm; struct cred; @@ -301,7 +302,8 @@ int security_kernel_create_files_as(struct cred *new, struct inode *inode); int security_kernel_fw_from_file(struct file *file, char *buf, size_t size); int security_kernel_module_request(char *kmod_name); int security_kernel_module_from_file(struct file *file); -int security_kernel_post_read_file(struct file *file, char *buf, loff_t size); +int security_kernel_post_read_file(struct file *file, char *buf, loff_t size, + enum kernel_read_file_id id); int security_task_fix_setuid(struct cred *new, const struct cred *old, int flags); int security_task_setpgid(struct task_struct *p, pid_t pgid); @@ -868,7 +870,8 @@ static inline int security_kernel_module_from_file(struct file *file) } static inline int security_kernel_post_read_file(struct file *file, - char *buf, loff_t size) + char *buf, loff_t size, + enum kernel_read_file_id id) { return 0; } diff --git a/security/security.c b/security/security.c index c98dd6bf4ebd..5b96eabaafd4 100644 --- a/security/security.c +++ b/security/security.c @@ -910,9 +910,10 @@ int security_kernel_module_from_file(struct file *file) return ima_module_check(file); } -int security_kernel_post_read_file(struct file *file, char *buf, loff_t size) +int security_kernel_post_read_file(struct file *file, char *buf, loff_t size, + enum kernel_read_file_id id) { - return call_int_hook(kernel_post_read_file, 0, file, buf, size); + return call_int_hook(kernel_post_read_file, 0, file, buf, size, id); } EXPORT_SYMBOL_GPL(security_kernel_post_read_file); -- cgit v1.2.3 From 11d7646df8e800f434ff710ad6100acbea59068e Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Thu, 17 Apr 2014 12:01:40 +0300 Subject: ima: provide buffer hash calculation function This patch provides convenient buffer hash calculation function. Changelog v3: - fix while hash calculation - Dmitry v1: - rewrite to support loff_t sized buffers - Mimi (based on Fenguang Wu's testing) Signed-off-by: Dmitry Kasatkin Signed-off-by: Mimi Zohar --- security/integrity/ima/ima.h | 2 ++ security/integrity/ima/ima_crypto.c | 47 +++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+) (limited to 'security') diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index b7e793501bdb..2c5262f2823f 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -107,6 +107,8 @@ int ima_add_template_entry(struct ima_template_entry *entry, int violation, const char *op, struct inode *inode, const unsigned char *filename); int ima_calc_file_hash(struct file *file, struct ima_digest_data *hash); +int ima_calc_buffer_hash(const void *buf, loff_t len, + struct ima_digest_data *hash); int ima_calc_field_array_hash(struct ima_field_data *field_data, struct ima_template_desc *desc, int num_fields, struct ima_digest_data *hash); diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index fb30ce406af4..fccb6ceb388b 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -519,6 +519,53 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data, return rc; } +static int calc_buffer_shash_tfm(const void *buf, loff_t size, + struct ima_digest_data *hash, + struct crypto_shash *tfm) +{ + SHASH_DESC_ON_STACK(shash, tfm); + unsigned int len; + int rc; + + shash->tfm = tfm; + shash->flags = 0; + + hash->length = crypto_shash_digestsize(tfm); + + rc = crypto_shash_init(shash); + if (rc != 0) + return rc; + + while (size) { + len = size < PAGE_SIZE ? size : PAGE_SIZE; + rc = crypto_shash_update(shash, buf, len); + if (rc) + break; + buf += len; + size -= len; + } + + if (!rc) + rc = crypto_shash_final(shash, hash->digest); + return rc; +} + +int ima_calc_buffer_hash(const void *buf, loff_t len, + struct ima_digest_data *hash) +{ + struct crypto_shash *tfm; + int rc; + + tfm = ima_alloc_tfm(hash->algo); + if (IS_ERR(tfm)) + return PTR_ERR(tfm); + + rc = calc_buffer_shash_tfm(buf, len, hash, tfm); + + ima_free_tfm(tfm); + return rc; +} + static void __init ima_pcrread(int idx, u8 *pcr) { if (!ima_used_chip) -- cgit v1.2.3 From 98304bcf71845e97c0b5c800ae619311156b66c1 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Mon, 28 Dec 2015 11:56:09 -0500 Subject: ima: calculate the hash of a buffer using aynchronous hash(ahash) Setting up ahash has some overhead. Only use ahash to calculate the hash of a buffer, if the buffer is larger than ima_ahash_minsize. Signed-off-by: Mimi Zohar Acked-by: Dmitry Kasatkin --- security/integrity/ima/ima_crypto.c | 75 ++++++++++++++++++++++++++++++++++++- 1 file changed, 73 insertions(+), 2 deletions(-) (limited to 'security') diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c index fccb6ceb388b..38f2ed830dd6 100644 --- a/security/integrity/ima/ima_crypto.c +++ b/security/integrity/ima/ima_crypto.c @@ -519,6 +519,63 @@ int ima_calc_field_array_hash(struct ima_field_data *field_data, return rc; } +static int calc_buffer_ahash_atfm(const void *buf, loff_t len, + struct ima_digest_data *hash, + struct crypto_ahash *tfm) +{ + struct ahash_request *req; + struct scatterlist sg; + struct ahash_completion res; + int rc, ahash_rc = 0; + + hash->length = crypto_ahash_digestsize(tfm); + + req = ahash_request_alloc(tfm, GFP_KERNEL); + if (!req) + return -ENOMEM; + + init_completion(&res.completion); + ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP, + ahash_complete, &res); + + rc = ahash_wait(crypto_ahash_init(req), &res); + if (rc) + goto out; + + sg_init_one(&sg, buf, len); + ahash_request_set_crypt(req, &sg, NULL, len); + + ahash_rc = crypto_ahash_update(req); + + /* wait for the update request to complete */ + rc = ahash_wait(ahash_rc, &res); + if (!rc) { + ahash_request_set_crypt(req, NULL, hash->digest, 0); + rc = ahash_wait(crypto_ahash_final(req), &res); + } +out: + ahash_request_free(req); + return rc; +} + +static int calc_buffer_ahash(const void *buf, loff_t len, + struct ima_digest_data *hash) +{ + struct crypto_ahash *tfm; + int rc; + + tfm = ima_alloc_atfm(hash->algo); + if (IS_ERR(tfm)) + return PTR_ERR(tfm); + + rc = calc_buffer_ahash_atfm(buf, len, hash, tfm); + + ima_free_atfm(tfm); + + return rc; +} + static int calc_buffer_shash_tfm(const void *buf, loff_t size, struct ima_digest_data *hash, struct crypto_shash *tfm) @@ -550,8 +607,8 @@ static int calc_buffer_shash_tfm(const void *buf, loff_t size, return rc; } -int ima_calc_buffer_hash(const void *buf, loff_t len, - struct ima_digest_data *hash) +static int calc_buffer_shash(const void *buf, loff_t len, + struct ima_digest_data *hash) { struct crypto_shash *tfm; int rc; @@ -566,6 +623,20 @@ int ima_calc_buffer_hash(const void *buf, loff_t len, return rc; } +int ima_calc_buffer_hash(const void *buf, loff_t len, + struct ima_digest_data *hash) +{ + int rc; + + if (ima_ahash_minsize && len >= ima_ahash_minsize) { + rc = calc_buffer_ahash(buf, len, hash); + if (!rc) + return 0; + } + + return calc_buffer_shash(buf, len, hash); +} + static void __init ima_pcrread(int idx, u8 *pcr) { if (!ima_used_chip) -- cgit v1.2.3 From cf2222178645e545e96717b2825601321ce4745c Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Thu, 14 Jan 2016 17:57:47 -0500 Subject: ima: define a new hook to measure and appraise a file already in memory This patch defines a new IMA hook ima_post_read_file() for measuring and appraising files read by the kernel. The caller loads the file into memory before calling this function, which calculates the hash followed by the normal IMA policy based processing. Changelog v5: - fail ima_post_read_file() if either file or buf is NULL v3: - rename ima_hash_and_process_file() to ima_post_read_file() v1: - split patch Signed-off-by: Mimi Zohar Acked-by: Dmitry Kasatkin --- include/linux/ima.h | 8 +++++++ include/linux/security.h | 1 + security/integrity/ima/ima.h | 4 +++- security/integrity/ima/ima_api.c | 6 +++-- security/integrity/ima/ima_appraise.c | 2 +- security/integrity/ima/ima_main.c | 45 ++++++++++++++++++++++++++++------- security/integrity/ima/ima_policy.c | 1 + security/integrity/integrity.h | 7 ++++-- security/security.c | 7 +++++- 9 files changed, 66 insertions(+), 15 deletions(-) (limited to 'security') diff --git a/include/linux/ima.h b/include/linux/ima.h index 120ccc53fcb7..d29a6a23fc19 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -20,6 +20,8 @@ extern void ima_file_free(struct file *file); extern int ima_file_mmap(struct file *file, unsigned long prot); extern int ima_module_check(struct file *file); extern int ima_fw_from_file(struct file *file, char *buf, size_t size); +extern int ima_post_read_file(struct file *file, void *buf, loff_t size, + enum kernel_read_file_id id); #else static inline int ima_bprm_check(struct linux_binprm *bprm) @@ -52,6 +54,12 @@ static inline int ima_fw_from_file(struct file *file, char *buf, size_t size) return 0; } +static inline int ima_post_read_file(struct file *file, void *buf, loff_t size, + enum kernel_read_file_id id) +{ + return 0; +} + #endif /* CONFIG_IMA */ #ifdef CONFIG_IMA_APPRAISE diff --git a/include/linux/security.h b/include/linux/security.h index b68ce94e4e00..d920718dc845 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -24,6 +24,7 @@ #include #include +#include #include #include #include diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 2c5262f2823f..0b7134c04165 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -152,7 +153,8 @@ enum ima_hooks { int ima_get_action(struct inode *inode, int mask, enum ima_hooks func); int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func); int ima_collect_measurement(struct integrity_iint_cache *iint, - struct file *file, enum hash_algo algo); + struct file *file, void *buf, loff_t size, + enum hash_algo algo); void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file, const unsigned char *filename, struct evm_ima_xattr_data *xattr_value, diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c index 8750254506a9..370e42dfc5c5 100644 --- a/security/integrity/ima/ima_api.c +++ b/security/integrity/ima/ima_api.c @@ -188,7 +188,8 @@ int ima_get_action(struct inode *inode, int mask, enum ima_hooks func) * Return 0 on success, error code otherwise */ int ima_collect_measurement(struct integrity_iint_cache *iint, - struct file *file, enum hash_algo algo) + struct file *file, void *buf, loff_t size, + enum hash_algo algo) { const char *audit_cause = "failed"; struct inode *inode = file_inode(file); @@ -210,7 +211,8 @@ int ima_collect_measurement(struct integrity_iint_cache *iint, hash.hdr.algo = algo; - result = ima_calc_file_hash(file, &hash.hdr); + result = (!buf) ? ima_calc_file_hash(file, &hash.hdr) : + ima_calc_buffer_hash(buf, size, &hash.hdr); if (!result) { int length = sizeof(hash.hdr) + hash.hdr.length; void *tmpbuf = krealloc(iint->ima_hash, length, diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 288844908788..cb0d0ff1137b 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -300,7 +300,7 @@ void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file) if (iint->flags & IMA_DIGSIG) return; - rc = ima_collect_measurement(iint, file, ima_hash_algo); + rc = ima_collect_measurement(iint, file, NULL, 0, ima_hash_algo); if (rc < 0) return; diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 1be99a27a7f3..757765354158 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -153,8 +153,8 @@ void ima_file_free(struct file *file) ima_check_last_writer(iint, inode, file); } -static int process_measurement(struct file *file, int mask, - enum ima_hooks func, int opened) +static int process_measurement(struct file *file, char *buf, loff_t size, + int mask, enum ima_hooks func, int opened) { struct inode *inode = file_inode(file); struct integrity_iint_cache *iint = NULL; @@ -226,7 +226,7 @@ static int process_measurement(struct file *file, int mask, hash_algo = ima_get_hash_algo(xattr_value, xattr_len); - rc = ima_collect_measurement(iint, file, hash_algo); + rc = ima_collect_measurement(iint, file, buf, size, hash_algo); if (rc != 0) { if (file->f_flags & O_DIRECT) rc = (iint->flags & IMA_PERMIT_DIRECTIO) ? 0 : -EACCES; @@ -273,7 +273,8 @@ out: int ima_file_mmap(struct file *file, unsigned long prot) { if (file && (prot & PROT_EXEC)) - return process_measurement(file, MAY_EXEC, MMAP_CHECK, 0); + return process_measurement(file, NULL, 0, MAY_EXEC, + MMAP_CHECK, 0); return 0; } @@ -292,7 +293,8 @@ int ima_file_mmap(struct file *file, unsigned long prot) */ int ima_bprm_check(struct linux_binprm *bprm) { - return process_measurement(bprm->file, MAY_EXEC, BPRM_CHECK, 0); + return process_measurement(bprm->file, NULL, 0, MAY_EXEC, + BPRM_CHECK, 0); } /** @@ -307,7 +309,7 @@ int ima_bprm_check(struct linux_binprm *bprm) */ int ima_file_check(struct file *file, int mask, int opened) { - return process_measurement(file, + return process_measurement(file, NULL, 0, mask & (MAY_READ | MAY_WRITE | MAY_EXEC), FILE_CHECK, opened); } @@ -332,7 +334,7 @@ int ima_module_check(struct file *file) #endif return 0; /* We rely on module signature checking */ } - return process_measurement(file, MAY_EXEC, MODULE_CHECK, 0); + return process_measurement(file, NULL, 0, MAY_EXEC, MODULE_CHECK, 0); } int ima_fw_from_file(struct file *file, char *buf, size_t size) @@ -343,7 +345,34 @@ int ima_fw_from_file(struct file *file, char *buf, size_t size) return -EACCES; /* INTEGRITY_UNKNOWN */ return 0; } - return process_measurement(file, MAY_EXEC, FIRMWARE_CHECK, 0); + return process_measurement(file, NULL, 0, MAY_EXEC, FIRMWARE_CHECK, 0); +} + +/** + * ima_post_read_file - in memory collect/appraise/audit measurement + * @file: pointer to the file to be measured/appraised/audit + * @buf: pointer to in memory file contents + * @size: size of in memory file contents + * @read_id: caller identifier + * + * Measure/appraise/audit in memory file based on policy. Policy rules + * are written in terms of a policy identifier. + * + * On success return 0. On integrity appraisal error, assuming the file + * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. + */ +int ima_post_read_file(struct file *file, void *buf, loff_t size, + enum kernel_read_file_id read_id) +{ + enum ima_hooks func = FILE_CHECK; + + if (!file || !buf || size == 0) { /* should never happen */ + if (ima_appraise & IMA_APPRAISE_ENFORCE) + return -EACCES; + return 0; + } + + return process_measurement(file, buf, size, MAY_READ, func, 0); } static int __init init_ima(void) diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index b089ebef6648..cfbe86f476d0 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -12,6 +12,7 @@ */ #include #include +#include #include #include #include diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 5efe2ecc538d..9a0ea4c4e3dd 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -49,12 +49,14 @@ #define IMA_MODULE_APPRAISED 0x00008000 #define IMA_FIRMWARE_APPRAISE 0x00010000 #define IMA_FIRMWARE_APPRAISED 0x00020000 +#define IMA_READ_APPRAISE 0x00040000 +#define IMA_READ_APPRAISED 0x00080000 #define IMA_APPRAISE_SUBMASK (IMA_FILE_APPRAISE | IMA_MMAP_APPRAISE | \ IMA_BPRM_APPRAISE | IMA_MODULE_APPRAISE | \ - IMA_FIRMWARE_APPRAISE) + IMA_FIRMWARE_APPRAISE | IMA_READ_APPRAISE) #define IMA_APPRAISED_SUBMASK (IMA_FILE_APPRAISED | IMA_MMAP_APPRAISED | \ IMA_BPRM_APPRAISED | IMA_MODULE_APPRAISED | \ - IMA_FIRMWARE_APPRAISED) + IMA_FIRMWARE_APPRAISED | IMA_READ_APPRAISED) enum evm_ima_xattr_type { IMA_XATTR_DIGEST = 0x01, @@ -111,6 +113,7 @@ struct integrity_iint_cache { enum integrity_status ima_bprm_status:4; enum integrity_status ima_module_status:4; enum integrity_status ima_firmware_status:4; + enum integrity_status ima_read_status:4; enum integrity_status evm_status:4; struct ima_digest_data *ima_hash; }; diff --git a/security/security.c b/security/security.c index 5b96eabaafd4..ef4c65a9fd17 100644 --- a/security/security.c +++ b/security/security.c @@ -913,7 +913,12 @@ int security_kernel_module_from_file(struct file *file) int security_kernel_post_read_file(struct file *file, char *buf, loff_t size, enum kernel_read_file_id id) { - return call_int_hook(kernel_post_read_file, 0, file, buf, size, id); + int ret; + + ret = call_int_hook(kernel_post_read_file, 0, file, buf, size, id); + if (ret) + return ret; + return ima_post_read_file(file, buf, size, id); } EXPORT_SYMBOL_GPL(security_kernel_post_read_file); -- cgit v1.2.3 From e40ba6d56b41754b37b995dbc8035b2b3a6afd8a Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Thu, 19 Nov 2015 12:39:22 -0500 Subject: firmware: replace call to fw_read_file_contents() with kernel version Replace the fw_read_file_contents with kernel_file_read_from_path(). Although none of the upstreamed LSMs define a kernel_fw_from_file hook, IMA is called by the security function to prevent unsigned firmware from being loaded and to measure/appraise signed firmware, based on policy. Instead of reading the firmware twice, once for measuring/appraising the firmware and again for reading the firmware contents into memory, the kernel_post_read_file() security hook calculates the file hash based on the in memory file buffer. The firmware is read once. This patch removes the LSM kernel_fw_from_file() hook and security call. Changelog v4+: - revert dropped buf->size assignment - reported by Sergey Senozhatsky v3: - remove kernel_fw_from_file hook - use kernel_file_read_from_path() - requested by Luis v2: - reordered and squashed firmware patches - fix MAX firmware size (Kees Cook) Signed-off-by: Mimi Zohar Acked-by: Kees Cook Acked-by: Luis R. Rodriguez --- drivers/base/firmware_class.c | 52 ++++++++------------------------------- include/linux/fs.h | 1 + include/linux/ima.h | 6 ----- include/linux/lsm_hooks.h | 11 --------- include/linux/security.h | 7 ------ security/integrity/ima/ima_main.c | 21 ++++++++-------- security/security.c | 13 ---------- 7 files changed, 21 insertions(+), 90 deletions(-) (limited to 'security') diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index c743a2f18c33..a414008ea64c 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include @@ -291,37 +292,6 @@ static const char * const fw_path[] = { module_param_string(path, fw_path_para, sizeof(fw_path_para), 0644); MODULE_PARM_DESC(path, "customized firmware image search path with a higher priority than default path"); -static int fw_read_file_contents(struct file *file, struct firmware_buf *fw_buf) -{ - int size; - char *buf; - int rc; - - if (!S_ISREG(file_inode(file)->i_mode)) - return -EINVAL; - size = i_size_read(file_inode(file)); - if (size <= 0) - return -EINVAL; - buf = vmalloc(size); - if (!buf) - return -ENOMEM; - rc = kernel_read(file, 0, buf, size); - if (rc != size) { - if (rc > 0) - rc = -EIO; - goto fail; - } - rc = security_kernel_fw_from_file(file, buf, size); - if (rc) - goto fail; - fw_buf->data = buf; - fw_buf->size = size; - return 0; -fail: - vfree(buf); - return rc; -} - static void fw_finish_direct_load(struct device *device, struct firmware_buf *buf) { @@ -334,6 +304,7 @@ static void fw_finish_direct_load(struct device *device, static int fw_get_filesystem_firmware(struct device *device, struct firmware_buf *buf) { + loff_t size; int i, len; int rc = -ENOENT; char *path; @@ -343,8 +314,6 @@ static int fw_get_filesystem_firmware(struct device *device, return -ENOMEM; for (i = 0; i < ARRAY_SIZE(fw_path); i++) { - struct file *file; - /* skip the unset customized path */ if (!fw_path[i][0]) continue; @@ -356,18 +325,16 @@ static int fw_get_filesystem_firmware(struct device *device, break; } - file = filp_open(path, O_RDONLY, 0); - if (IS_ERR(file)) - continue; - rc = fw_read_file_contents(file, buf); - fput(file); + buf->size = 0; + rc = kernel_read_file_from_path(path, &buf->data, &size, + INT_MAX, READING_FIRMWARE); if (rc) { dev_warn(device, "loading %s failed with error %d\n", path, rc); continue; } - dev_dbg(device, "direct-loading %s\n", - buf->fw_id); + dev_dbg(device, "direct-loading %s\n", buf->fw_id); + buf->size = size; fw_finish_direct_load(device, buf); break; } @@ -689,8 +656,9 @@ static ssize_t firmware_loading_store(struct device *dev, dev_err(dev, "%s: map pages failed\n", __func__); else - rc = security_kernel_fw_from_file(NULL, - fw_buf->data, fw_buf->size); + rc = security_kernel_post_read_file(NULL, + fw_buf->data, fw_buf->size, + READING_FIRMWARE); /* * Same logic as fw_load_abort, only the DONE bit diff --git a/include/linux/fs.h b/include/linux/fs.h index 00fa5c45fd63..c8bc4d8c843f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2577,6 +2577,7 @@ static inline void i_readcount_inc(struct inode *inode) extern int do_pipe_flags(int *, int); enum kernel_read_file_id { + READING_FIRMWARE = 1, READING_MAX_ID }; diff --git a/include/linux/ima.h b/include/linux/ima.h index d29a6a23fc19..7aea4863c244 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -19,7 +19,6 @@ extern int ima_file_check(struct file *file, int mask, int opened); extern void ima_file_free(struct file *file); extern int ima_file_mmap(struct file *file, unsigned long prot); extern int ima_module_check(struct file *file); -extern int ima_fw_from_file(struct file *file, char *buf, size_t size); extern int ima_post_read_file(struct file *file, void *buf, loff_t size, enum kernel_read_file_id id); @@ -49,11 +48,6 @@ static inline int ima_module_check(struct file *file) return 0; } -static inline int ima_fw_from_file(struct file *file, char *buf, size_t size) -{ - return 0; -} - static inline int ima_post_read_file(struct file *file, void *buf, loff_t size, enum kernel_read_file_id id) { diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 2337f33913c1..7d04a1220223 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -541,15 +541,6 @@ * @inode points to the inode to use as a reference. * The current task must be the one that nominated @inode. * Return 0 if successful. - * @kernel_fw_from_file: - * Load firmware from userspace (not called for built-in firmware). - * @file contains the file structure pointing to the file containing - * the firmware to load. This argument will be NULL if the firmware - * was loaded via the uevent-triggered blob-based interface exposed - * by CONFIG_FW_LOADER_USER_HELPER. - * @buf pointer to buffer containing firmware contents. - * @size length of the firmware contents. - * Return 0 if permission is granted. * @kernel_module_request: * Ability to trigger the kernel to automatically upcall to userspace for * userspace to load a kernel module with the given name. @@ -1462,7 +1453,6 @@ union security_list_options { void (*cred_transfer)(struct cred *new, const struct cred *old); int (*kernel_act_as)(struct cred *new, u32 secid); int (*kernel_create_files_as)(struct cred *new, struct inode *inode); - int (*kernel_fw_from_file)(struct file *file, char *buf, size_t size); int (*kernel_module_request)(char *kmod_name); int (*kernel_module_from_file)(struct file *file); int (*kernel_post_read_file)(struct file *file, char *buf, loff_t size, @@ -1725,7 +1715,6 @@ struct security_hook_heads { struct list_head cred_transfer; struct list_head kernel_act_as; struct list_head kernel_create_files_as; - struct list_head kernel_fw_from_file; struct list_head kernel_post_read_file; struct list_head kernel_module_request; struct list_head kernel_module_from_file; diff --git a/include/linux/security.h b/include/linux/security.h index d920718dc845..cee1349e1155 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -300,7 +300,6 @@ int security_prepare_creds(struct cred *new, const struct cred *old, gfp_t gfp); void security_transfer_creds(struct cred *new, const struct cred *old); int security_kernel_act_as(struct cred *new, u32 secid); int security_kernel_create_files_as(struct cred *new, struct inode *inode); -int security_kernel_fw_from_file(struct file *file, char *buf, size_t size); int security_kernel_module_request(char *kmod_name); int security_kernel_module_from_file(struct file *file); int security_kernel_post_read_file(struct file *file, char *buf, loff_t size, @@ -854,12 +853,6 @@ static inline int security_kernel_create_files_as(struct cred *cred, return 0; } -static inline int security_kernel_fw_from_file(struct file *file, - char *buf, size_t size) -{ - return 0; -} - static inline int security_kernel_module_request(char *kmod_name) { return 0; diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 757765354158..e9651be17b72 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -337,17 +337,6 @@ int ima_module_check(struct file *file) return process_measurement(file, NULL, 0, MAY_EXEC, MODULE_CHECK, 0); } -int ima_fw_from_file(struct file *file, char *buf, size_t size) -{ - if (!file) { - if ((ima_appraise & IMA_APPRAISE_FIRMWARE) && - (ima_appraise & IMA_APPRAISE_ENFORCE)) - return -EACCES; /* INTEGRITY_UNKNOWN */ - return 0; - } - return process_measurement(file, NULL, 0, MAY_EXEC, FIRMWARE_CHECK, 0); -} - /** * ima_post_read_file - in memory collect/appraise/audit measurement * @file: pointer to the file to be measured/appraised/audit @@ -366,12 +355,22 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size, { enum ima_hooks func = FILE_CHECK; + if (!file && read_id == READING_FIRMWARE) { + if ((ima_appraise & IMA_APPRAISE_FIRMWARE) && + (ima_appraise & IMA_APPRAISE_ENFORCE)) + return -EACCES; /* INTEGRITY_UNKNOWN */ + return 0; + } + if (!file || !buf || size == 0) { /* should never happen */ if (ima_appraise & IMA_APPRAISE_ENFORCE) return -EACCES; return 0; } + if (read_id == READING_FIRMWARE) + func = FIRMWARE_CHECK; + return process_measurement(file, buf, size, MAY_READ, func, 0); } diff --git a/security/security.c b/security/security.c index ef4c65a9fd17..cd85be61c416 100644 --- a/security/security.c +++ b/security/security.c @@ -884,17 +884,6 @@ int security_kernel_create_files_as(struct cred *new, struct inode *inode) return call_int_hook(kernel_create_files_as, 0, new, inode); } -int security_kernel_fw_from_file(struct file *file, char *buf, size_t size) -{ - int ret; - - ret = call_int_hook(kernel_fw_from_file, 0, file, buf, size); - if (ret) - return ret; - return ima_fw_from_file(file, buf, size); -} -EXPORT_SYMBOL_GPL(security_kernel_fw_from_file); - int security_kernel_module_request(char *kmod_name) { return call_int_hook(kernel_module_request, 0, kmod_name); @@ -1703,8 +1692,6 @@ struct security_hook_heads security_hook_heads = { LIST_HEAD_INIT(security_hook_heads.kernel_act_as), .kernel_create_files_as = LIST_HEAD_INIT(security_hook_heads.kernel_create_files_as), - .kernel_fw_from_file = - LIST_HEAD_INIT(security_hook_heads.kernel_fw_from_file), .kernel_module_request = LIST_HEAD_INIT(security_hook_heads.kernel_module_request), .kernel_module_from_file = -- cgit v1.2.3 From 39eeb4fb97f60dbdfc823c1a673a8844b9226b60 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Sat, 30 Jan 2016 22:23:26 -0500 Subject: security: define kernel_read_file hook The kernel_read_file security hook is called prior to reading the file into memory. Changelog v4+: - export security_kernel_read_file() Signed-off-by: Mimi Zohar Acked-by: Kees Cook Acked-by: Luis R. Rodriguez Acked-by: Casey Schaufler --- fs/exec.c | 4 ++++ include/linux/ima.h | 6 ++++++ include/linux/lsm_hooks.h | 8 ++++++++ include/linux/security.h | 7 +++++++ security/integrity/ima/ima_main.c | 16 ++++++++++++++++ security/security.c | 13 +++++++++++++ 6 files changed, 54 insertions(+) (limited to 'security') diff --git a/fs/exec.c b/fs/exec.c index 64cb3bc788c1..8aaa38666119 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -842,6 +842,10 @@ int kernel_read_file(struct file *file, void **buf, loff_t *size, if (!S_ISREG(file_inode(file)->i_mode) || max_size < 0) return -EINVAL; + ret = security_kernel_read_file(file, id); + if (ret) + return ret; + i_size = i_size_read(file_inode(file)); if (max_size > 0 && i_size > max_size) return -EFBIG; diff --git a/include/linux/ima.h b/include/linux/ima.h index 7aea4863c244..6adcaea8101c 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -19,6 +19,7 @@ extern int ima_file_check(struct file *file, int mask, int opened); extern void ima_file_free(struct file *file); extern int ima_file_mmap(struct file *file, unsigned long prot); extern int ima_module_check(struct file *file); +extern int ima_read_file(struct file *file, enum kernel_read_file_id id); extern int ima_post_read_file(struct file *file, void *buf, loff_t size, enum kernel_read_file_id id); @@ -48,6 +49,11 @@ static inline int ima_module_check(struct file *file) return 0; } +static inline int ima_read_file(struct file *file, enum kernel_read_file_id id) +{ + return 0; +} + static inline int ima_post_read_file(struct file *file, void *buf, loff_t size, enum kernel_read_file_id id) { diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index 7d04a1220223..d32b7bd13635 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -552,6 +552,12 @@ * the kernel module to load. If the module is being loaded from a blob, * this argument will be NULL. * Return 0 if permission is granted. + * @kernel_read_file: + * Read a file specified by userspace. + * @file contains the file structure pointing to the file being read + * by the kernel. + * @id kernel read file identifier + * Return 0 if permission is granted. * @kernel_post_read_file: * Read a file specified by userspace. * @file contains the file structure pointing to the file being read @@ -1455,6 +1461,7 @@ union security_list_options { int (*kernel_create_files_as)(struct cred *new, struct inode *inode); int (*kernel_module_request)(char *kmod_name); int (*kernel_module_from_file)(struct file *file); + int (*kernel_read_file)(struct file *file, enum kernel_read_file_id id); int (*kernel_post_read_file)(struct file *file, char *buf, loff_t size, enum kernel_read_file_id id); int (*task_fix_setuid)(struct cred *new, const struct cred *old, @@ -1715,6 +1722,7 @@ struct security_hook_heads { struct list_head cred_transfer; struct list_head kernel_act_as; struct list_head kernel_create_files_as; + struct list_head kernel_read_file; struct list_head kernel_post_read_file; struct list_head kernel_module_request; struct list_head kernel_module_from_file; diff --git a/include/linux/security.h b/include/linux/security.h index cee1349e1155..071fb747fdbb 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -302,6 +302,7 @@ int security_kernel_act_as(struct cred *new, u32 secid); int security_kernel_create_files_as(struct cred *new, struct inode *inode); int security_kernel_module_request(char *kmod_name); int security_kernel_module_from_file(struct file *file); +int security_kernel_read_file(struct file *file, enum kernel_read_file_id id); int security_kernel_post_read_file(struct file *file, char *buf, loff_t size, enum kernel_read_file_id id); int security_task_fix_setuid(struct cred *new, const struct cred *old, @@ -863,6 +864,12 @@ static inline int security_kernel_module_from_file(struct file *file) return 0; } +static inline int security_kernel_read_file(struct file *file, + enum kernel_read_file_id id) +{ + return 0; +} + static inline int security_kernel_post_read_file(struct file *file, char *buf, loff_t size, enum kernel_read_file_id id) diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index e9651be17b72..bbb80df28fb1 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -337,6 +337,22 @@ int ima_module_check(struct file *file) return process_measurement(file, NULL, 0, MAY_EXEC, MODULE_CHECK, 0); } +/** + * ima_read_file - pre-measure/appraise hook decision based on policy + * @file: pointer to the file to be measured/appraised/audit + * @read_id: caller identifier + * + * Permit reading a file based on policy. The policy rules are written + * in terms of the policy identifier. Appraising the integrity of + * a file requires a file descriptor. + * + * For permission return 0, otherwise return -EACCES. + */ +int ima_read_file(struct file *file, enum kernel_read_file_id read_id) +{ + return 0; +} + /** * ima_post_read_file - in memory collect/appraise/audit measurement * @file: pointer to the file to be measured/appraised/audit diff --git a/security/security.c b/security/security.c index cd85be61c416..8e699f98a600 100644 --- a/security/security.c +++ b/security/security.c @@ -899,6 +899,17 @@ int security_kernel_module_from_file(struct file *file) return ima_module_check(file); } +int security_kernel_read_file(struct file *file, enum kernel_read_file_id id) +{ + int ret; + + ret = call_int_hook(kernel_read_file, 0, file, id); + if (ret) + return ret; + return ima_read_file(file, id); +} +EXPORT_SYMBOL_GPL(security_kernel_read_file); + int security_kernel_post_read_file(struct file *file, char *buf, loff_t size, enum kernel_read_file_id id) { @@ -1696,6 +1707,8 @@ struct security_hook_heads security_hook_heads = { LIST_HEAD_INIT(security_hook_heads.kernel_module_request), .kernel_module_from_file = LIST_HEAD_INIT(security_hook_heads.kernel_module_from_file), + .kernel_read_file = + LIST_HEAD_INIT(security_hook_heads.kernel_read_file), .kernel_post_read_file = LIST_HEAD_INIT(security_hook_heads.kernel_post_read_file), .task_fix_setuid = -- cgit v1.2.3 From a1db74209483a24c861c848b4bb79a4d945ef6fa Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Wed, 30 Dec 2015 07:35:30 -0500 Subject: module: replace copy_module_from_fd with kernel version Replace copy_module_from_fd() with kernel_read_file_from_fd(). Although none of the upstreamed LSMs define a kernel_module_from_file hook, IMA is called, based on policy, to prevent unsigned kernel modules from being loaded by the original kernel module syscall and to measure/appraise signed kernel modules. The security function security_kernel_module_from_file() was called prior to reading a kernel module. Preventing unsigned kernel modules from being loaded by the original kernel module syscall remains on the pre-read kernel_read_file() security hook. Instead of reading the kernel module twice, once for measuring/appraising and again for loading the kernel module, the signature validation is moved to the kernel_post_read_file() security hook. This patch removes the security_kernel_module_from_file() hook and security call. Signed-off-by: Mimi Zohar Acked-by: Kees Cook Acked-by: Luis R. Rodriguez Cc: Rusty Russell --- include/linux/fs.h | 1 + include/linux/ima.h | 6 ---- include/linux/lsm_hooks.h | 7 ---- include/linux/security.h | 5 --- kernel/module.c | 68 +++++---------------------------------- security/integrity/ima/ima_main.c | 35 ++++++++------------ security/security.c | 12 ------- 7 files changed, 22 insertions(+), 112 deletions(-) (limited to 'security') diff --git a/include/linux/fs.h b/include/linux/fs.h index 9c85deae1bf2..fb08b668c37a 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2578,6 +2578,7 @@ extern int do_pipe_flags(int *, int); enum kernel_read_file_id { READING_FIRMWARE = 1, + READING_MODULE, READING_MAX_ID }; diff --git a/include/linux/ima.h b/include/linux/ima.h index 6adcaea8101c..e6516cbbe9bf 100644 --- a/include/linux/ima.h +++ b/include/linux/ima.h @@ -18,7 +18,6 @@ extern int ima_bprm_check(struct linux_binprm *bprm); extern int ima_file_check(struct file *file, int mask, int opened); extern void ima_file_free(struct file *file); extern int ima_file_mmap(struct file *file, unsigned long prot); -extern int ima_module_check(struct file *file); extern int ima_read_file(struct file *file, enum kernel_read_file_id id); extern int ima_post_read_file(struct file *file, void *buf, loff_t size, enum kernel_read_file_id id); @@ -44,11 +43,6 @@ static inline int ima_file_mmap(struct file *file, unsigned long prot) return 0; } -static inline int ima_module_check(struct file *file) -{ - return 0; -} - static inline int ima_read_file(struct file *file, enum kernel_read_file_id id) { return 0; diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h index d32b7bd13635..cdee11cbcdf1 100644 --- a/include/linux/lsm_hooks.h +++ b/include/linux/lsm_hooks.h @@ -546,12 +546,6 @@ * userspace to load a kernel module with the given name. * @kmod_name name of the module requested by the kernel * Return 0 if successful. - * @kernel_module_from_file: - * Load a kernel module from userspace. - * @file contains the file structure pointing to the file containing - * the kernel module to load. If the module is being loaded from a blob, - * this argument will be NULL. - * Return 0 if permission is granted. * @kernel_read_file: * Read a file specified by userspace. * @file contains the file structure pointing to the file being read @@ -1725,7 +1719,6 @@ struct security_hook_heads { struct list_head kernel_read_file; struct list_head kernel_post_read_file; struct list_head kernel_module_request; - struct list_head kernel_module_from_file; struct list_head task_fix_setuid; struct list_head task_setpgid; struct list_head task_getpgid; diff --git a/include/linux/security.h b/include/linux/security.h index 071fb747fdbb..157f0cb1e4d2 100644 --- a/include/linux/security.h +++ b/include/linux/security.h @@ -859,11 +859,6 @@ static inline int security_kernel_module_request(char *kmod_name) return 0; } -static inline int security_kernel_module_from_file(struct file *file) -{ - return 0; -} - static inline int security_kernel_read_file(struct file *file, enum kernel_read_file_id id) { diff --git a/kernel/module.c b/kernel/module.c index 8358f4697c0c..955410928696 100644 --- a/kernel/module.c +++ b/kernel/module.c @@ -2654,7 +2654,7 @@ static int copy_module_from_user(const void __user *umod, unsigned long len, if (info->len < sizeof(*(info->hdr))) return -ENOEXEC; - err = security_kernel_module_from_file(NULL); + err = security_kernel_read_file(NULL, READING_MODULE); if (err) return err; @@ -2672,63 +2672,6 @@ static int copy_module_from_user(const void __user *umod, unsigned long len, return 0; } -/* Sets info->hdr and info->len. */ -static int copy_module_from_fd(int fd, struct load_info *info) -{ - struct fd f = fdget(fd); - int err; - struct kstat stat; - loff_t pos; - ssize_t bytes = 0; - - if (!f.file) - return -ENOEXEC; - - err = security_kernel_module_from_file(f.file); - if (err) - goto out; - - err = vfs_getattr(&f.file->f_path, &stat); - if (err) - goto out; - - if (stat.size > INT_MAX) { - err = -EFBIG; - goto out; - } - - /* Don't hand 0 to vmalloc, it whines. */ - if (stat.size == 0) { - err = -EINVAL; - goto out; - } - - info->hdr = vmalloc(stat.size); - if (!info->hdr) { - err = -ENOMEM; - goto out; - } - - pos = 0; - while (pos < stat.size) { - bytes = kernel_read(f.file, pos, (char *)(info->hdr) + pos, - stat.size - pos); - if (bytes < 0) { - vfree(info->hdr); - err = bytes; - goto out; - } - if (bytes == 0) - break; - pos += bytes; - } - info->len = pos; - -out: - fdput(f); - return err; -} - static void free_copy(struct load_info *info) { vfree(info->hdr); @@ -3589,8 +3532,10 @@ SYSCALL_DEFINE3(init_module, void __user *, umod, SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags) { - int err; struct load_info info = { }; + loff_t size; + void *hdr; + int err; err = may_init_module(); if (err) @@ -3602,9 +3547,12 @@ SYSCALL_DEFINE3(finit_module, int, fd, const char __user *, uargs, int, flags) |MODULE_INIT_IGNORE_VERMAGIC)) return -EINVAL; - err = copy_module_from_fd(fd, &info); + err = kernel_read_file_from_fd(fd, &hdr, &size, INT_MAX, + READING_MODULE); if (err) return err; + info.hdr = hdr; + info.len = size; return load_module(&info, uargs, flags); } diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index bbb80df28fb1..5da0b9c00072 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -315,28 +315,6 @@ int ima_file_check(struct file *file, int mask, int opened) } EXPORT_SYMBOL_GPL(ima_file_check); -/** - * ima_module_check - based on policy, collect/store/appraise measurement. - * @file: pointer to the file to be measured/appraised - * - * Measure/appraise kernel modules based on policy. - * - * On success return 0. On integrity appraisal error, assuming the file - * is in policy and IMA-appraisal is in enforcing mode, return -EACCES. - */ -int ima_module_check(struct file *file) -{ - if (!file) { -#ifndef CONFIG_MODULE_SIG_FORCE - if ((ima_appraise & IMA_APPRAISE_MODULES) && - (ima_appraise & IMA_APPRAISE_ENFORCE)) - return -EACCES; /* INTEGRITY_UNKNOWN */ -#endif - return 0; /* We rely on module signature checking */ - } - return process_measurement(file, NULL, 0, MAY_EXEC, MODULE_CHECK, 0); -} - /** * ima_read_file - pre-measure/appraise hook decision based on policy * @file: pointer to the file to be measured/appraised/audit @@ -350,6 +328,14 @@ int ima_module_check(struct file *file) */ int ima_read_file(struct file *file, enum kernel_read_file_id read_id) { + if (!file && read_id == READING_MODULE) { +#ifndef CONFIG_MODULE_SIG_FORCE + if ((ima_appraise & IMA_APPRAISE_MODULES) && + (ima_appraise & IMA_APPRAISE_ENFORCE)) + return -EACCES; /* INTEGRITY_UNKNOWN */ +#endif + return 0; /* We rely on module signature checking */ + } return 0; } @@ -378,6 +364,9 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size, return 0; } + if (!file && read_id == READING_MODULE) /* MODULE_SIG_FORCE enabled */ + return 0; + if (!file || !buf || size == 0) { /* should never happen */ if (ima_appraise & IMA_APPRAISE_ENFORCE) return -EACCES; @@ -386,6 +375,8 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size, if (read_id == READING_FIRMWARE) func = FIRMWARE_CHECK; + else if (read_id == READING_MODULE) + func = MODULE_CHECK; return process_measurement(file, buf, size, MAY_READ, func, 0); } diff --git a/security/security.c b/security/security.c index 8e699f98a600..3644b0344d29 100644 --- a/security/security.c +++ b/security/security.c @@ -889,16 +889,6 @@ int security_kernel_module_request(char *kmod_name) return call_int_hook(kernel_module_request, 0, kmod_name); } -int security_kernel_module_from_file(struct file *file) -{ - int ret; - - ret = call_int_hook(kernel_module_from_file, 0, file); - if (ret) - return ret; - return ima_module_check(file); -} - int security_kernel_read_file(struct file *file, enum kernel_read_file_id id) { int ret; @@ -1705,8 +1695,6 @@ struct security_hook_heads security_hook_heads = { LIST_HEAD_INIT(security_hook_heads.kernel_create_files_as), .kernel_module_request = LIST_HEAD_INIT(security_hook_heads.kernel_module_request), - .kernel_module_from_file = - LIST_HEAD_INIT(security_hook_heads.kernel_module_from_file), .kernel_read_file = LIST_HEAD_INIT(security_hook_heads.kernel_read_file), .kernel_post_read_file = -- cgit v1.2.3 From c6af8efe97d87fa308eb1bbd0cf4feb820a4d622 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Thu, 19 Nov 2015 12:39:22 -0500 Subject: ima: remove firmware and module specific cached status info Each time a file is read by the kernel, the file should be re-measured and the file signature re-appraised, based on policy. As there is no need to preserve the status information, this patch replaces the firmware and module specific cache status with a generic one named read_file. This change simplifies adding support for other files read by the kernel. Signed-off-by: Mimi Zohar Acked-by: Petko Manolov Acked-by: Dmitry Kasatkin --- security/integrity/iint.c | 4 ++-- security/integrity/ima/ima.h | 3 ++- security/integrity/ima/ima_appraise.c | 35 ++++++++++++++++------------------- security/integrity/ima/ima_policy.c | 9 ++++----- security/integrity/integrity.h | 16 ++++------------ 5 files changed, 28 insertions(+), 39 deletions(-) (limited to 'security') diff --git a/security/integrity/iint.c b/security/integrity/iint.c index 8f1ab37f2897..345b75997e4c 100644 --- a/security/integrity/iint.c +++ b/security/integrity/iint.c @@ -77,7 +77,7 @@ static void iint_free(struct integrity_iint_cache *iint) iint->ima_file_status = INTEGRITY_UNKNOWN; iint->ima_mmap_status = INTEGRITY_UNKNOWN; iint->ima_bprm_status = INTEGRITY_UNKNOWN; - iint->ima_module_status = INTEGRITY_UNKNOWN; + iint->ima_read_status = INTEGRITY_UNKNOWN; iint->evm_status = INTEGRITY_UNKNOWN; kmem_cache_free(iint_cache, iint); } @@ -157,7 +157,7 @@ static void init_once(void *foo) iint->ima_file_status = INTEGRITY_UNKNOWN; iint->ima_mmap_status = INTEGRITY_UNKNOWN; iint->ima_bprm_status = INTEGRITY_UNKNOWN; - iint->ima_module_status = INTEGRITY_UNKNOWN; + iint->ima_read_status = INTEGRITY_UNKNOWN; iint->evm_status = INTEGRITY_UNKNOWN; } diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 0b7134c04165..a5d25921ee3c 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -144,9 +144,10 @@ enum ima_hooks { FILE_CHECK = 1, MMAP_CHECK, BPRM_CHECK, + POST_SETATTR, MODULE_CHECK, FIRMWARE_CHECK, - POST_SETATTR + MAX_CHECK }; /* LIM API function definitions */ diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index cb0d0ff1137b..6b4694aedae8 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -74,13 +74,12 @@ enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, return iint->ima_mmap_status; case BPRM_CHECK: return iint->ima_bprm_status; - case MODULE_CHECK: - return iint->ima_module_status; - case FIRMWARE_CHECK: - return iint->ima_firmware_status; case FILE_CHECK: - default: + case POST_SETATTR: return iint->ima_file_status; + case MODULE_CHECK ... MAX_CHECK - 1: + default: + return iint->ima_read_status; } } @@ -95,15 +94,14 @@ static void ima_set_cache_status(struct integrity_iint_cache *iint, case BPRM_CHECK: iint->ima_bprm_status = status; break; - case MODULE_CHECK: - iint->ima_module_status = status; - break; - case FIRMWARE_CHECK: - iint->ima_firmware_status = status; - break; case FILE_CHECK: - default: + case POST_SETATTR: iint->ima_file_status = status; + break; + case MODULE_CHECK ... MAX_CHECK - 1: + default: + iint->ima_read_status = status; + break; } } @@ -117,15 +115,14 @@ static void ima_cache_flags(struct integrity_iint_cache *iint, case BPRM_CHECK: iint->flags |= (IMA_BPRM_APPRAISED | IMA_APPRAISED); break; - case MODULE_CHECK: - iint->flags |= (IMA_MODULE_APPRAISED | IMA_APPRAISED); - break; - case FIRMWARE_CHECK: - iint->flags |= (IMA_FIRMWARE_APPRAISED | IMA_APPRAISED); - break; case FILE_CHECK: - default: + case POST_SETATTR: iint->flags |= (IMA_FILE_APPRAISED | IMA_APPRAISED); + break; + case MODULE_CHECK ... MAX_CHECK - 1: + default: + iint->flags |= (IMA_READ_APPRAISED | IMA_APPRAISED); + break; } } diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index cfbe86f476d0..7571ce8841ff 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -300,13 +300,12 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func) return IMA_MMAP_APPRAISE; case BPRM_CHECK: return IMA_BPRM_APPRAISE; - case MODULE_CHECK: - return IMA_MODULE_APPRAISE; - case FIRMWARE_CHECK: - return IMA_FIRMWARE_APPRAISE; case FILE_CHECK: - default: + case POST_SETATTR: return IMA_FILE_APPRAISE; + case MODULE_CHECK ... MAX_CHECK - 1: + default: + return IMA_READ_APPRAISE; } } diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 9a0ea4c4e3dd..c7a111cc7d89 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -45,18 +45,12 @@ #define IMA_MMAP_APPRAISED 0x00000800 #define IMA_BPRM_APPRAISE 0x00001000 #define IMA_BPRM_APPRAISED 0x00002000 -#define IMA_MODULE_APPRAISE 0x00004000 -#define IMA_MODULE_APPRAISED 0x00008000 -#define IMA_FIRMWARE_APPRAISE 0x00010000 -#define IMA_FIRMWARE_APPRAISED 0x00020000 -#define IMA_READ_APPRAISE 0x00040000 -#define IMA_READ_APPRAISED 0x00080000 +#define IMA_READ_APPRAISE 0x00004000 +#define IMA_READ_APPRAISED 0x00008000 #define IMA_APPRAISE_SUBMASK (IMA_FILE_APPRAISE | IMA_MMAP_APPRAISE | \ - IMA_BPRM_APPRAISE | IMA_MODULE_APPRAISE | \ - IMA_FIRMWARE_APPRAISE | IMA_READ_APPRAISE) + IMA_BPRM_APPRAISE | IMA_READ_APPRAISE) #define IMA_APPRAISED_SUBMASK (IMA_FILE_APPRAISED | IMA_MMAP_APPRAISED | \ - IMA_BPRM_APPRAISED | IMA_MODULE_APPRAISED | \ - IMA_FIRMWARE_APPRAISED | IMA_READ_APPRAISED) + IMA_BPRM_APPRAISED | IMA_READ_APPRAISED) enum evm_ima_xattr_type { IMA_XATTR_DIGEST = 0x01, @@ -111,8 +105,6 @@ struct integrity_iint_cache { enum integrity_status ima_file_status:4; enum integrity_status ima_mmap_status:4; enum integrity_status ima_bprm_status:4; - enum integrity_status ima_module_status:4; - enum integrity_status ima_firmware_status:4; enum integrity_status ima_read_status:4; enum integrity_status evm_status:4; struct ima_digest_data *ima_hash; -- cgit v1.2.3 From d9ddf077bb85b54200dfcb5f2edec4f0d6a7c2ca Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Thu, 14 Jan 2016 20:59:14 -0500 Subject: ima: support for kexec image and initramfs Add IMA policy support for measuring/appraising the kexec image and initramfs. Two new IMA policy identifiers KEXEC_KERNEL_CHECK and KEXEC_INITRAMFS_CHECK are defined. Example policy rules: measure func=KEXEC_KERNEL_CHECK appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig measure func=KEXEC_INITRAMFS_CHECK appraise func=KEXEC_INITRAMFS_CHECK appraise_type=imasig Moving the enumeration to the vfs layer simplified the patches, allowing the IMA changes, for the most part, to be separated from the other changes. Unfortunately, passing either a kernel_read_file_id or a ima_hooks enumeration within IMA is messy. Option 1: duplicate kernel_read_file enumeration in ima_hooks enum kernel_read_file_id { ... READING_KEXEC_IMAGE, READING_KEXEC_INITRAMFS, READING_MAX_ID enum ima_hooks { ... KEXEC_KERNEL_CHECK KEXEC_INITRAMFS_CHECK Option 2: define ima_hooks as extension of kernel_read_file eg: enum ima_hooks { FILE_CHECK = READING_MAX_ID, MMAP_CHECK, In order to pass both kernel_read_file_id and ima_hooks values, we would need to specify a struct containing a union. struct caller_id { union { enum ima_hooks func_id; enum kernel_read_file_id read_id; }; }; Option 3: incorportate the ima_hooks enumeration into kernel_read_file_id, perhaps changing the enumeration name. For now, duplicate the new READING_KEXEC_IMAGE/INITRAMFS in the ima_hooks. Changelog v4: - replaced switch statement with a kernel_read_file_id to an ima_hooks id mapping array - Dmitry - renamed ima_hook tokens KEXEC_CHECK and INITRAMFS_CHECK to KEXEC_KERNEL_CHECK and KEXEC_INITRAMFS_CHECK respectively - Dave Young Signed-off-by: Mimi Zohar Acked-by: Petko Manolov Acked-by: Dmitry Kasatkin Cc: Dave Young --- Documentation/ABI/testing/ima_policy | 1 + security/integrity/ima/ima.h | 2 ++ security/integrity/ima/ima_main.c | 15 +++++++++------ security/integrity/ima/ima_policy.c | 17 ++++++++++++++++- 4 files changed, 28 insertions(+), 7 deletions(-) (limited to 'security') diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy index 0a378a88217a..bb0f9a135e21 100644 --- a/Documentation/ABI/testing/ima_policy +++ b/Documentation/ABI/testing/ima_policy @@ -27,6 +27,7 @@ Description: base: func:= [BPRM_CHECK][MMAP_CHECK][FILE_CHECK][MODULE_CHECK] [FIRMWARE_CHECK] + [KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK] mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND] [[^]MAY_EXEC] fsmagic:= hex value diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index a5d25921ee3c..bd97e0d290de 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -147,6 +147,8 @@ enum ima_hooks { POST_SETATTR, MODULE_CHECK, FIRMWARE_CHECK, + KEXEC_KERNEL_CHECK, + KEXEC_INITRAMFS_CHECK, MAX_CHECK }; diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index 5da0b9c00072..f76488162c1e 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -339,6 +339,13 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id) return 0; } +static int read_idmap[READING_MAX_ID] = { + [READING_FIRMWARE] = FIRMWARE_CHECK, + [READING_MODULE] = MODULE_CHECK, + [READING_KEXEC_IMAGE] = KEXEC_KERNEL_CHECK, + [READING_KEXEC_INITRAMFS] = KEXEC_INITRAMFS_CHECK, +}; + /** * ima_post_read_file - in memory collect/appraise/audit measurement * @file: pointer to the file to be measured/appraised/audit @@ -355,7 +362,7 @@ int ima_read_file(struct file *file, enum kernel_read_file_id read_id) int ima_post_read_file(struct file *file, void *buf, loff_t size, enum kernel_read_file_id read_id) { - enum ima_hooks func = FILE_CHECK; + enum ima_hooks func; if (!file && read_id == READING_FIRMWARE) { if ((ima_appraise & IMA_APPRAISE_FIRMWARE) && @@ -373,11 +380,7 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size, return 0; } - if (read_id == READING_FIRMWARE) - func = FIRMWARE_CHECK; - else if (read_id == READING_MODULE) - func = MODULE_CHECK; - + func = read_idmap[read_id] ?: FILE_CHECK; return process_measurement(file, buf, size, MAY_READ, func, 0); } diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 7571ce8841ff..646134cdf3e8 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -612,6 +612,12 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) entry->func = MMAP_CHECK; else if (strcmp(args[0].from, "BPRM_CHECK") == 0) entry->func = BPRM_CHECK; + else if (strcmp(args[0].from, "KEXEC_KERNEL_CHECK") == + 0) + entry->func = KEXEC_KERNEL_CHECK; + else if (strcmp(args[0].from, "KEXEC_INITRAMFS_CHECK") + == 0) + entry->func = KEXEC_INITRAMFS_CHECK; else result = -EINVAL; if (!result) @@ -855,7 +861,8 @@ static char *mask_tokens[] = { enum { func_file = 0, func_mmap, func_bprm, - func_module, func_firmware, func_post + func_module, func_firmware, func_post, + func_kexec_kernel, func_kexec_initramfs }; static char *func_tokens[] = { @@ -864,6 +871,8 @@ static char *func_tokens[] = { "BPRM_CHECK", "MODULE_CHECK", "FIRMWARE_CHECK", + "KEXEC_KERNEL_CHECK", + "KEXEC_INITRAMFS_CHECK", "POST_SETATTR" }; @@ -929,6 +938,12 @@ static void policy_func_show(struct seq_file *m, enum ima_hooks func) case POST_SETATTR: seq_printf(m, pt(Opt_func), ft(func_post)); break; + case KEXEC_KERNEL_CHECK: + seq_printf(m, pt(Opt_func), ft(func_kexec_kernel)); + break; + case KEXEC_INITRAMFS_CHECK: + seq_printf(m, pt(Opt_func), ft(func_kexec_initramfs)); + break; default: snprintf(tbuf, sizeof(tbuf), "%d", func); seq_printf(m, pt(Opt_func), tbuf); -- cgit v1.2.3 From 7429b092811fb20c6a5b261c2c116a6a90cb9a29 Mon Sep 17 00:00:00 2001 From: Dmitry Kasatkin Date: Fri, 11 Apr 2014 17:47:01 +0300 Subject: ima: load policy using path We currently cannot do appraisal or signature vetting of IMA policies since we currently can only load IMA policies by writing the contents of the policy directly in, as follows: cat policy-file > /ima/policy If we provide the kernel the path to the IMA policy so it can load the policy itself it'd be able to later appraise or vet the file signature if it has one. This patch adds support to load the IMA policy with a given path as follows: echo /etc/ima/ima_policy > /sys/kernel/security/ima/policy Changelog v4+: - moved kernel_read_file_from_path() error messages to callers v3: - moved kernel_read_file_from_path() to a separate patch v2: - after re-ordering the patches, replace calling integrity_kernel_read() to read the file with kernel_read_file_from_path() (Mimi) - Patch description re-written by Luis R. Rodriguez Signed-off-by: Dmitry Kasatkin Signed-off-by: Mimi Zohar --- include/linux/fs.h | 1 + security/integrity/ima/ima_fs.c | 45 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 44 insertions(+), 2 deletions(-) (limited to 'security') diff --git a/include/linux/fs.h b/include/linux/fs.h index 52567252288e..e514f76db04f 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2581,6 +2581,7 @@ enum kernel_read_file_id { READING_MODULE, READING_KEXEC_IMAGE, READING_KEXEC_INITRAMFS, + READING_POLICY, READING_MAX_ID }; diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index f355231997b4..a6c61b351f36 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -22,6 +22,7 @@ #include #include #include +#include #include "ima.h" @@ -258,6 +259,43 @@ static const struct file_operations ima_ascii_measurements_ops = { .release = seq_release, }; +static ssize_t ima_read_policy(char *path) +{ + void *data; + char *datap; + loff_t size; + int rc, pathlen = strlen(path); + + char *p; + + /* remove \n */ + datap = path; + strsep(&datap, "\n"); + + rc = kernel_read_file_from_path(path, &data, &size, 0, READING_POLICY); + if (rc < 0) { + pr_err("Unable to open file: %s (%d)", path, rc); + return rc; + } + + datap = data; + while (size > 0 && (p = strsep(&datap, "\n"))) { + pr_debug("rule: %s\n", p); + rc = ima_parse_add_rule(p); + if (rc < 0) + break; + size -= rc; + } + + vfree(data); + if (rc < 0) + return rc; + else if (size) + return -EINVAL; + else + return pathlen; +} + static ssize_t ima_write_policy(struct file *file, const char __user *buf, size_t datalen, loff_t *ppos) { @@ -286,9 +324,12 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf, result = mutex_lock_interruptible(&ima_write_mutex); if (result < 0) goto out_free; - result = ima_parse_add_rule(data); - mutex_unlock(&ima_write_mutex); + if (data[0] == '/') + result = ima_read_policy(data); + else + result = ima_parse_add_rule(data); + mutex_unlock(&ima_write_mutex); out_free: kfree(data); out: -- cgit v1.2.3 From 19f8a84713edc1d27ea05be00effb97b8f1ef207 Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Fri, 15 Jan 2016 10:17:12 -0500 Subject: ima: measure and appraise the IMA policy itself Add support for measuring and appraising the IMA policy itself. Changelog v4: - use braces on both if/else branches, even if single line on one of the branches - Dmitry - Use the id mapping - Dmitry Signed-off-by: Mimi Zohar Acked-by: Petko Manolov Acked-by: Dmitry Kasatkin --- security/integrity/ima/ima.h | 2 ++ security/integrity/ima/ima_fs.c | 12 ++++++++++-- security/integrity/ima/ima_main.c | 1 + security/integrity/ima/ima_policy.c | 12 +++++++++++- 4 files changed, 24 insertions(+), 3 deletions(-) (limited to 'security') diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index bd97e0d290de..5d0f61163d98 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -149,6 +149,7 @@ enum ima_hooks { FIRMWARE_CHECK, KEXEC_KERNEL_CHECK, KEXEC_INITRAMFS_CHECK, + POLICY_CHECK, MAX_CHECK }; @@ -191,6 +192,7 @@ int ima_policy_show(struct seq_file *m, void *v); #define IMA_APPRAISE_LOG 0x04 #define IMA_APPRAISE_MODULES 0x08 #define IMA_APPRAISE_FIRMWARE 0x10 +#define IMA_APPRAISE_POLICY 0x20 #ifdef CONFIG_IMA_APPRAISE int ima_appraise_measurement(enum ima_hooks func, diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index a6c61b351f36..60d011aaec38 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -325,10 +325,18 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf, if (result < 0) goto out_free; - if (data[0] == '/') + if (data[0] == '/') { result = ima_read_policy(data); - else + } else if (ima_appraise & IMA_APPRAISE_POLICY) { + pr_err("IMA: signed policy file (specified as an absolute pathname) required\n"); + integrity_audit_msg(AUDIT_INTEGRITY_STATUS, NULL, NULL, + "policy_update", "signed policy required", + 1, 0); + if (ima_appraise & IMA_APPRAISE_ENFORCE) + result = -EACCES; + } else { result = ima_parse_add_rule(data); + } mutex_unlock(&ima_write_mutex); out_free: kfree(data); diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c index f76488162c1e..391f41751021 100644 --- a/security/integrity/ima/ima_main.c +++ b/security/integrity/ima/ima_main.c @@ -344,6 +344,7 @@ static int read_idmap[READING_MAX_ID] = { [READING_MODULE] = MODULE_CHECK, [READING_KEXEC_IMAGE] = KEXEC_KERNEL_CHECK, [READING_KEXEC_INITRAMFS] = KEXEC_INITRAMFS_CHECK, + [READING_POLICY] = POLICY_CHECK }; /** diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index 646134cdf3e8..c1b5d00fe5d4 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -114,6 +114,7 @@ static struct ima_rule_entry default_measurement_rules[] = { .uid = GLOBAL_ROOT_UID, .flags = IMA_FUNC | IMA_INMASK | IMA_UID}, {.action = MEASURE, .func = MODULE_CHECK, .flags = IMA_FUNC}, {.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC}, + {.action = MEASURE, .func = POLICY_CHECK, .flags = IMA_FUNC}, }; static struct ima_rule_entry default_appraise_rules[] = { @@ -618,6 +619,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) else if (strcmp(args[0].from, "KEXEC_INITRAMFS_CHECK") == 0) entry->func = KEXEC_INITRAMFS_CHECK; + else if (strcmp(args[0].from, "POLICY_CHECK") == 0) + entry->func = POLICY_CHECK; else result = -EINVAL; if (!result) @@ -776,6 +779,8 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) temp_ima_appraise |= IMA_APPRAISE_MODULES; else if (entry->func == FIRMWARE_CHECK) temp_ima_appraise |= IMA_APPRAISE_FIRMWARE; + else if (entry->func == POLICY_CHECK) + temp_ima_appraise |= IMA_APPRAISE_POLICY; audit_log_format(ab, "res=%d", !result); audit_log_end(ab); return result; @@ -862,7 +867,8 @@ static char *mask_tokens[] = { enum { func_file = 0, func_mmap, func_bprm, func_module, func_firmware, func_post, - func_kexec_kernel, func_kexec_initramfs + func_kexec_kernel, func_kexec_initramfs, + func_policy }; static char *func_tokens[] = { @@ -873,6 +879,7 @@ static char *func_tokens[] = { "FIRMWARE_CHECK", "KEXEC_KERNEL_CHECK", "KEXEC_INITRAMFS_CHECK", + "POLICY_CHECK", "POST_SETATTR" }; @@ -944,6 +951,9 @@ static void policy_func_show(struct seq_file *m, enum ima_hooks func) case KEXEC_INITRAMFS_CHECK: seq_printf(m, pt(Opt_func), ft(func_kexec_initramfs)); break; + case POLICY_CHECK: + seq_printf(m, pt(Opt_func), ft(func_policy)); + break; default: snprintf(tbuf, sizeof(tbuf), "%d", func); seq_printf(m, pt(Opt_func), tbuf); -- cgit v1.2.3 From 95ee08fa373b9ede1059c2f384cfeafe10dcd6bb Mon Sep 17 00:00:00 2001 From: Mimi Zohar Date: Mon, 7 Dec 2015 15:08:01 -0500 Subject: ima: require signed IMA policy Require the IMA policy to be signed when additional rules can be added. v1: - initialize the policy flag - include IMA_APPRAISE_POLICY in the policy flag Signed-off-by: Mimi Zohar Acked-by: Petko Manolov Acked-by: Dmitry Kasatkin --- security/integrity/ima/ima_policy.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'security') diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index c1b5d00fe5d4..be09e2cacf82 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -129,6 +129,10 @@ static struct ima_rule_entry default_appraise_rules[] = { {.action = DONT_APPRAISE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC}, {.action = DONT_APPRAISE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC}, {.action = DONT_APPRAISE, .fsmagic = CGROUP_SUPER_MAGIC, .flags = IMA_FSMAGIC}, +#ifdef CONFIG_IMA_WRITE_POLICY + {.action = APPRAISE, .func = POLICY_CHECK, + .flags = IMA_FUNC | IMA_DIGSIG_REQUIRED}, +#endif #ifndef CONFIG_IMA_APPRAISE_SIGNED_INIT {.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .flags = IMA_FOWNER}, #else @@ -412,9 +416,12 @@ void __init ima_init_policy(void) for (i = 0; i < appraise_entries; i++) { list_add_tail(&default_appraise_rules[i].list, &ima_default_rules); + if (default_appraise_rules[i].func == POLICY_CHECK) + temp_ima_appraise |= IMA_APPRAISE_POLICY; } ima_rules = &ima_default_rules; + ima_update_policy_flag(); } /* Make sure we have a valid policy, at least containing some rules. */ -- cgit v1.2.3 From d43de6c780a84def056afaf4fb3e66bdaa1efc00 Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 3 Mar 2016 21:49:27 +0000 Subject: akcipher: Move the RSA DER encoding check to the crypto layer Move the RSA EMSA-PKCS1-v1_5 encoding from the asymmetric-key public_key subtype to the rsa crypto module's pkcs1pad template. This means that the public_key subtype no longer has any dependencies on public key type. To make this work, the following changes have been made: (1) The rsa pkcs1pad template is now used for RSA keys. This strips off the padding and returns just the message hash. (2) In a previous patch, the pkcs1pad template gained an optional second parameter that, if given, specifies the hash used. We now give this, and pkcs1pad checks the encoded message E(M) for the EMSA-PKCS1-v1_5 encoding and verifies that the correct digest OID is present. (3) The crypto driver in crypto/asymmetric_keys/rsa.c is now reduced to something that doesn't care about what the encryption actually does and and has been merged into public_key.c. (4) CONFIG_PUBLIC_KEY_ALGO_RSA is gone. Module signing must set CONFIG_CRYPTO_RSA=y instead. Thoughts: (*) Should the encoding style (eg. raw, EMSA-PKCS1-v1_5) also be passed to the padding template? Should there be multiple padding templates registered that share most of the code? Signed-off-by: David Howells Signed-off-by: Tadeusz Struk Acked-by: Herbert Xu --- crypto/asymmetric_keys/Kconfig | 7 -- crypto/asymmetric_keys/Makefile | 1 - crypto/asymmetric_keys/public_key.c | 104 +++++++++++++-- crypto/asymmetric_keys/rsa.c | 224 --------------------------------- include/crypto/public_key.h | 2 - init/Kconfig | 2 +- security/integrity/digsig_asymmetric.c | 1 + 7 files changed, 95 insertions(+), 246 deletions(-) delete mode 100644 crypto/asymmetric_keys/rsa.c (limited to 'security') diff --git a/crypto/asymmetric_keys/Kconfig b/crypto/asymmetric_keys/Kconfig index 905d745c2f85..91a7e047a765 100644 --- a/crypto/asymmetric_keys/Kconfig +++ b/crypto/asymmetric_keys/Kconfig @@ -12,7 +12,6 @@ if ASYMMETRIC_KEY_TYPE config ASYMMETRIC_PUBLIC_KEY_SUBTYPE tristate "Asymmetric public-key crypto algorithm subtype" select MPILIB - select PUBLIC_KEY_ALGO_RSA select CRYPTO_HASH_INFO help This option provides support for asymmetric public key type handling. @@ -20,12 +19,6 @@ config ASYMMETRIC_PUBLIC_KEY_SUBTYPE appropriate hash algorithms (such as SHA-1) must be available. ENOPKG will be reported if the requisite algorithm is unavailable. -config PUBLIC_KEY_ALGO_RSA - tristate "RSA public-key algorithm" - select CRYPTO_RSA - help - This option enables support for the RSA algorithm (PKCS#1, RFC3447). - config X509_CERTIFICATE_PARSER tristate "X.509 certificate parser" depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE diff --git a/crypto/asymmetric_keys/Makefile b/crypto/asymmetric_keys/Makefile index b78a194ea014..f90486256f01 100644 --- a/crypto/asymmetric_keys/Makefile +++ b/crypto/asymmetric_keys/Makefile @@ -7,7 +7,6 @@ obj-$(CONFIG_ASYMMETRIC_KEY_TYPE) += asymmetric_keys.o asymmetric_keys-y := asymmetric_type.o signature.o obj-$(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += public_key.o -obj-$(CONFIG_PUBLIC_KEY_ALGO_RSA) += rsa.o # # X.509 Certificate handling diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c index b383629b9e62..27ebc2f44394 100644 --- a/crypto/asymmetric_keys/public_key.c +++ b/crypto/asymmetric_keys/public_key.c @@ -17,8 +17,10 @@ #include #include #include +#include #include #include +#include MODULE_LICENSE("GPL"); @@ -35,12 +37,6 @@ const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = { }; EXPORT_SYMBOL_GPL(pkey_id_type_name); -static int (*alg_verify[PKEY_ALGO__LAST])(const struct public_key *pkey, - const struct public_key_signature *sig) = { - NULL, - rsa_verify_signature -}; - /* * Provide a part of a description of the key for /proc/keys. */ @@ -68,24 +64,110 @@ void public_key_destroy(void *payload) } EXPORT_SYMBOL_GPL(public_key_destroy); +struct public_key_completion { + struct completion completion; + int err; +}; + +static void public_key_verify_done(struct crypto_async_request *req, int err) +{ + struct public_key_completion *compl = req->data; + + if (err == -EINPROGRESS) + return; + + compl->err = err; + complete(&compl->completion); +} + /* * Verify a signature using a public key. */ int public_key_verify_signature(const struct public_key *pkey, const struct public_key_signature *sig) { + struct public_key_completion compl; + struct crypto_akcipher *tfm; + struct akcipher_request *req; + struct scatterlist sig_sg, digest_sg; + const char *alg_name; + char alg_name_buf[CRYPTO_MAX_ALG_NAME]; + void *output; + unsigned int outlen; + int ret = -ENOMEM; + + pr_devel("==>%s()\n", __func__); + BUG_ON(!pkey); BUG_ON(!sig); BUG_ON(!sig->digest); BUG_ON(!sig->s); - if (pkey->pkey_algo >= PKEY_ALGO__LAST) - return -ENOPKG; + alg_name = pkey_algo_name[sig->pkey_algo]; + if (sig->pkey_algo == PKEY_ALGO_RSA) { + /* The data wangled by the RSA algorithm is typically padded + * and encoded in some manner, such as EMSA-PKCS1-1_5 [RFC3447 + * sec 8.2]. + */ + if (snprintf(alg_name_buf, CRYPTO_MAX_ALG_NAME, + "pkcs1pad(rsa,%s)", + hash_algo_name[sig->pkey_hash_algo] + ) >= CRYPTO_MAX_ALG_NAME) + return -EINVAL; + alg_name = alg_name_buf; + } + + tfm = crypto_alloc_akcipher(alg_name, 0, 0); + if (IS_ERR(tfm)) + return PTR_ERR(tfm); + + req = akcipher_request_alloc(tfm, GFP_KERNEL); + if (!req) + goto error_free_tfm; + + ret = crypto_akcipher_set_pub_key(tfm, pkey->key, pkey->keylen); + if (ret) + goto error_free_req; + + outlen = crypto_akcipher_maxsize(tfm); + output = kmalloc(outlen, GFP_KERNEL); + if (!output) + goto error_free_req; + + sg_init_one(&sig_sg, sig->s, sig->s_size); + sg_init_one(&digest_sg, output, outlen); + akcipher_request_set_crypt(req, &sig_sg, &digest_sg, sig->s_size, + outlen); + init_completion(&compl.completion); + akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | + CRYPTO_TFM_REQ_MAY_SLEEP, + public_key_verify_done, &compl); + + /* Perform the verification calculation. This doesn't actually do the + * verification, but rather calculates the hash expected by the + * signature and returns that to us. + */ + ret = crypto_akcipher_verify(req); + if (ret == -EINPROGRESS) { + wait_for_completion(&compl.completion); + ret = compl.err; + } + if (ret < 0) + goto out_free_output; - if (!alg_verify[pkey->pkey_algo]) - return -ENOPKG; + /* Do the actual verification step. */ + if (req->dst_len != sig->digest_size || + memcmp(sig->digest, output, sig->digest_size) != 0) + ret = -EKEYREJECTED; - return alg_verify[pkey->pkey_algo](pkey, sig); +out_free_output: + kfree(output); +error_free_req: + akcipher_request_free(req); +error_free_tfm: + crypto_free_akcipher(tfm); + pr_devel("<==%s() = %d\n", __func__, ret); + return ret; } EXPORT_SYMBOL_GPL(public_key_verify_signature); diff --git a/crypto/asymmetric_keys/rsa.c b/crypto/asymmetric_keys/rsa.c deleted file mode 100644 index 51502bca65e7..000000000000 --- a/crypto/asymmetric_keys/rsa.c +++ /dev/null @@ -1,224 +0,0 @@ -/* RSA asymmetric public-key algorithm [RFC3447] - * - * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. - * Written by David Howells (dhowells@redhat.com) - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public Licence - * as published by the Free Software Foundation; either version - * 2 of the Licence, or (at your option) any later version. - */ - -#define pr_fmt(fmt) "RSA: "fmt -#include -#include -#include -#include -#include - -MODULE_LICENSE("GPL"); -MODULE_DESCRIPTION("RSA Public Key Algorithm"); - -#define kenter(FMT, ...) \ - pr_devel("==> %s("FMT")\n", __func__, ##__VA_ARGS__) -#define kleave(FMT, ...) \ - pr_devel("<== %s()"FMT"\n", __func__, ##__VA_ARGS__) - -/* - * Hash algorithm OIDs plus ASN.1 DER wrappings [RFC4880 sec 5.2.2]. - */ -static const u8 RSA_digest_info_MD5[] = { - 0x30, 0x20, 0x30, 0x0C, 0x06, 0x08, - 0x2A, 0x86, 0x48, 0x86, 0xF7, 0x0D, 0x02, 0x05, /* OID */ - 0x05, 0x00, 0x04, 0x10 -}; - -static const u8 RSA_digest_info_SHA1[] = { - 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, - 0x2B, 0x0E, 0x03, 0x02, 0x1A, - 0x05, 0x00, 0x04, 0x14 -}; - -static const u8 RSA_digest_info_RIPE_MD_160[] = { - 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, - 0x2B, 0x24, 0x03, 0x02, 0x01, - 0x05, 0x00, 0x04, 0x14 -}; - -static const u8 RSA_digest_info_SHA224[] = { - 0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09, - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x04, - 0x05, 0x00, 0x04, 0x1C -}; - -static const u8 RSA_digest_info_SHA256[] = { - 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, - 0x05, 0x00, 0x04, 0x20 -}; - -static const u8 RSA_digest_info_SHA384[] = { - 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, - 0x05, 0x00, 0x04, 0x30 -}; - -static const u8 RSA_digest_info_SHA512[] = { - 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, - 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, - 0x05, 0x00, 0x04, 0x40 -}; - -static const struct { - const u8 *data; - size_t size; -} RSA_ASN1_templates[PKEY_HASH__LAST] = { -#define _(X) { RSA_digest_info_##X, sizeof(RSA_digest_info_##X) } - [HASH_ALGO_MD5] = _(MD5), - [HASH_ALGO_SHA1] = _(SHA1), - [HASH_ALGO_RIPE_MD_160] = _(RIPE_MD_160), - [HASH_ALGO_SHA256] = _(SHA256), - [HASH_ALGO_SHA384] = _(SHA384), - [HASH_ALGO_SHA512] = _(SHA512), - [HASH_ALGO_SHA224] = _(SHA224), -#undef _ -}; - -struct rsa_completion { - struct completion completion; - int err; -}; - -/* - * Perform the RSA signature verification. - * @H: Value of hash of data and metadata - * @EM: The computed signature value - * @k: The size of EM (EM[0] is an invalid location but should hold 0x00) - * @hash_size: The size of H - * @asn1_template: The DigestInfo ASN.1 template - * @asn1_size: Size of asm1_template[] - */ -static int rsa_verify(const u8 *H, const u8 *EM, size_t k, size_t hash_size, - const u8 *asn1_template, size_t asn1_size) -{ - unsigned PS_end, T_offset, i; - - kenter(",,%zu,%zu,%zu", k, hash_size, asn1_size); - - if (k < 2 + 1 + asn1_size + hash_size) - return -EBADMSG; - - /* Decode the EMSA-PKCS1-v1_5 - * note: leading zeros are stripped by the RSA implementation - */ - if (EM[0] != 0x01) { - kleave(" = -EBADMSG [EM[0] == %02u]", EM[0]); - return -EBADMSG; - } - - T_offset = k - (asn1_size + hash_size); - PS_end = T_offset - 1; - if (EM[PS_end] != 0x00) { - kleave(" = -EBADMSG [EM[T-1] == %02u]", EM[PS_end]); - return -EBADMSG; - } - - for (i = 1; i < PS_end; i++) { - if (EM[i] != 0xff) { - kleave(" = -EBADMSG [EM[PS%x] == %02u]", i - 2, EM[i]); - return -EBADMSG; - } - } - - if (crypto_memneq(asn1_template, EM + T_offset, asn1_size) != 0) { - kleave(" = -EBADMSG [EM[T] ASN.1 mismatch]"); - return -EBADMSG; - } - - if (crypto_memneq(H, EM + T_offset + asn1_size, hash_size) != 0) { - kleave(" = -EKEYREJECTED [EM[T] hash mismatch]"); - return -EKEYREJECTED; - } - - kleave(" = 0"); - return 0; -} - -static void public_key_verify_done(struct crypto_async_request *req, int err) -{ - struct rsa_completion *compl = req->data; - - if (err == -EINPROGRESS) - return; - - compl->err = err; - complete(&compl->completion); -} - -int rsa_verify_signature(const struct public_key *pkey, - const struct public_key_signature *sig) -{ - struct crypto_akcipher *tfm; - struct akcipher_request *req; - struct rsa_completion compl; - struct scatterlist sig_sg, sg_out; - void *outbuf = NULL; - unsigned int outlen = 0; - int ret = -ENOMEM; - - tfm = crypto_alloc_akcipher("rsa", 0, 0); - if (IS_ERR(tfm)) - goto error_out; - - req = akcipher_request_alloc(tfm, GFP_KERNEL); - if (!req) - goto error_free_tfm; - - ret = crypto_akcipher_set_pub_key(tfm, pkey->key, pkey->keylen); - if (ret) - goto error_free_req; - - ret = -EINVAL; - outlen = crypto_akcipher_maxsize(tfm); - if (!outlen) - goto error_free_req; - - /* Initialize the output buffer */ - ret = -ENOMEM; - outbuf = kmalloc(outlen, GFP_KERNEL); - if (!outbuf) - goto error_free_req; - - sg_init_one(&sig_sg, sig->s, sig->s_size); - sg_init_one(&sg_out, outbuf, outlen); - akcipher_request_set_crypt(req, &sig_sg, &sg_out, sig->s_size, outlen); - init_completion(&compl.completion); - akcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG | - CRYPTO_TFM_REQ_MAY_SLEEP, - public_key_verify_done, &compl); - - ret = crypto_akcipher_verify(req); - if (ret == -EINPROGRESS) { - wait_for_completion(&compl.completion); - ret = compl.err; - } - - if (ret) - goto error_free_req; - - /* Output from the operation is an encoded message (EM) of - * length k octets. - */ - outlen = req->dst_len; - ret = rsa_verify(sig->digest, outbuf, outlen, sig->digest_size, - RSA_ASN1_templates[sig->pkey_hash_algo].data, - RSA_ASN1_templates[sig->pkey_hash_algo].size); -error_free_req: - akcipher_request_free(req); -error_free_tfm: - crypto_free_akcipher(tfm); -error_out: - kfree(outbuf); - return ret; -} -EXPORT_SYMBOL_GPL(rsa_verify_signature); diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h index a1693ed77be6..80ab099a3edf 100644 --- a/include/crypto/public_key.h +++ b/include/crypto/public_key.h @@ -91,6 +91,4 @@ extern struct key *x509_request_asymmetric_key(struct key *keyring, int public_key_verify_signature(const struct public_key *pkey, const struct public_key_signature *sig); -int rsa_verify_signature(const struct public_key *pkey, - const struct public_key_signature *sig); #endif /* _LINUX_PUBLIC_KEY_H */ diff --git a/init/Kconfig b/init/Kconfig index 22320804fbaf..af4de4f1b02c 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -1757,9 +1757,9 @@ config SYSTEM_DATA_VERIFICATION select SYSTEM_TRUSTED_KEYRING select KEYS select CRYPTO + select CRYPTO_RSA select ASYMMETRIC_KEY_TYPE select ASYMMETRIC_PUBLIC_KEY_SUBTYPE - select PUBLIC_KEY_ALGO_RSA select ASN1 select OID_REGISTRY select X509_CERTIFICATE_PARSER diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c index 2fa3bc681a1b..69a92e6db23d 100644 --- a/security/integrity/digsig_asymmetric.c +++ b/security/integrity/digsig_asymmetric.c @@ -103,6 +103,7 @@ int asymmetric_verify(struct key *keyring, const char *sig, memset(&pks, 0, sizeof(pks)); + pks.pkey_algo = PKEY_ALGO_RSA; pks.pkey_hash_algo = hdr->hash_algo; pks.digest = (u8 *)data; pks.digest_size = datalen; -- cgit v1.2.3 From 4e8ae72a75aae285ec5b93518b9680da198afd0d Mon Sep 17 00:00:00 2001 From: David Howells Date: Thu, 3 Mar 2016 21:49:27 +0000 Subject: X.509: Make algo identifiers text instead of enum Make the identifier public key and digest algorithm fields text instead of enum. Signed-off-by: David Howells Acked-by: Herbert Xu --- crypto/asymmetric_keys/mscode_parser.c | 14 +++++++------- crypto/asymmetric_keys/pkcs7_parser.c | 18 ++++++++---------- crypto/asymmetric_keys/pkcs7_verify.c | 8 +++----- crypto/asymmetric_keys/public_key.c | 24 ++++-------------------- crypto/asymmetric_keys/verify_pefile.c | 4 ++-- crypto/asymmetric_keys/verify_pefile.h | 2 +- crypto/asymmetric_keys/x509_cert_parser.c | 26 +++++++++++++------------- crypto/asymmetric_keys/x509_public_key.c | 17 ++++++++--------- include/crypto/public_key.h | 30 ++++-------------------------- kernel/module_signing.c | 6 ++++++ security/integrity/digsig_asymmetric.c | 7 ++++--- security/integrity/integrity.h | 2 +- 12 files changed, 61 insertions(+), 97 deletions(-) (limited to 'security') diff --git a/crypto/asymmetric_keys/mscode_parser.c b/crypto/asymmetric_keys/mscode_parser.c index adcef59eec0b..3242cbfaeaa2 100644 --- a/crypto/asymmetric_keys/mscode_parser.c +++ b/crypto/asymmetric_keys/mscode_parser.c @@ -86,25 +86,25 @@ int mscode_note_digest_algo(void *context, size_t hdrlen, oid = look_up_OID(value, vlen); switch (oid) { case OID_md4: - ctx->digest_algo = HASH_ALGO_MD4; + ctx->digest_algo = "md4"; break; case OID_md5: - ctx->digest_algo = HASH_ALGO_MD5; + ctx->digest_algo = "md5"; break; case OID_sha1: - ctx->digest_algo = HASH_ALGO_SHA1; + ctx->digest_algo = "sha1"; break; case OID_sha256: - ctx->digest_algo = HASH_ALGO_SHA256; + ctx->digest_algo = "sha256"; break; case OID_sha384: - ctx->digest_algo = HASH_ALGO_SHA384; + ctx->digest_algo = "sha384"; break; case OID_sha512: - ctx->digest_algo = HASH_ALGO_SHA512; + ctx->digest_algo = "sha512"; break; case OID_sha224: - ctx->digest_algo = HASH_ALGO_SHA224; + ctx->digest_algo = "sha224"; break; case OID__NR: diff --git a/crypto/asymmetric_keys/pkcs7_parser.c b/crypto/asymmetric_keys/pkcs7_parser.c index cbbd03fd94f8..40de03f49ff8 100644 --- a/crypto/asymmetric_keys/pkcs7_parser.c +++ b/crypto/asymmetric_keys/pkcs7_parser.c @@ -218,25 +218,25 @@ int pkcs7_sig_note_digest_algo(void *context, size_t hdrlen, switch (ctx->last_oid) { case OID_md4: - ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_MD4; + ctx->sinfo->sig.hash_algo = "md4"; break; case OID_md5: - ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_MD5; + ctx->sinfo->sig.hash_algo = "md5"; break; case OID_sha1: - ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA1; + ctx->sinfo->sig.hash_algo = "sha1"; break; case OID_sha256: - ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA256; + ctx->sinfo->sig.hash_algo = "sha256"; break; case OID_sha384: - ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA384; + ctx->sinfo->sig.hash_algo = "sha384"; break; case OID_sha512: - ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA512; + ctx->sinfo->sig.hash_algo = "sha512"; break; case OID_sha224: - ctx->sinfo->sig.pkey_hash_algo = HASH_ALGO_SHA224; + ctx->sinfo->sig.hash_algo = "sha224"; default: printk("Unsupported digest algo: %u\n", ctx->last_oid); return -ENOPKG; @@ -255,7 +255,7 @@ int pkcs7_sig_note_pkey_algo(void *context, size_t hdrlen, switch (ctx->last_oid) { case OID_rsaEncryption: - ctx->sinfo->sig.pkey_algo = PKEY_ALGO_RSA; + ctx->sinfo->sig.pkey_algo = "rsa"; break; default: printk("Unsupported pkey algo: %u\n", ctx->last_oid); @@ -615,8 +615,6 @@ int pkcs7_sig_note_signature(void *context, size_t hdrlen, { struct pkcs7_parse_context *ctx = context; - BUG_ON(ctx->sinfo->sig.pkey_algo != PKEY_ALGO_RSA); - ctx->sinfo->sig.s = kmemdup(value, vlen, GFP_KERNEL); if (!ctx->sinfo->sig.s) return -ENOMEM; diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c index f5db1378c096..50be2a15e531 100644 --- a/crypto/asymmetric_keys/pkcs7_verify.c +++ b/crypto/asymmetric_keys/pkcs7_verify.c @@ -31,17 +31,15 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7, void *digest; int ret; - kenter(",%u,%u", sinfo->index, sinfo->sig.pkey_hash_algo); + kenter(",%u,%s", sinfo->index, sinfo->sig.hash_algo); - if (sinfo->sig.pkey_hash_algo >= PKEY_HASH__LAST || - !hash_algo_name[sinfo->sig.pkey_hash_algo]) + if (!sinfo->sig.hash_algo) return -ENOPKG; /* Allocate the hashing algorithm we're going to need and find out how * big the hash operational data will be. */ - tfm = crypto_alloc_shash(hash_algo_name[sinfo->sig.pkey_hash_algo], - 0, 0); + tfm = crypto_alloc_shash(sinfo->sig.hash_algo, 0, 0); if (IS_ERR(tfm)) return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); diff --git a/crypto/asymmetric_keys/public_key.c b/crypto/asymmetric_keys/public_key.c index 27ebc2f44394..0f8b264b3961 100644 --- a/crypto/asymmetric_keys/public_key.c +++ b/crypto/asymmetric_keys/public_key.c @@ -24,19 +24,6 @@ MODULE_LICENSE("GPL"); -const char *const pkey_algo_name[PKEY_ALGO__LAST] = { - [PKEY_ALGO_DSA] = "dsa", - [PKEY_ALGO_RSA] = "rsa", -}; -EXPORT_SYMBOL_GPL(pkey_algo_name); - -const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST] = { - [PKEY_ID_PGP] = "PGP", - [PKEY_ID_X509] = "X509", - [PKEY_ID_PKCS7] = "PKCS#7", -}; -EXPORT_SYMBOL_GPL(pkey_id_type_name); - /* * Provide a part of a description of the key for /proc/keys. */ @@ -46,9 +33,7 @@ static void public_key_describe(const struct key *asymmetric_key, struct public_key *key = asymmetric_key->payload.data[asym_crypto]; if (key) - seq_printf(m, "%s.%s", - pkey_id_type_name[key->id_type], - pkey_algo_name[key->pkey_algo]); + seq_printf(m, "%s.%s", key->id_type, key->pkey_algo); } /* @@ -103,15 +88,14 @@ int public_key_verify_signature(const struct public_key *pkey, BUG_ON(!sig->digest); BUG_ON(!sig->s); - alg_name = pkey_algo_name[sig->pkey_algo]; - if (sig->pkey_algo == PKEY_ALGO_RSA) { + alg_name = sig->pkey_algo; + if (strcmp(sig->pkey_algo, "rsa") == 0) { /* The data wangled by the RSA algorithm is typically padded * and encoded in some manner, such as EMSA-PKCS1-1_5 [RFC3447 * sec 8.2]. */ if (snprintf(alg_name_buf, CRYPTO_MAX_ALG_NAME, - "pkcs1pad(rsa,%s)", - hash_algo_name[sig->pkey_hash_algo] + "pkcs1pad(rsa,%s)", sig->hash_algo ) >= CRYPTO_MAX_ALG_NAME) return -EINVAL; alg_name = alg_name_buf; diff --git a/crypto/asymmetric_keys/verify_pefile.c b/crypto/asymmetric_keys/verify_pefile.c index 897b734dabf9..7e8c2338ae25 100644 --- a/crypto/asymmetric_keys/verify_pefile.c +++ b/crypto/asymmetric_keys/verify_pefile.c @@ -328,12 +328,12 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen, void *digest; int ret; - kenter(",%u", ctx->digest_algo); + kenter(",%s", ctx->digest_algo); /* Allocate the hashing algorithm we're going to need and find out how * big the hash operational data will be. */ - tfm = crypto_alloc_shash(hash_algo_name[ctx->digest_algo], 0, 0); + tfm = crypto_alloc_shash(ctx->digest_algo, 0, 0); if (IS_ERR(tfm)) return (PTR_ERR(tfm) == -ENOENT) ? -ENOPKG : PTR_ERR(tfm); diff --git a/crypto/asymmetric_keys/verify_pefile.h b/crypto/asymmetric_keys/verify_pefile.h index 55d5f7ebc45a..a133eb81a492 100644 --- a/crypto/asymmetric_keys/verify_pefile.h +++ b/crypto/asymmetric_keys/verify_pefile.h @@ -28,7 +28,7 @@ struct pefile_context { /* PKCS#7 MS Individual Code Signing content */ const void *digest; /* Digest */ unsigned digest_len; /* Digest length */ - enum hash_algo digest_algo; /* Digest algorithm */ + const char *digest_algo; /* Digest algorithm */ }; #define kenter(FMT, ...) \ diff --git a/crypto/asymmetric_keys/x509_cert_parser.c b/crypto/asymmetric_keys/x509_cert_parser.c index c02c200a7136..4a29bac70060 100644 --- a/crypto/asymmetric_keys/x509_cert_parser.c +++ b/crypto/asymmetric_keys/x509_cert_parser.c @@ -188,33 +188,33 @@ int x509_note_pkey_algo(void *context, size_t hdrlen, return -ENOPKG; /* Unsupported combination */ case OID_md4WithRSAEncryption: - ctx->cert->sig.pkey_hash_algo = HASH_ALGO_MD5; - ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; + ctx->cert->sig.hash_algo = "md4"; + ctx->cert->sig.pkey_algo = "rsa"; break; case OID_sha1WithRSAEncryption: - ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA1; - ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; + ctx->cert->sig.hash_algo = "sha1"; + ctx->cert->sig.pkey_algo = "rsa"; break; case OID_sha256WithRSAEncryption: - ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA256; - ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; + ctx->cert->sig.hash_algo = "sha256"; + ctx->cert->sig.pkey_algo = "rsa"; break; case OID_sha384WithRSAEncryption: - ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA384; - ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; + ctx->cert->sig.hash_algo = "sha384"; + ctx->cert->sig.pkey_algo = "rsa"; break; case OID_sha512WithRSAEncryption: - ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA512; - ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; + ctx->cert->sig.hash_algo = "sha512"; + ctx->cert->sig.pkey_algo = "rsa"; break; case OID_sha224WithRSAEncryption: - ctx->cert->sig.pkey_hash_algo = HASH_ALGO_SHA224; - ctx->cert->sig.pkey_algo = PKEY_ALGO_RSA; + ctx->cert->sig.hash_algo = "sha224"; + ctx->cert->sig.pkey_algo = "rsa"; break; } @@ -396,7 +396,7 @@ int x509_extract_key_data(void *context, size_t hdrlen, if (ctx->last_oid != OID_rsaEncryption) return -ENOPKG; - ctx->cert->pub->pkey_algo = PKEY_ALGO_RSA; + ctx->cert->pub->pkey_algo = "rsa"; /* Discard the BIT STRING metadata */ ctx->key = value + 1; diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c index 7092d5cbb5d3..733c046aacc6 100644 --- a/crypto/asymmetric_keys/x509_public_key.c +++ b/crypto/asymmetric_keys/x509_public_key.c @@ -176,7 +176,7 @@ int x509_get_sig_params(struct x509_certificate *cert) /* Allocate the hashing algorithm we're going to need and find out how * big the hash operational data will be. */ - tfm = crypto_alloc_shash(hash_algo_name[cert->sig.pkey_hash_algo], 0, 0); + tfm = crypto_alloc_shash(cert->sig.hash_algo, 0, 0); if (IS_ERR(tfm)) { if (PTR_ERR(tfm) == -ENOENT) { cert->unsupported_crypto = true; @@ -291,21 +291,20 @@ static int x509_key_preparse(struct key_preparsed_payload *prep) pr_devel("Cert Issuer: %s\n", cert->issuer); pr_devel("Cert Subject: %s\n", cert->subject); - if (cert->pub->pkey_algo >= PKEY_ALGO__LAST || - cert->sig.pkey_algo >= PKEY_ALGO__LAST || - cert->sig.pkey_hash_algo >= PKEY_HASH__LAST || - !hash_algo_name[cert->sig.pkey_hash_algo]) { + if (!cert->pub->pkey_algo || + !cert->sig.pkey_algo || + !cert->sig.hash_algo) { ret = -ENOPKG; goto error_free_cert; } - pr_devel("Cert Key Algo: %s\n", pkey_algo_name[cert->pub->pkey_algo]); + pr_devel("Cert Key Algo: %s\n", cert->pub->pkey_algo); pr_devel("Cert Valid period: %lld-%lld\n", cert->valid_from, cert->valid_to); pr_devel("Cert Signature: %s + %s\n", - pkey_algo_name[cert->sig.pkey_algo], - hash_algo_name[cert->sig.pkey_hash_algo]); + cert->sig.pkey_algo, + cert->sig.hash_algo); - cert->pub->id_type = PKEY_ID_X509; + cert->pub->id_type = "X509"; /* Check the signature on the key if it appears to be self-signed */ if ((!cert->akid_skid && !cert->akid_id) || diff --git a/include/crypto/public_key.h b/include/crypto/public_key.h index 80ab099a3edf..aa730ea7faf8 100644 --- a/include/crypto/public_key.h +++ b/include/crypto/public_key.h @@ -14,28 +14,6 @@ #ifndef _LINUX_PUBLIC_KEY_H #define _LINUX_PUBLIC_KEY_H -#include - -enum pkey_algo { - PKEY_ALGO_DSA, - PKEY_ALGO_RSA, - PKEY_ALGO__LAST -}; - -extern const char *const pkey_algo_name[PKEY_ALGO__LAST]; - -/* asymmetric key implementation supports only up to SHA224 */ -#define PKEY_HASH__LAST (HASH_ALGO_SHA224 + 1) - -enum pkey_id_type { - PKEY_ID_PGP, /* OpenPGP generated key ID */ - PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */ - PKEY_ID_PKCS7, /* Signature in PKCS#7 message */ - PKEY_ID_TYPE__LAST -}; - -extern const char *const pkey_id_type_name[PKEY_ID_TYPE__LAST]; - /* * The use to which an asymmetric key is being put. */ @@ -59,8 +37,8 @@ extern const char *const key_being_used_for[NR__KEY_BEING_USED_FOR]; struct public_key { void *key; u32 keylen; - enum pkey_algo pkey_algo : 8; - enum pkey_id_type id_type : 8; + const char *id_type; + const char *pkey_algo; }; extern void public_key_destroy(void *payload); @@ -73,8 +51,8 @@ struct public_key_signature { u32 s_size; /* Number of bytes in signature */ u8 *digest; u8 digest_size; /* Number of bytes in digest */ - enum pkey_algo pkey_algo : 8; - enum hash_algo pkey_hash_algo : 8; + const char *pkey_algo; + const char *hash_algo; }; extern struct asymmetric_key_subtype public_key_subtype; diff --git a/kernel/module_signing.c b/kernel/module_signing.c index 9cfa46d8d14f..64b9dead4a07 100644 --- a/kernel/module_signing.c +++ b/kernel/module_signing.c @@ -16,6 +16,12 @@ #include #include "module-internal.h" +enum pkey_id_type { + PKEY_ID_PGP, /* OpenPGP generated key ID */ + PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */ + PKEY_ID_PKCS7, /* Signature in PKCS#7 message */ +}; + /* * Module signature information block. * diff --git a/security/integrity/digsig_asymmetric.c b/security/integrity/digsig_asymmetric.c index 69a92e6db23d..80052ed8d467 100644 --- a/security/integrity/digsig_asymmetric.c +++ b/security/integrity/digsig_asymmetric.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -94,7 +95,7 @@ int asymmetric_verify(struct key *keyring, const char *sig, if (siglen != __be16_to_cpu(hdr->sig_size)) return -EBADMSG; - if (hdr->hash_algo >= PKEY_HASH__LAST) + if (hdr->hash_algo >= HASH_ALGO__LAST) return -ENOPKG; key = request_asymmetric_key(keyring, __be32_to_cpu(hdr->keyid)); @@ -103,8 +104,8 @@ int asymmetric_verify(struct key *keyring, const char *sig, memset(&pks, 0, sizeof(pks)); - pks.pkey_algo = PKEY_ALGO_RSA; - pks.pkey_hash_algo = hdr->hash_algo; + pks.pkey_algo = "rsa"; + pks.hash_algo = hash_algo_name[hdr->hash_algo]; pks.digest = (u8 *)data; pks.digest_size = datalen; pks.s = hdr->sig; diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h index 5efe2ecc538d..c7708d9a1b41 100644 --- a/security/integrity/integrity.h +++ b/security/integrity/integrity.h @@ -94,7 +94,7 @@ struct ima_digest_data { struct signature_v2_hdr { uint8_t type; /* xattr type */ uint8_t version; /* signature format version */ - uint8_t hash_algo; /* Digest algorithm [enum pkey_hash_algo] */ + uint8_t hash_algo; /* Digest algorithm [enum hash_algo] */ uint32_t keyid; /* IMA key identifier - not X509/PGP specific */ uint16_t sig_size; /* signature size */ uint8_t sig[0]; /* signature payload */ -- cgit v1.2.3