Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity

Pull integrity updates from Mimi Zohar:
"The major feature in this time is IMA support for measuring and
appraising appended file signatures. In addition are a couple of bug
fixes and code cleanup to use struct_size().

In addition to the PE/COFF and IMA xattr signatures, the kexec kernel
image may be signed with an appended signature, using the same
scripts/sign-file tool that is used to sign kernel modules.

Similarly, the initramfs may contain an appended signature.

This contained a lot of refactoring of the existing appended signature
verification code, so that IMA could retain the existing framework of
calculating the file hash once, storing it in the IMA measurement list
and extending the TPM, verifying the file's integrity based on a file
hash or signature (eg. xattrs), and adding an audit record containing
the file hash, all based on policy. (The IMA support for appended
signatures patch set was posted and reviewed 11 times.)

The support for appended signature paves the way for adding other
signature verification methods, such as fs-verity, based on a single
system-wide policy. The file hash used for verifying the signature and
the signature, itself, can be included in the IMA measurement list"

* 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity:
ima: ima_api: Use struct_size() in kzalloc()
ima: use struct_size() in kzalloc()
sefltest/ima: support appended signatures (modsig)
ima: Fix use after free in ima_read_modsig()
MODSIGN: make new include file self contained
ima: fix freeing ongoing ahash_request
ima: always return negative code for error
ima: Store the measurement again when appraising a modsig
ima: Define ima-modsig template
ima: Collect modsig
ima: Implement support for module-style appended signatures
ima: Factor xattr_verify() out of ima_appraise_measurement()
ima: Add modsig appraise_type option for module-style appended signatures
integrity: Select CONFIG_KEYS instead of depending on it
PKCS#7: Introduce pkcs7_get_digest()
PKCS#7: Refactor verify_pkcs7_signature()
MODSIGN: Export module signature definitions
ima: initialize the "template" field with the default template

+871 -203
+5 -1
Documentation/ABI/testing/ima_policy
··· 37 37 euid:= decimal value 38 38 fowner:= decimal value 39 39 lsm: are LSM specific 40 - option: appraise_type:= [imasig] 40 + option: appraise_type:= [imasig] [imasig|modsig] 41 41 template:= name of a defined IMA template type 42 42 (eg, ima-ng). Only valid when action is "measure". 43 43 pcr:= decimal value ··· 105 105 106 106 measure func=KEXEC_KERNEL_CHECK pcr=4 107 107 measure func=KEXEC_INITRAMFS_CHECK pcr=5 108 + 109 + Example of appraise rule allowing modsig appended signatures: 110 + 111 + appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig|modsig
+3
Documentation/security/IMA-templates.rst
··· 68 68 - 'd-ng': the digest of the event, calculated with an arbitrary hash 69 69 algorithm (field format: [<hash algo>:]digest, where the digest 70 70 prefix is shown only if the hash algorithm is not SHA1 or MD5); 71 + - 'd-modsig': the digest of the event without the appended modsig; 71 72 - 'n-ng': the name of the event, without size limitations; 72 73 - 'sig': the file signature; 74 + - 'modsig' the appended file signature; 73 75 - 'buf': the buffer data that was used to generate the hash without size limitations; 74 76 75 77 ··· 81 79 - "ima-ng" (default): its format is ``d-ng|n-ng``; 82 80 - "ima-sig": its format is ``d-ng|n-ng|sig``; 83 81 - "ima-buf": its format is ``d-ng|n-ng|buf``; 82 + - "ima-modsig": its format is ``d-ng|n-ng|sig|d-modsig|modsig``; 84 83 85 84 86 85 Use
+1 -1
arch/s390/Kconfig
··· 556 556 557 557 config KEXEC_VERIFY_SIG 558 558 bool "Verify kernel signature during kexec_file_load() syscall" 559 - depends on KEXEC_FILE && SYSTEM_DATA_VERIFICATION 559 + depends on KEXEC_FILE && MODULE_SIG_FORMAT 560 560 help 561 561 This option makes kernel signature verification mandatory for 562 562 the kexec_file_load() syscall.
+1 -23
arch/s390/kernel/machine_kexec_file.c
··· 10 10 #include <linux/elf.h> 11 11 #include <linux/errno.h> 12 12 #include <linux/kexec.h> 13 - #include <linux/module.h> 13 + #include <linux/module_signature.h> 14 14 #include <linux/verification.h> 15 15 #include <asm/boot_data.h> 16 16 #include <asm/ipl.h> ··· 23 23 }; 24 24 25 25 #ifdef CONFIG_KEXEC_VERIFY_SIG 26 - /* 27 - * Module signature information block. 28 - * 29 - * The constituents of the signature section are, in order: 30 - * 31 - * - Signer's name 32 - * - Key identifier 33 - * - Signature data 34 - * - Information block 35 - */ 36 - struct module_signature { 37 - u8 algo; /* Public-key crypto algorithm [0] */ 38 - u8 hash; /* Digest algorithm [0] */ 39 - u8 id_type; /* Key identifier type [PKEY_ID_PKCS7] */ 40 - u8 signer_len; /* Length of signer's name [0] */ 41 - u8 key_id_len; /* Length of key identifier [0] */ 42 - u8 __pad[3]; 43 - __be32 sig_len; /* Length of signature data */ 44 - }; 45 - 46 - #define PKEY_ID_PKCS7 2 47 - 48 26 int s390_verify_sig(const char *kernel, unsigned long kernel_len) 49 27 { 50 28 const unsigned long marker_len = sizeof(MODULE_SIG_STRING) - 1;
+45 -16
certs/system_keyring.c
··· 190 190 #ifdef CONFIG_SYSTEM_DATA_VERIFICATION 191 191 192 192 /** 193 - * verify_pkcs7_signature - Verify a PKCS#7-based signature on system data. 193 + * verify_pkcs7_message_sig - Verify a PKCS#7-based signature on system data. 194 194 * @data: The data to be verified (NULL if expecting internal data). 195 195 * @len: Size of @data. 196 - * @raw_pkcs7: The PKCS#7 message that is the signature. 197 - * @pkcs7_len: The size of @raw_pkcs7. 196 + * @pkcs7: The PKCS#7 message that is the signature. 198 197 * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only, 199 198 * (void *)1UL for all trusted keys). 200 199 * @usage: The use to which the key is being put. 201 200 * @view_content: Callback to gain access to content. 202 201 * @ctx: Context for callback. 203 202 */ 204 - int verify_pkcs7_signature(const void *data, size_t len, 205 - const void *raw_pkcs7, size_t pkcs7_len, 206 - struct key *trusted_keys, 207 - enum key_being_used_for usage, 208 - int (*view_content)(void *ctx, 209 - const void *data, size_t len, 210 - size_t asn1hdrlen), 211 - void *ctx) 203 + int verify_pkcs7_message_sig(const void *data, size_t len, 204 + struct pkcs7_message *pkcs7, 205 + struct key *trusted_keys, 206 + enum key_being_used_for usage, 207 + int (*view_content)(void *ctx, 208 + const void *data, size_t len, 209 + size_t asn1hdrlen), 210 + void *ctx) 212 211 { 213 - struct pkcs7_message *pkcs7; 214 212 int ret; 215 - 216 - pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len); 217 - if (IS_ERR(pkcs7)) 218 - return PTR_ERR(pkcs7); 219 213 220 214 /* The data should be detached - so we need to supply it. */ 221 215 if (data && pkcs7_supply_detached_data(pkcs7, data, len) < 0) { ··· 263 269 } 264 270 265 271 error: 272 + pr_devel("<==%s() = %d\n", __func__, ret); 273 + return ret; 274 + } 275 + 276 + /** 277 + * verify_pkcs7_signature - Verify a PKCS#7-based signature on system data. 278 + * @data: The data to be verified (NULL if expecting internal data). 279 + * @len: Size of @data. 280 + * @raw_pkcs7: The PKCS#7 message that is the signature. 281 + * @pkcs7_len: The size of @raw_pkcs7. 282 + * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only, 283 + * (void *)1UL for all trusted keys). 284 + * @usage: The use to which the key is being put. 285 + * @view_content: Callback to gain access to content. 286 + * @ctx: Context for callback. 287 + */ 288 + int verify_pkcs7_signature(const void *data, size_t len, 289 + const void *raw_pkcs7, size_t pkcs7_len, 290 + struct key *trusted_keys, 291 + enum key_being_used_for usage, 292 + int (*view_content)(void *ctx, 293 + const void *data, size_t len, 294 + size_t asn1hdrlen), 295 + void *ctx) 296 + { 297 + struct pkcs7_message *pkcs7; 298 + int ret; 299 + 300 + pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len); 301 + if (IS_ERR(pkcs7)) 302 + return PTR_ERR(pkcs7); 303 + 304 + ret = verify_pkcs7_message_sig(data, len, pkcs7, trusted_keys, usage, 305 + view_content, ctx); 306 + 266 307 pkcs7_free_message(pkcs7); 267 308 pr_devel("<==%s() = %d\n", __func__, ret); 268 309 return ret;
+33
crypto/asymmetric_keys/pkcs7_verify.c
··· 12 12 #include <linux/err.h> 13 13 #include <linux/asn1.h> 14 14 #include <crypto/hash.h> 15 + #include <crypto/hash_info.h> 15 16 #include <crypto/public_key.h> 16 17 #include "pkcs7_parser.h" 17 18 ··· 29 28 int ret; 30 29 31 30 kenter(",%u,%s", sinfo->index, sinfo->sig->hash_algo); 31 + 32 + /* The digest was calculated already. */ 33 + if (sig->digest) 34 + return 0; 32 35 33 36 if (!sinfo->sig->hash_algo) 34 37 return -ENOPKG; ··· 120 115 crypto_free_shash(tfm); 121 116 kleave(" = %d", ret); 122 117 return ret; 118 + } 119 + 120 + int pkcs7_get_digest(struct pkcs7_message *pkcs7, const u8 **buf, u32 *len, 121 + enum hash_algo *hash_algo) 122 + { 123 + struct pkcs7_signed_info *sinfo = pkcs7->signed_infos; 124 + int i, ret; 125 + 126 + /* 127 + * This function doesn't support messages with more than one signature. 128 + */ 129 + if (sinfo == NULL || sinfo->next != NULL) 130 + return -EBADMSG; 131 + 132 + ret = pkcs7_digest(pkcs7, sinfo); 133 + if (ret) 134 + return ret; 135 + 136 + *buf = sinfo->sig->digest; 137 + *len = sinfo->sig->digest_size; 138 + 139 + for (i = 0; i < HASH_ALGO__LAST; i++) 140 + if (!strcmp(hash_algo_name[i], sinfo->sig->hash_algo)) { 141 + *hash_algo = i; 142 + break; 143 + } 144 + 145 + return 0; 123 146 } 124 147 125 148 /*
+4
include/crypto/pkcs7.h
··· 9 9 #define _CRYPTO_PKCS7_H 10 10 11 11 #include <linux/verification.h> 12 + #include <linux/hash_info.h> 12 13 #include <crypto/public_key.h> 13 14 14 15 struct key; ··· 40 39 41 40 extern int pkcs7_supply_detached_data(struct pkcs7_message *pkcs7, 42 41 const void *data, size_t datalen); 42 + 43 + extern int pkcs7_get_digest(struct pkcs7_message *pkcs7, const u8 **buf, 44 + u32 *len, enum hash_algo *hash_algo); 43 45 44 46 #endif /* _CRYPTO_PKCS7_H */
-3
include/linux/module.h
··· 26 26 #include <linux/percpu.h> 27 27 #include <asm/module.h> 28 28 29 - /* In stripped ARM and x86-64 modules, ~ is surprisingly rare. */ 30 - #define MODULE_SIG_STRING "~Module signature appended~\n" 31 - 32 29 /* Not Yet Implemented */ 33 30 #define MODULE_SUPPORTED_DEVICE(name) 34 31
+46
include/linux/module_signature.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0+ */ 2 + /* 3 + * Module signature handling. 4 + * 5 + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 6 + * Written by David Howells (dhowells@redhat.com) 7 + */ 8 + 9 + #ifndef _LINUX_MODULE_SIGNATURE_H 10 + #define _LINUX_MODULE_SIGNATURE_H 11 + 12 + #include <linux/types.h> 13 + 14 + /* In stripped ARM and x86-64 modules, ~ is surprisingly rare. */ 15 + #define MODULE_SIG_STRING "~Module signature appended~\n" 16 + 17 + enum pkey_id_type { 18 + PKEY_ID_PGP, /* OpenPGP generated key ID */ 19 + PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */ 20 + PKEY_ID_PKCS7, /* Signature in PKCS#7 message */ 21 + }; 22 + 23 + /* 24 + * Module signature information block. 25 + * 26 + * The constituents of the signature section are, in order: 27 + * 28 + * - Signer's name 29 + * - Key identifier 30 + * - Signature data 31 + * - Information block 32 + */ 33 + struct module_signature { 34 + u8 algo; /* Public-key crypto algorithm [0] */ 35 + u8 hash; /* Digest algorithm [0] */ 36 + u8 id_type; /* Key identifier type [PKEY_ID_PKCS7] */ 37 + u8 signer_len; /* Length of signer's name [0] */ 38 + u8 key_id_len; /* Length of key identifier [0] */ 39 + u8 __pad[3]; 40 + __be32 sig_len; /* Length of signature data */ 41 + }; 42 + 43 + int mod_check_sig(const struct module_signature *ms, size_t file_len, 44 + const char *name); 45 + 46 + #endif /* _LINUX_MODULE_SIGNATURE_H */
+10
include/linux/verification.h
··· 32 32 #ifdef CONFIG_SYSTEM_DATA_VERIFICATION 33 33 34 34 struct key; 35 + struct pkcs7_message; 35 36 36 37 extern int verify_pkcs7_signature(const void *data, size_t len, 37 38 const void *raw_pkcs7, size_t pkcs7_len, ··· 42 41 const void *data, size_t len, 43 42 size_t asn1hdrlen), 44 43 void *ctx); 44 + extern int verify_pkcs7_message_sig(const void *data, size_t len, 45 + struct pkcs7_message *pkcs7, 46 + struct key *trusted_keys, 47 + enum key_being_used_for usage, 48 + int (*view_content)(void *ctx, 49 + const void *data, 50 + size_t len, 51 + size_t asn1hdrlen), 52 + void *ctx); 45 53 46 54 #ifdef CONFIG_SIGNED_PE_FILE_VERIFICATION 47 55 extern int verify_pefile_signature(const void *pebuf, unsigned pelen,
+5 -1
init/Kconfig
··· 1963 1963 default 0 if BASE_FULL 1964 1964 default 1 if !BASE_FULL 1965 1965 1966 + config MODULE_SIG_FORMAT 1967 + def_bool n 1968 + select SYSTEM_DATA_VERIFICATION 1969 + 1966 1970 menuconfig MODULES 1967 1971 bool "Enable loadable module support" 1968 1972 option modules ··· 2051 2047 2052 2048 config MODULE_SIG 2053 2049 bool "Module signature verification" 2054 - select SYSTEM_DATA_VERIFICATION 2050 + select MODULE_SIG_FORMAT 2055 2051 help 2056 2052 Check modules for valid signatures upon load: the signature 2057 2053 is simply appended to the module. For more information see
+1
kernel/Makefile
··· 58 58 obj-$(CONFIG_UID16) += uid16.o 59 59 obj-$(CONFIG_MODULES) += module.o 60 60 obj-$(CONFIG_MODULE_SIG) += module_signing.o 61 + obj-$(CONFIG_MODULE_SIG_FORMAT) += module_signature.o 61 62 obj-$(CONFIG_KALLSYMS) += kallsyms.o 62 63 obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o 63 64 obj-$(CONFIG_CRASH_CORE) += crash_core.o
+1
kernel/module.c
··· 7 7 #include <linux/export.h> 8 8 #include <linux/extable.h> 9 9 #include <linux/moduleloader.h> 10 + #include <linux/module_signature.h> 10 11 #include <linux/trace_events.h> 11 12 #include <linux/init.h> 12 13 #include <linux/kallsyms.h>
+46
kernel/module_signature.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * Module signature checker 4 + * 5 + * Copyright (C) 2012 Red Hat, Inc. All Rights Reserved. 6 + * Written by David Howells (dhowells@redhat.com) 7 + */ 8 + 9 + #include <linux/errno.h> 10 + #include <linux/printk.h> 11 + #include <linux/module_signature.h> 12 + #include <asm/byteorder.h> 13 + 14 + /** 15 + * mod_check_sig - check that the given signature is sane 16 + * 17 + * @ms: Signature to check. 18 + * @file_len: Size of the file to which @ms is appended. 19 + * @name: What is being checked. Used for error messages. 20 + */ 21 + int mod_check_sig(const struct module_signature *ms, size_t file_len, 22 + const char *name) 23 + { 24 + if (be32_to_cpu(ms->sig_len) >= file_len - sizeof(*ms)) 25 + return -EBADMSG; 26 + 27 + if (ms->id_type != PKEY_ID_PKCS7) { 28 + pr_err("%s: Module is not signed with expected PKCS#7 message\n", 29 + name); 30 + return -ENOPKG; 31 + } 32 + 33 + if (ms->algo != 0 || 34 + ms->hash != 0 || 35 + ms->signer_len != 0 || 36 + ms->key_id_len != 0 || 37 + ms->__pad[0] != 0 || 38 + ms->__pad[1] != 0 || 39 + ms->__pad[2] != 0) { 40 + pr_err("%s: PKCS#7 signature info has unexpected non-zero params\n", 41 + name); 42 + return -EBADMSG; 43 + } 44 + 45 + return 0; 46 + }
+8 -48
kernel/module_signing.c
··· 7 7 8 8 #include <linux/kernel.h> 9 9 #include <linux/errno.h> 10 + #include <linux/module.h> 11 + #include <linux/module_signature.h> 10 12 #include <linux/string.h> 11 13 #include <linux/verification.h> 12 14 #include <crypto/public_key.h> 13 15 #include "module-internal.h" 14 - 15 - enum pkey_id_type { 16 - PKEY_ID_PGP, /* OpenPGP generated key ID */ 17 - PKEY_ID_X509, /* X.509 arbitrary subjectKeyIdentifier */ 18 - PKEY_ID_PKCS7, /* Signature in PKCS#7 message */ 19 - }; 20 - 21 - /* 22 - * Module signature information block. 23 - * 24 - * The constituents of the signature section are, in order: 25 - * 26 - * - Signer's name 27 - * - Key identifier 28 - * - Signature data 29 - * - Information block 30 - */ 31 - struct module_signature { 32 - u8 algo; /* Public-key crypto algorithm [0] */ 33 - u8 hash; /* Digest algorithm [0] */ 34 - u8 id_type; /* Key identifier type [PKEY_ID_PKCS7] */ 35 - u8 signer_len; /* Length of signer's name [0] */ 36 - u8 key_id_len; /* Length of key identifier [0] */ 37 - u8 __pad[3]; 38 - __be32 sig_len; /* Length of signature data */ 39 - }; 40 16 41 17 /* 42 18 * Verify the signature on a module. ··· 21 45 { 22 46 struct module_signature ms; 23 47 size_t sig_len, modlen = info->len; 48 + int ret; 24 49 25 50 pr_devel("==>%s(,%zu)\n", __func__, modlen); 26 51 ··· 29 52 return -EBADMSG; 30 53 31 54 memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms)); 32 - modlen -= sizeof(ms); 55 + 56 + ret = mod_check_sig(&ms, modlen, info->name); 57 + if (ret) 58 + return ret; 33 59 34 60 sig_len = be32_to_cpu(ms.sig_len); 35 - if (sig_len >= modlen) 36 - return -EBADMSG; 37 - modlen -= sig_len; 61 + modlen -= sig_len + sizeof(ms); 38 62 info->len = modlen; 39 - 40 - if (ms.id_type != PKEY_ID_PKCS7) { 41 - pr_err("%s: Module is not signed with expected PKCS#7 message\n", 42 - info->name); 43 - return -ENOPKG; 44 - } 45 - 46 - if (ms.algo != 0 || 47 - ms.hash != 0 || 48 - ms.signer_len != 0 || 49 - ms.key_id_len != 0 || 50 - ms.__pad[0] != 0 || 51 - ms.__pad[1] != 0 || 52 - ms.__pad[2] != 0) { 53 - pr_err("%s: PKCS#7 signature info has unexpected non-zero params\n", 54 - info->name); 55 - return -EBADMSG; 56 - } 57 63 58 64 return verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len, 59 65 VERIFY_USE_SECONDARY_KEYRING,
+1 -1
scripts/Makefile
··· 17 17 hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount 18 18 hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable 19 19 hostprogs-$(CONFIG_ASN1) += asn1_compiler 20 - hostprogs-$(CONFIG_MODULE_SIG) += sign-file 20 + hostprogs-$(CONFIG_MODULE_SIG_FORMAT) += sign-file 21 21 hostprogs-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert 22 22 hostprogs-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert 23 23
+1 -1
security/integrity/Kconfig
··· 18 18 19 19 config INTEGRITY_SIGNATURE 20 20 bool "Digital signature verification using multiple keyrings" 21 - depends on KEYS 22 21 default n 22 + select KEYS 23 23 select SIGNATURE 24 24 help 25 25 This option enables digital signature verification support
+34 -9
security/integrity/digsig.c
··· 39 39 #define restrict_link_to_ima restrict_link_by_builtin_trusted 40 40 #endif 41 41 42 - int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, 43 - const char *digest, int digestlen) 42 + static struct key *integrity_keyring_from_id(const unsigned int id) 44 43 { 45 - if (id >= INTEGRITY_KEYRING_MAX || siglen < 2) 46 - return -EINVAL; 44 + if (id >= INTEGRITY_KEYRING_MAX) 45 + return ERR_PTR(-EINVAL); 47 46 48 47 if (!keyring[id]) { 49 48 keyring[id] = ··· 51 52 int err = PTR_ERR(keyring[id]); 52 53 pr_err("no %s keyring: %d\n", keyring_name[id], err); 53 54 keyring[id] = NULL; 54 - return err; 55 + return ERR_PTR(err); 55 56 } 56 57 } 58 + 59 + return keyring[id]; 60 + } 61 + 62 + int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, 63 + const char *digest, int digestlen) 64 + { 65 + struct key *keyring; 66 + 67 + if (siglen < 2) 68 + return -EINVAL; 69 + 70 + keyring = integrity_keyring_from_id(id); 71 + if (IS_ERR(keyring)) 72 + return PTR_ERR(keyring); 57 73 58 74 switch (sig[1]) { 59 75 case 1: 60 76 /* v1 API expect signature without xattr type */ 61 - return digsig_verify(keyring[id], sig + 1, siglen - 1, 62 - digest, digestlen); 77 + return digsig_verify(keyring, sig + 1, siglen - 1, digest, 78 + digestlen); 63 79 case 2: 64 - return asymmetric_verify(keyring[id], sig, siglen, 65 - digest, digestlen); 80 + return asymmetric_verify(keyring, sig, siglen, digest, 81 + digestlen); 66 82 } 67 83 68 84 return -EOPNOTSUPP; 85 + } 86 + 87 + int integrity_modsig_verify(const unsigned int id, const struct modsig *modsig) 88 + { 89 + struct key *keyring; 90 + 91 + keyring = integrity_keyring_from_id(id); 92 + if (IS_ERR(keyring)) 93 + return PTR_ERR(keyring); 94 + 95 + return ima_modsig_verify(keyring, modsig); 69 96 } 70 97 71 98 static int __init __integrity_init_keyring(const unsigned int id,
+13
security/integrity/ima/Kconfig
··· 233 233 This option enables the different "ima_appraise=" modes 234 234 (eg. fix, log) from the boot command line. 235 235 236 + config IMA_APPRAISE_MODSIG 237 + bool "Support module-style signatures for appraisal" 238 + depends on IMA_APPRAISE 239 + depends on INTEGRITY_ASYMMETRIC_KEYS 240 + select PKCS7_MESSAGE_PARSER 241 + select MODULE_SIG_FORMAT 242 + default n 243 + help 244 + Adds support for signatures appended to files. The format of the 245 + appended signature is the same used for signed kernel modules. 246 + The modsig keyword can be used in the IMA policy to allow a hook 247 + to accept such signatures. 248 + 236 249 config IMA_TRUSTED_KEYRING 237 250 bool "Require all keys on the .ima keyring be signed (deprecated)" 238 251 depends on IMA_APPRAISE && SYSTEM_TRUSTED_KEYRING
+1
security/integrity/ima/Makefile
··· 9 9 ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \ 10 10 ima_policy.o ima_template.o ima_template_lib.o 11 11 ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o 12 + ima-$(CONFIG_IMA_APPRAISE_MODSIG) += ima_modsig.o 12 13 ima-$(CONFIG_HAVE_IMA_KEXEC) += ima_kexec.o 13 14 obj-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o
+56 -4
security/integrity/ima/ima.h
··· 60 60 const unsigned char *filename; 61 61 struct evm_ima_xattr_data *xattr_value; 62 62 int xattr_len; 63 + const struct modsig *modsig; 63 64 const char *violation; 64 65 const void *buf; 65 66 int buf_len; ··· 150 149 int *num_fields); 151 150 struct ima_template_desc *ima_template_desc_current(void); 152 151 struct ima_template_desc *lookup_template_desc(const char *name); 152 + bool ima_template_has_modsig(const struct ima_template_desc *ima_template); 153 153 int ima_restore_measurement_entry(struct ima_template_entry *entry); 154 154 int ima_restore_measurement_list(loff_t bufsize, void *buf); 155 155 int ima_measurements_show(struct seq_file *m, void *v); ··· 198 196 __ima_hooks(__ima_hook_enumify) 199 197 }; 200 198 199 + extern const char *const func_tokens[]; 200 + 201 + struct modsig; 202 + 201 203 /* LIM API function definitions */ 202 204 int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid, 203 205 int mask, enum ima_hooks func, int *pcr, ··· 209 203 int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func); 210 204 int ima_collect_measurement(struct integrity_iint_cache *iint, 211 205 struct file *file, void *buf, loff_t size, 212 - enum hash_algo algo); 206 + enum hash_algo algo, struct modsig *modsig); 213 207 void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file, 214 208 const unsigned char *filename, 215 209 struct evm_ima_xattr_data *xattr_value, 216 - int xattr_len, int pcr, 210 + int xattr_len, const struct modsig *modsig, int pcr, 217 211 struct ima_template_desc *template_desc); 218 212 void ima_audit_measurement(struct integrity_iint_cache *iint, 219 213 const unsigned char *filename); ··· 255 249 struct integrity_iint_cache *iint, 256 250 struct file *file, const unsigned char *filename, 257 251 struct evm_ima_xattr_data *xattr_value, 258 - int xattr_len); 252 + int xattr_len, const struct modsig *modsig); 259 253 int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func); 260 254 void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file); 261 255 enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, ··· 271 265 struct file *file, 272 266 const unsigned char *filename, 273 267 struct evm_ima_xattr_data *xattr_value, 274 - int xattr_len) 268 + int xattr_len, 269 + const struct modsig *modsig) 275 270 { 276 271 return INTEGRITY_UNKNOWN; 277 272 } ··· 308 301 } 309 302 310 303 #endif /* CONFIG_IMA_APPRAISE */ 304 + 305 + #ifdef CONFIG_IMA_APPRAISE_MODSIG 306 + bool ima_hook_supports_modsig(enum ima_hooks func); 307 + int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len, 308 + struct modsig **modsig); 309 + void ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size); 310 + int ima_get_modsig_digest(const struct modsig *modsig, enum hash_algo *algo, 311 + const u8 **digest, u32 *digest_size); 312 + int ima_get_raw_modsig(const struct modsig *modsig, const void **data, 313 + u32 *data_len); 314 + void ima_free_modsig(struct modsig *modsig); 315 + #else 316 + static inline bool ima_hook_supports_modsig(enum ima_hooks func) 317 + { 318 + return false; 319 + } 320 + 321 + static inline int ima_read_modsig(enum ima_hooks func, const void *buf, 322 + loff_t buf_len, struct modsig **modsig) 323 + { 324 + return -EOPNOTSUPP; 325 + } 326 + 327 + static inline void ima_collect_modsig(struct modsig *modsig, const void *buf, 328 + loff_t size) 329 + { 330 + } 331 + 332 + static inline int ima_get_modsig_digest(const struct modsig *modsig, 333 + enum hash_algo *algo, const u8 **digest, 334 + u32 *digest_size) 335 + { 336 + return -EOPNOTSUPP; 337 + } 338 + 339 + static inline int ima_get_raw_modsig(const struct modsig *modsig, 340 + const void **data, u32 *data_len) 341 + { 342 + return -EOPNOTSUPP; 343 + } 344 + 345 + static inline void ima_free_modsig(struct modsig *modsig) 346 + { 347 + } 348 + #endif /* CONFIG_IMA_APPRAISE_MODSIG */ 311 349 312 350 /* LSM based policy rules require audit */ 313 351 #ifdef CONFIG_IMA_LSM_RULES
+21 -6
security/integrity/ima/ima_api.c
··· 45 45 else 46 46 template_desc = ima_template_desc_current(); 47 47 48 - *entry = kzalloc(sizeof(**entry) + template_desc->num_fields * 49 - sizeof(struct ima_field_data), GFP_NOFS); 48 + *entry = kzalloc(struct_size(*entry, template_data, 49 + template_desc->num_fields), GFP_NOFS); 50 50 if (!*entry) 51 51 return -ENOMEM; 52 52 ··· 205 205 */ 206 206 int ima_collect_measurement(struct integrity_iint_cache *iint, 207 207 struct file *file, void *buf, loff_t size, 208 - enum hash_algo algo) 208 + enum hash_algo algo, struct modsig *modsig) 209 209 { 210 210 const char *audit_cause = "failed"; 211 211 struct inode *inode = file_inode(file); ··· 218 218 struct ima_digest_data hdr; 219 219 char digest[IMA_MAX_DIGEST_SIZE]; 220 220 } hash; 221 + 222 + /* 223 + * Always collect the modsig, because IMA might have already collected 224 + * the file digest without collecting the modsig in a previous 225 + * measurement rule. 226 + */ 227 + if (modsig) 228 + ima_collect_modsig(modsig, buf, size); 221 229 222 230 if (iint->flags & IMA_COLLECTED) 223 231 goto out; ··· 293 285 void ima_store_measurement(struct integrity_iint_cache *iint, 294 286 struct file *file, const unsigned char *filename, 295 287 struct evm_ima_xattr_data *xattr_value, 296 - int xattr_len, int pcr, 288 + int xattr_len, const struct modsig *modsig, int pcr, 297 289 struct ima_template_desc *template_desc) 298 290 { 299 291 static const char op[] = "add_template_measure"; ··· 305 297 .file = file, 306 298 .filename = filename, 307 299 .xattr_value = xattr_value, 308 - .xattr_len = xattr_len }; 300 + .xattr_len = xattr_len, 301 + .modsig = modsig }; 309 302 int violation = 0; 310 303 311 - if (iint->measured_pcrs & (0x1 << pcr)) 304 + /* 305 + * We still need to store the measurement in the case of MODSIG because 306 + * we only have its contents to put in the list at the time of 307 + * appraisal, but a file measurement from earlier might already exist in 308 + * the measurement list. 309 + */ 310 + if (iint->measured_pcrs & (0x1 << pcr) && !modsig) 312 311 return; 313 312 314 313 result = ima_alloc_init_template(&event_data, &entry, template_desc);
+129 -65
security/integrity/ima/ima_appraise.c
··· 200 200 } 201 201 202 202 /* 203 + * xattr_verify - verify xattr digest or signature 204 + * 205 + * Verify whether the hash or signature matches the file contents. 206 + * 207 + * Return 0 on success, error code otherwise. 208 + */ 209 + static int xattr_verify(enum ima_hooks func, struct integrity_iint_cache *iint, 210 + struct evm_ima_xattr_data *xattr_value, int xattr_len, 211 + enum integrity_status *status, const char **cause) 212 + { 213 + int rc = -EINVAL, hash_start = 0; 214 + 215 + switch (xattr_value->type) { 216 + case IMA_XATTR_DIGEST_NG: 217 + /* first byte contains algorithm id */ 218 + hash_start = 1; 219 + /* fall through */ 220 + case IMA_XATTR_DIGEST: 221 + if (iint->flags & IMA_DIGSIG_REQUIRED) { 222 + *cause = "IMA-signature-required"; 223 + *status = INTEGRITY_FAIL; 224 + break; 225 + } 226 + clear_bit(IMA_DIGSIG, &iint->atomic_flags); 227 + if (xattr_len - sizeof(xattr_value->type) - hash_start >= 228 + iint->ima_hash->length) 229 + /* 230 + * xattr length may be longer. md5 hash in previous 231 + * version occupied 20 bytes in xattr, instead of 16 232 + */ 233 + rc = memcmp(&xattr_value->data[hash_start], 234 + iint->ima_hash->digest, 235 + iint->ima_hash->length); 236 + else 237 + rc = -EINVAL; 238 + if (rc) { 239 + *cause = "invalid-hash"; 240 + *status = INTEGRITY_FAIL; 241 + break; 242 + } 243 + *status = INTEGRITY_PASS; 244 + break; 245 + case EVM_IMA_XATTR_DIGSIG: 246 + set_bit(IMA_DIGSIG, &iint->atomic_flags); 247 + rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA, 248 + (const char *)xattr_value, 249 + xattr_len, 250 + iint->ima_hash->digest, 251 + iint->ima_hash->length); 252 + if (rc == -EOPNOTSUPP) { 253 + *status = INTEGRITY_UNKNOWN; 254 + break; 255 + } 256 + if (IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING) && rc && 257 + func == KEXEC_KERNEL_CHECK) 258 + rc = integrity_digsig_verify(INTEGRITY_KEYRING_PLATFORM, 259 + (const char *)xattr_value, 260 + xattr_len, 261 + iint->ima_hash->digest, 262 + iint->ima_hash->length); 263 + if (rc) { 264 + *cause = "invalid-signature"; 265 + *status = INTEGRITY_FAIL; 266 + } else { 267 + *status = INTEGRITY_PASS; 268 + } 269 + break; 270 + default: 271 + *status = INTEGRITY_UNKNOWN; 272 + *cause = "unknown-ima-data"; 273 + break; 274 + } 275 + 276 + return rc; 277 + } 278 + 279 + /* 280 + * modsig_verify - verify modsig signature 281 + * 282 + * Verify whether the signature matches the file contents. 283 + * 284 + * Return 0 on success, error code otherwise. 285 + */ 286 + static int modsig_verify(enum ima_hooks func, const struct modsig *modsig, 287 + enum integrity_status *status, const char **cause) 288 + { 289 + int rc; 290 + 291 + rc = integrity_modsig_verify(INTEGRITY_KEYRING_IMA, modsig); 292 + if (IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING) && rc && 293 + func == KEXEC_KERNEL_CHECK) 294 + rc = integrity_modsig_verify(INTEGRITY_KEYRING_PLATFORM, 295 + modsig); 296 + if (rc) { 297 + *cause = "invalid-signature"; 298 + *status = INTEGRITY_FAIL; 299 + } else { 300 + *status = INTEGRITY_PASS; 301 + } 302 + 303 + return rc; 304 + } 305 + 306 + /* 203 307 * ima_appraise_measurement - appraise file measurement 204 308 * 205 309 * Call evm_verifyxattr() to verify the integrity of 'security.ima'. ··· 315 211 struct integrity_iint_cache *iint, 316 212 struct file *file, const unsigned char *filename, 317 213 struct evm_ima_xattr_data *xattr_value, 318 - int xattr_len) 214 + int xattr_len, const struct modsig *modsig) 319 215 { 320 216 static const char op[] = "appraise_data"; 321 217 const char *cause = "unknown"; 322 218 struct dentry *dentry = file_dentry(file); 323 219 struct inode *inode = d_backing_inode(dentry); 324 220 enum integrity_status status = INTEGRITY_UNKNOWN; 325 - int rc = xattr_len, hash_start = 0; 221 + int rc = xattr_len; 222 + bool try_modsig = iint->flags & IMA_MODSIG_ALLOWED && modsig; 326 223 327 - if (!(inode->i_opflags & IOP_XATTR)) 224 + /* If not appraising a modsig, we need an xattr. */ 225 + if (!(inode->i_opflags & IOP_XATTR) && !try_modsig) 328 226 return INTEGRITY_UNKNOWN; 329 227 330 - if (rc <= 0) { 228 + /* If reading the xattr failed and there's no modsig, error out. */ 229 + if (rc <= 0 && !try_modsig) { 331 230 if (rc && rc != -ENODATA) 332 231 goto out; 333 232 ··· 353 246 case INTEGRITY_UNKNOWN: 354 247 break; 355 248 case INTEGRITY_NOXATTRS: /* No EVM protected xattrs. */ 249 + /* It's fine not to have xattrs when using a modsig. */ 250 + if (try_modsig) 251 + break; 252 + /* fall through */ 356 253 case INTEGRITY_NOLABEL: /* No security.evm xattr. */ 357 254 cause = "missing-HMAC"; 358 255 goto out; ··· 367 256 WARN_ONCE(true, "Unexpected integrity status %d\n", status); 368 257 } 369 258 370 - switch (xattr_value->type) { 371 - case IMA_XATTR_DIGEST_NG: 372 - /* first byte contains algorithm id */ 373 - hash_start = 1; 374 - /* fall through */ 375 - case IMA_XATTR_DIGEST: 376 - if (iint->flags & IMA_DIGSIG_REQUIRED) { 377 - cause = "IMA-signature-required"; 378 - status = INTEGRITY_FAIL; 379 - break; 380 - } 381 - clear_bit(IMA_DIGSIG, &iint->atomic_flags); 382 - if (xattr_len - sizeof(xattr_value->type) - hash_start >= 383 - iint->ima_hash->length) 384 - /* xattr length may be longer. md5 hash in previous 385 - version occupied 20 bytes in xattr, instead of 16 386 - */ 387 - rc = memcmp(&xattr_value->data[hash_start], 388 - iint->ima_hash->digest, 389 - iint->ima_hash->length); 390 - else 391 - rc = -EINVAL; 392 - if (rc) { 393 - cause = "invalid-hash"; 394 - status = INTEGRITY_FAIL; 395 - break; 396 - } 397 - status = INTEGRITY_PASS; 398 - break; 399 - case EVM_IMA_XATTR_DIGSIG: 400 - set_bit(IMA_DIGSIG, &iint->atomic_flags); 401 - rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA, 402 - (const char *)xattr_value, 403 - xattr_len, 404 - iint->ima_hash->digest, 405 - iint->ima_hash->length); 406 - if (rc == -EOPNOTSUPP) { 407 - status = INTEGRITY_UNKNOWN; 408 - break; 409 - } 410 - if (IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING) && rc && 411 - func == KEXEC_KERNEL_CHECK) 412 - rc = integrity_digsig_verify(INTEGRITY_KEYRING_PLATFORM, 413 - (const char *)xattr_value, 414 - xattr_len, 415 - iint->ima_hash->digest, 416 - iint->ima_hash->length); 417 - if (rc) { 418 - cause = "invalid-signature"; 419 - status = INTEGRITY_FAIL; 420 - } else { 421 - status = INTEGRITY_PASS; 422 - } 423 - break; 424 - default: 425 - status = INTEGRITY_UNKNOWN; 426 - cause = "unknown-ima-data"; 427 - break; 428 - } 259 + if (xattr_value) 260 + rc = xattr_verify(func, iint, xattr_value, xattr_len, &status, 261 + &cause); 262 + 263 + /* 264 + * If we have a modsig and either no imasig or the imasig's key isn't 265 + * known, then try verifying the modsig. 266 + */ 267 + if (try_modsig && 268 + (!xattr_value || xattr_value->type == IMA_XATTR_DIGEST_NG || 269 + rc == -ENOKEY)) 270 + rc = modsig_verify(func, modsig, &status, &cause); 429 271 430 272 out: 431 273 /* ··· 396 332 op, cause, rc, 0); 397 333 } else if (status != INTEGRITY_PASS) { 398 334 /* Fix mode, but don't replace file signatures. */ 399 - if ((ima_appraise & IMA_APPRAISE_FIX) && 335 + if ((ima_appraise & IMA_APPRAISE_FIX) && !try_modsig && 400 336 (!xattr_value || 401 337 xattr_value->type != EVM_IMA_XATTR_DIGSIG)) { 402 338 if (!ima_fix_xattr(dentry, iint)) ··· 435 371 !(iint->flags & IMA_HASH)) 436 372 return; 437 373 438 - rc = ima_collect_measurement(iint, file, NULL, 0, ima_hash_algo); 374 + rc = ima_collect_measurement(iint, file, NULL, 0, ima_hash_algo, NULL); 439 375 if (rc < 0) 440 376 return; 441 377
+9 -1
security/integrity/ima/ima_crypto.c
··· 268 268 rbuf_len = min_t(loff_t, i_size - offset, rbuf_size[active]); 269 269 rc = integrity_kernel_read(file, offset, rbuf[active], 270 270 rbuf_len); 271 - if (rc != rbuf_len) 271 + if (rc != rbuf_len) { 272 + if (rc >= 0) 273 + rc = -EINVAL; 274 + /* 275 + * Forward current rc, do not overwrite with return value 276 + * from ahash_wait() 277 + */ 278 + ahash_wait(ahash_rc, &wait); 272 279 goto out3; 280 + } 273 281 274 282 if (rbuf[1] && offset) { 275 283 /* Using two buffers, and it is not the first
+20 -4
security/integrity/ima/ima_main.c
··· 202 202 int rc = 0, action, must_appraise = 0; 203 203 int pcr = CONFIG_IMA_MEASURE_PCR_IDX; 204 204 struct evm_ima_xattr_data *xattr_value = NULL; 205 + struct modsig *modsig = NULL; 205 206 int xattr_len = 0; 206 207 bool violation_check; 207 208 enum hash_algo hash_algo; ··· 303 302 } 304 303 305 304 if ((action & IMA_APPRAISE_SUBMASK) || 306 - strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0) 305 + strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0) { 307 306 /* read 'security.ima' */ 308 307 xattr_len = ima_read_xattr(file_dentry(file), &xattr_value); 309 308 309 + /* 310 + * Read the appended modsig if allowed by the policy, and allow 311 + * an additional measurement list entry, if needed, based on the 312 + * template format and whether the file was already measured. 313 + */ 314 + if (iint->flags & IMA_MODSIG_ALLOWED) { 315 + rc = ima_read_modsig(func, buf, size, &modsig); 316 + 317 + if (!rc && ima_template_has_modsig(template_desc) && 318 + iint->flags & IMA_MEASURED) 319 + action |= IMA_MEASURE; 320 + } 321 + } 322 + 310 323 hash_algo = ima_get_hash_algo(xattr_value, xattr_len); 311 324 312 - rc = ima_collect_measurement(iint, file, buf, size, hash_algo); 325 + rc = ima_collect_measurement(iint, file, buf, size, hash_algo, modsig); 313 326 if (rc != 0 && rc != -EBADF && rc != -EINVAL) 314 327 goto out_locked; 315 328 ··· 332 317 333 318 if (action & IMA_MEASURE) 334 319 ima_store_measurement(iint, file, pathname, 335 - xattr_value, xattr_len, pcr, 320 + xattr_value, xattr_len, modsig, pcr, 336 321 template_desc); 337 322 if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) { 338 323 inode_lock(inode); 339 324 rc = ima_appraise_measurement(func, iint, file, pathname, 340 - xattr_value, xattr_len); 325 + xattr_value, xattr_len, modsig); 341 326 inode_unlock(inode); 342 327 if (!rc) 343 328 rc = mmap_violation_check(func, file, &pathbuf, ··· 354 339 rc = -EACCES; 355 340 mutex_unlock(&iint->mutex); 356 341 kfree(xattr_value); 342 + ima_free_modsig(modsig); 357 343 out: 358 344 if (pathbuf) 359 345 __putname(pathbuf);
+168
security/integrity/ima/ima_modsig.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* 3 + * IMA support for appraising module-style appended signatures. 4 + * 5 + * Copyright (C) 2019 IBM Corporation 6 + * 7 + * Author: 8 + * Thiago Jung Bauermann <bauerman@linux.ibm.com> 9 + */ 10 + 11 + #include <linux/types.h> 12 + #include <linux/module_signature.h> 13 + #include <keys/asymmetric-type.h> 14 + #include <crypto/pkcs7.h> 15 + 16 + #include "ima.h" 17 + 18 + struct modsig { 19 + struct pkcs7_message *pkcs7_msg; 20 + 21 + enum hash_algo hash_algo; 22 + 23 + /* This digest will go in the 'd-modsig' field of the IMA template. */ 24 + const u8 *digest; 25 + u32 digest_size; 26 + 27 + /* 28 + * This is what will go to the measurement list if the template requires 29 + * storing the signature. 30 + */ 31 + int raw_pkcs7_len; 32 + u8 raw_pkcs7[]; 33 + }; 34 + 35 + /** 36 + * ima_hook_supports_modsig - can the policy allow modsig for this hook? 37 + * 38 + * modsig is only supported by hooks using ima_post_read_file(), because only 39 + * they preload the contents of the file in a buffer. FILE_CHECK does that in 40 + * some cases, but not when reached from vfs_open(). POLICY_CHECK can support 41 + * it, but it's not useful in practice because it's a text file so deny. 42 + */ 43 + bool ima_hook_supports_modsig(enum ima_hooks func) 44 + { 45 + switch (func) { 46 + case KEXEC_KERNEL_CHECK: 47 + case KEXEC_INITRAMFS_CHECK: 48 + case MODULE_CHECK: 49 + return true; 50 + default: 51 + return false; 52 + } 53 + } 54 + 55 + /* 56 + * ima_read_modsig - Read modsig from buf. 57 + * 58 + * Return: 0 on success, error code otherwise. 59 + */ 60 + int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len, 61 + struct modsig **modsig) 62 + { 63 + const size_t marker_len = strlen(MODULE_SIG_STRING); 64 + const struct module_signature *sig; 65 + struct modsig *hdr; 66 + size_t sig_len; 67 + const void *p; 68 + int rc; 69 + 70 + if (buf_len <= marker_len + sizeof(*sig)) 71 + return -ENOENT; 72 + 73 + p = buf + buf_len - marker_len; 74 + if (memcmp(p, MODULE_SIG_STRING, marker_len)) 75 + return -ENOENT; 76 + 77 + buf_len -= marker_len; 78 + sig = (const struct module_signature *)(p - sizeof(*sig)); 79 + 80 + rc = mod_check_sig(sig, buf_len, func_tokens[func]); 81 + if (rc) 82 + return rc; 83 + 84 + sig_len = be32_to_cpu(sig->sig_len); 85 + buf_len -= sig_len + sizeof(*sig); 86 + 87 + /* Allocate sig_len additional bytes to hold the raw PKCS#7 data. */ 88 + hdr = kzalloc(sizeof(*hdr) + sig_len, GFP_KERNEL); 89 + if (!hdr) 90 + return -ENOMEM; 91 + 92 + hdr->pkcs7_msg = pkcs7_parse_message(buf + buf_len, sig_len); 93 + if (IS_ERR(hdr->pkcs7_msg)) { 94 + rc = PTR_ERR(hdr->pkcs7_msg); 95 + kfree(hdr); 96 + return rc; 97 + } 98 + 99 + memcpy(hdr->raw_pkcs7, buf + buf_len, sig_len); 100 + hdr->raw_pkcs7_len = sig_len; 101 + 102 + /* We don't know the hash algorithm yet. */ 103 + hdr->hash_algo = HASH_ALGO__LAST; 104 + 105 + *modsig = hdr; 106 + 107 + return 0; 108 + } 109 + 110 + /** 111 + * ima_collect_modsig - Calculate the file hash without the appended signature. 112 + * 113 + * Since the modsig is part of the file contents, the hash used in its signature 114 + * isn't the same one ordinarily calculated by IMA. Therefore PKCS7 code 115 + * calculates a separate one for signature verification. 116 + */ 117 + void ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size) 118 + { 119 + int rc; 120 + 121 + /* 122 + * Provide the file contents (minus the appended sig) so that the PKCS7 123 + * code can calculate the file hash. 124 + */ 125 + size -= modsig->raw_pkcs7_len + strlen(MODULE_SIG_STRING) + 126 + sizeof(struct module_signature); 127 + rc = pkcs7_supply_detached_data(modsig->pkcs7_msg, buf, size); 128 + if (rc) 129 + return; 130 + 131 + /* Ask the PKCS7 code to calculate the file hash. */ 132 + rc = pkcs7_get_digest(modsig->pkcs7_msg, &modsig->digest, 133 + &modsig->digest_size, &modsig->hash_algo); 134 + } 135 + 136 + int ima_modsig_verify(struct key *keyring, const struct modsig *modsig) 137 + { 138 + return verify_pkcs7_message_sig(NULL, 0, modsig->pkcs7_msg, keyring, 139 + VERIFYING_MODULE_SIGNATURE, NULL, NULL); 140 + } 141 + 142 + int ima_get_modsig_digest(const struct modsig *modsig, enum hash_algo *algo, 143 + const u8 **digest, u32 *digest_size) 144 + { 145 + *algo = modsig->hash_algo; 146 + *digest = modsig->digest; 147 + *digest_size = modsig->digest_size; 148 + 149 + return 0; 150 + } 151 + 152 + int ima_get_raw_modsig(const struct modsig *modsig, const void **data, 153 + u32 *data_len) 154 + { 155 + *data = &modsig->raw_pkcs7; 156 + *data_len = modsig->raw_pkcs7_len; 157 + 158 + return 0; 159 + } 160 + 161 + void ima_free_modsig(struct modsig *modsig) 162 + { 163 + if (!modsig) 164 + return; 165 + 166 + pkcs7_free_message(modsig->pkcs7_msg); 167 + kfree(modsig); 168 + }
+61 -10
security/integrity/ima/ima_policy.c
··· 6 6 * ima_policy.c 7 7 * - initialize default measure policy rules 8 8 */ 9 + 10 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 11 + 9 12 #include <linux/init.h> 10 13 #include <linux/list.h> 11 14 #include <linux/fs.h> ··· 494 491 struct ima_rule_entry *entry; 495 492 int action = 0, actmask = flags | (flags << 1); 496 493 494 + if (template_desc) 495 + *template_desc = ima_template_desc_current(); 496 + 497 497 rcu_read_lock(); 498 498 list_for_each_entry_rcu(entry, ima_rules, list) { 499 499 ··· 516 510 action |= IMA_FAIL_UNVERIFIABLE_SIGS; 517 511 } 518 512 513 + 519 514 if (entry->action & IMA_DO_MASK) 520 515 actmask &= ~(entry->action | entry->action << 1); 521 516 else ··· 527 520 528 521 if (template_desc && entry->template) 529 522 *template_desc = entry->template; 530 - else if (template_desc) 531 - *template_desc = ima_template_desc_current(); 532 523 533 524 if (!actmask) 534 525 break; ··· 848 843 ima_log_string_op(ab, key, value, NULL); 849 844 } 850 845 846 + /* 847 + * Validating the appended signature included in the measurement list requires 848 + * the file hash calculated without the appended signature (i.e., the 'd-modsig' 849 + * field). Therefore, notify the user if they have the 'modsig' field but not 850 + * the 'd-modsig' field in the template. 851 + */ 852 + static void check_template_modsig(const struct ima_template_desc *template) 853 + { 854 + #define MSG "template with 'modsig' field also needs 'd-modsig' field\n" 855 + bool has_modsig, has_dmodsig; 856 + static bool checked; 857 + int i; 858 + 859 + /* We only need to notify the user once. */ 860 + if (checked) 861 + return; 862 + 863 + has_modsig = has_dmodsig = false; 864 + for (i = 0; i < template->num_fields; i++) { 865 + if (!strcmp(template->fields[i]->field_id, "modsig")) 866 + has_modsig = true; 867 + else if (!strcmp(template->fields[i]->field_id, "d-modsig")) 868 + has_dmodsig = true; 869 + } 870 + 871 + if (has_modsig && !has_dmodsig) 872 + pr_notice(MSG); 873 + 874 + checked = true; 875 + #undef MSG 876 + } 877 + 851 878 static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) 852 879 { 853 880 struct audit_buffer *ab; ··· 1165 1128 ima_log_string(ab, "appraise_type", args[0].from); 1166 1129 if ((strcmp(args[0].from, "imasig")) == 0) 1167 1130 entry->flags |= IMA_DIGSIG_REQUIRED; 1131 + else if (ima_hook_supports_modsig(entry->func) && 1132 + strcmp(args[0].from, "imasig|modsig") == 0) 1133 + entry->flags |= IMA_DIGSIG_REQUIRED | 1134 + IMA_MODSIG_ALLOWED; 1168 1135 else 1169 1136 result = -EINVAL; 1170 1137 break; ··· 1221 1180 result = -EINVAL; 1222 1181 else if (entry->action == APPRAISE) 1223 1182 temp_ima_appraise |= ima_appraise_flag(entry->func); 1183 + 1184 + if (!result && entry->flags & IMA_MODSIG_ALLOWED) { 1185 + template_desc = entry->template ? entry->template : 1186 + ima_template_desc_current(); 1187 + check_template_modsig(template_desc); 1188 + } 1224 1189 1225 1190 audit_log_format(ab, "res=%d", !result); 1226 1191 audit_log_end(ab); ··· 1299 1252 } 1300 1253 } 1301 1254 1255 + #define __ima_hook_stringify(str) (#str), 1256 + 1257 + const char *const func_tokens[] = { 1258 + __ima_hooks(__ima_hook_stringify) 1259 + }; 1260 + 1302 1261 #ifdef CONFIG_IMA_READ_POLICY 1303 1262 enum { 1304 1263 mask_exec = 0, mask_write, mask_read, mask_append ··· 1315 1262 "^MAY_WRITE", 1316 1263 "^MAY_READ", 1317 1264 "^MAY_APPEND" 1318 - }; 1319 - 1320 - #define __ima_hook_stringify(str) (#str), 1321 - 1322 - static const char *const func_tokens[] = { 1323 - __ima_hooks(__ima_hook_stringify) 1324 1265 }; 1325 1266 1326 1267 void *ima_policy_start(struct seq_file *m, loff_t *pos) ··· 1494 1447 } 1495 1448 if (entry->template) 1496 1449 seq_printf(m, "template=%s ", entry->template->name); 1497 - if (entry->flags & IMA_DIGSIG_REQUIRED) 1498 - seq_puts(m, "appraise_type=imasig "); 1450 + if (entry->flags & IMA_DIGSIG_REQUIRED) { 1451 + if (entry->flags & IMA_MODSIG_ALLOWED) 1452 + seq_puts(m, "appraise_type=imasig|modsig "); 1453 + else 1454 + seq_puts(m, "appraise_type=imasig "); 1455 + } 1499 1456 if (entry->flags & IMA_PERMIT_DIRECTIO) 1500 1457 seq_puts(m, "permit_directio "); 1501 1458 rcu_read_unlock();
+27 -4
security/integrity/ima/ima_template.c
··· 23 23 {.name = "ima-ng", .fmt = "d-ng|n-ng"}, 24 24 {.name = "ima-sig", .fmt = "d-ng|n-ng|sig"}, 25 25 {.name = "ima-buf", .fmt = "d-ng|n-ng|buf"}, 26 + {.name = "ima-modsig", .fmt = "d-ng|n-ng|sig|d-modsig|modsig"}, 26 27 {.name = "", .fmt = ""}, /* placeholder for a custom format */ 27 28 }; 28 29 ··· 43 42 .field_show = ima_show_template_sig}, 44 43 {.field_id = "buf", .field_init = ima_eventbuf_init, 45 44 .field_show = ima_show_template_buf}, 45 + {.field_id = "d-modsig", .field_init = ima_eventdigest_modsig_init, 46 + .field_show = ima_show_template_digest_ng}, 47 + {.field_id = "modsig", .field_init = ima_eventmodsig_init, 48 + .field_show = ima_show_template_sig}, 46 49 }; 47 50 48 51 /* ··· 54 49 * need to be accounted for since they shouldn't be defined in the same template 55 50 * description as 'd-ng' and 'n-ng' respectively. 56 51 */ 57 - #define MAX_TEMPLATE_NAME_LEN sizeof("d-ng|n-ng|sig|buf") 52 + #define MAX_TEMPLATE_NAME_LEN sizeof("d-ng|n-ng|sig|buf|d-modisg|modsig") 58 53 59 54 static struct ima_template_desc *ima_template; 55 + 56 + /** 57 + * ima_template_has_modsig - Check whether template has modsig-related fields. 58 + * @ima_template: IMA template to check. 59 + * 60 + * Tells whether the given template has fields referencing a file's appended 61 + * signature. 62 + */ 63 + bool ima_template_has_modsig(const struct ima_template_desc *ima_template) 64 + { 65 + int i; 66 + 67 + for (i = 0; i < ima_template->num_fields; i++) 68 + if (!strcmp(ima_template->fields[i]->field_id, "modsig") || 69 + !strcmp(ima_template->fields[i]->field_id, "d-modsig")) 70 + return true; 71 + 72 + return false; 73 + } 60 74 61 75 static int __init ima_template_setup(char *str) 62 76 { ··· 306 282 int ret = 0; 307 283 int i; 308 284 309 - *entry = kzalloc(sizeof(**entry) + 310 - template_desc->num_fields * sizeof(struct ima_field_data), 311 - GFP_NOFS); 285 + *entry = kzalloc(struct_size(*entry, template_data, 286 + template_desc->num_fields), GFP_NOFS); 312 287 if (!*entry) 313 288 return -ENOMEM; 314 289
+63 -1
security/integrity/ima/ima_template_lib.c
··· 225 225 return 0; 226 226 } 227 227 228 - static int ima_eventdigest_init_common(u8 *digest, u32 digestsize, u8 hash_algo, 228 + static int ima_eventdigest_init_common(const u8 *digest, u32 digestsize, 229 + u8 hash_algo, 229 230 struct ima_field_data *field_data) 230 231 { 231 232 /* ··· 329 328 hash_algo, field_data); 330 329 } 331 330 331 + /* 332 + * This function writes the digest of the file which is expected to match the 333 + * digest contained in the file's appended signature. 334 + */ 335 + int ima_eventdigest_modsig_init(struct ima_event_data *event_data, 336 + struct ima_field_data *field_data) 337 + { 338 + enum hash_algo hash_algo; 339 + const u8 *cur_digest; 340 + u32 cur_digestsize; 341 + 342 + if (!event_data->modsig) 343 + return 0; 344 + 345 + if (event_data->violation) { 346 + /* Recording a violation. */ 347 + hash_algo = HASH_ALGO_SHA1; 348 + cur_digest = NULL; 349 + cur_digestsize = 0; 350 + } else { 351 + int rc; 352 + 353 + rc = ima_get_modsig_digest(event_data->modsig, &hash_algo, 354 + &cur_digest, &cur_digestsize); 355 + if (rc) 356 + return rc; 357 + else if (hash_algo == HASH_ALGO__LAST || cur_digestsize == 0) 358 + /* There was some error collecting the digest. */ 359 + return -EINVAL; 360 + } 361 + 362 + return ima_eventdigest_init_common(cur_digest, cur_digestsize, 363 + hash_algo, field_data); 364 + } 365 + 332 366 static int ima_eventname_init_common(struct ima_event_data *event_data, 333 367 struct ima_field_data *field_data, 334 368 bool size_limit) ··· 440 404 441 405 return ima_write_template_field_data(event_data->buf, 442 406 event_data->buf_len, DATA_FMT_HEX, 407 + field_data); 408 + } 409 + 410 + /* 411 + * ima_eventmodsig_init - include the appended file signature as part of the 412 + * template data 413 + */ 414 + int ima_eventmodsig_init(struct ima_event_data *event_data, 415 + struct ima_field_data *field_data) 416 + { 417 + const void *data; 418 + u32 data_len; 419 + int rc; 420 + 421 + if (!event_data->modsig) 422 + return 0; 423 + 424 + /* 425 + * modsig is a runtime structure containing pointers. Get its raw data 426 + * instead. 427 + */ 428 + rc = ima_get_raw_modsig(event_data->modsig, &data, &data_len); 429 + if (rc) 430 + return rc; 431 + 432 + return ima_write_template_field_data(data, data_len, DATA_FMT_HEX, 443 433 field_data); 444 434 }
+4
security/integrity/ima/ima_template_lib.h
··· 36 36 struct ima_field_data *field_data); 37 37 int ima_eventdigest_ng_init(struct ima_event_data *event_data, 38 38 struct ima_field_data *field_data); 39 + int ima_eventdigest_modsig_init(struct ima_event_data *event_data, 40 + struct ima_field_data *field_data); 39 41 int ima_eventname_ng_init(struct ima_event_data *event_data, 40 42 struct ima_field_data *field_data); 41 43 int ima_eventsig_init(struct ima_event_data *event_data, 42 44 struct ima_field_data *field_data); 43 45 int ima_eventbuf_init(struct ima_event_data *event_data, 44 46 struct ima_field_data *field_data); 47 + int ima_eventmodsig_init(struct ima_event_data *event_data, 48 + struct ima_field_data *field_data); 45 49 #endif /* __LINUX_IMA_TEMPLATE_LIB_H */
+20
security/integrity/integrity.h
··· 31 31 #define IMA_NEW_FILE 0x04000000 32 32 #define EVM_IMMUTABLE_DIGSIG 0x08000000 33 33 #define IMA_FAIL_UNVERIFIABLE_SIGS 0x10000000 34 + #define IMA_MODSIG_ALLOWED 0x20000000 34 35 35 36 #define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \ 36 37 IMA_HASH | IMA_APPRAISE_SUBMASK) ··· 148 147 149 148 extern struct dentry *integrity_dir; 150 149 150 + struct modsig; 151 + 151 152 #ifdef CONFIG_INTEGRITY_SIGNATURE 152 153 153 154 int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, 154 155 const char *digest, int digestlen); 156 + int integrity_modsig_verify(unsigned int id, const struct modsig *modsig); 155 157 156 158 int __init integrity_init_keyring(const unsigned int id); 157 159 int __init integrity_load_x509(const unsigned int id, const char *path); ··· 165 161 static inline int integrity_digsig_verify(const unsigned int id, 166 162 const char *sig, int siglen, 167 163 const char *digest, int digestlen) 164 + { 165 + return -EOPNOTSUPP; 166 + } 167 + 168 + static inline int integrity_modsig_verify(unsigned int id, 169 + const struct modsig *modsig) 168 170 { 169 171 return -EOPNOTSUPP; 170 172 } ··· 195 185 #else 196 186 static inline int asymmetric_verify(struct key *keyring, const char *sig, 197 187 int siglen, const char *data, int datalen) 188 + { 189 + return -EOPNOTSUPP; 190 + } 191 + #endif 192 + 193 + #ifdef CONFIG_IMA_APPRAISE_MODSIG 194 + int ima_modsig_verify(struct key *keyring, const struct modsig *modsig); 195 + #else 196 + static inline int ima_modsig_verify(struct key *keyring, 197 + const struct modsig *modsig) 198 198 { 199 199 return -EOPNOTSUPP; 200 200 }
+34 -4
tools/testing/selftests/kexec/test_kexec_file_load.sh
··· 37 37 # sequentially. As a result, a policy rule may be defined, but 38 38 # might not necessarily be used. This test assumes if a policy 39 39 # rule is specified, that is the intent. 40 + 41 + # First check for appended signature (modsig), then xattr 40 42 if [ $ima_read_policy -eq 1 ]; then 41 43 check_ima_policy "appraise" "func=KEXEC_KERNEL_CHECK" \ 42 - "appraise_type=imasig" 44 + "appraise_type=imasig|modsig" 43 45 ret=$? 44 - [ $ret -eq 1 ] && log_info "IMA signature required"; 46 + if [ $ret -eq 1 ]; then 47 + log_info "IMA or appended(modsig) signature required" 48 + else 49 + check_ima_policy "appraise" "func=KEXEC_KERNEL_CHECK" \ 50 + "appraise_type=imasig" 51 + ret=$? 52 + [ $ret -eq 1 ] && log_info "IMA signature required"; 53 + fi 45 54 fi 46 55 return $ret 47 56 } ··· 93 84 return $ret 94 85 } 95 86 87 + # Return 1 for appended signature (modsig) found and 0 for not found. 88 + check_for_modsig() 89 + { 90 + local module_sig_string="~Module signature appended~" 91 + local sig="$(tail --bytes $((${#module_sig_string} + 1)) $KERNEL_IMAGE)" 92 + local ret=0 93 + 94 + if [ "$sig" == "$module_sig_string" ]; then 95 + ret=1 96 + log_info "kexec kernel image modsig signed" 97 + else 98 + log_info "kexec kernel image not modsig signed" 99 + fi 100 + return $ret 101 + } 102 + 96 103 kexec_file_load_test() 97 104 { 98 105 local succeed_msg="kexec_file_load succeeded" ··· 123 98 # In secureboot mode with an architecture specific 124 99 # policy, make sure either an IMA or PE signature exists. 125 100 if [ $secureboot -eq 1 ] && [ $arch_policy -eq 1 ] && \ 126 - [ $ima_signed -eq 0 ] && [ $pe_signed -eq 0 ]; then 101 + [ $ima_signed -eq 0 ] && [ $pe_signed -eq 0 ] \ 102 + && [ $ima_modsig -eq 0 ]; then 127 103 log_fail "$succeed_msg (missing sig)" 128 104 fi 129 105 ··· 133 107 log_fail "$succeed_msg (missing PE sig)" 134 108 fi 135 109 136 - if [ $ima_sig_required -eq 1 ] && [ $ima_signed -eq 0 ]; then 110 + if [ $ima_sig_required -eq 1 ] && [ $ima_signed -eq 0 ] \ 111 + && [ $ima_modsig -eq 0 ]; then 137 112 log_fail "$succeed_msg (missing IMA sig)" 138 113 fi 139 114 ··· 230 203 231 204 check_for_imasig 232 205 ima_signed=$? 206 + 207 + check_for_modsig 208 + ima_modsig=$? 233 209 234 210 # Test loading the kernel image via kexec_file_load syscall 235 211 kexec_file_load_test