summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-09-27 22:37:27 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2019-09-27 22:37:27 -0400
commitf1f2f614d535564992f32e720739cb53cf03489f (patch)
tree7c363b95df8d63954e822c98462fd3a9a98794ae
parent298fb76a5583900a155d387efaf37a8b39e5dea2 (diff)
parent2a7f0e53daf29ca6dc9fbe2a27158f13474ec1b5 (diff)
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
-rw-r--r--Documentation/ABI/testing/ima_policy6
-rw-r--r--Documentation/security/IMA-templates.rst3
-rw-r--r--arch/s390/Kconfig2
-rw-r--r--arch/s390/kernel/machine_kexec_file.c24
-rw-r--r--certs/system_keyring.c61
-rw-r--r--crypto/asymmetric_keys/pkcs7_verify.c33
-rw-r--r--include/crypto/pkcs7.h4
-rw-r--r--include/linux/module.h3
-rw-r--r--include/linux/module_signature.h46
-rw-r--r--include/linux/verification.h10
-rw-r--r--init/Kconfig6
-rw-r--r--kernel/Makefile1
-rw-r--r--kernel/module.c1
-rw-r--r--kernel/module_signature.c46
-rw-r--r--kernel/module_signing.c56
-rw-r--r--scripts/Makefile2
-rw-r--r--security/integrity/Kconfig2
-rw-r--r--security/integrity/digsig.c43
-rw-r--r--security/integrity/ima/Kconfig13
-rw-r--r--security/integrity/ima/Makefile1
-rw-r--r--security/integrity/ima/ima.h60
-rw-r--r--security/integrity/ima/ima_api.c27
-rw-r--r--security/integrity/ima/ima_appraise.c194
-rw-r--r--security/integrity/ima/ima_crypto.c10
-rw-r--r--security/integrity/ima/ima_main.c24
-rw-r--r--security/integrity/ima/ima_modsig.c168
-rw-r--r--security/integrity/ima/ima_policy.c71
-rw-r--r--security/integrity/ima/ima_template.c31
-rw-r--r--security/integrity/ima/ima_template_lib.c64
-rw-r--r--security/integrity/ima/ima_template_lib.h4
-rw-r--r--security/integrity/integrity.h20
-rwxr-xr-xtools/testing/selftests/kexec/test_kexec_file_load.sh38
32 files changed, 871 insertions, 203 deletions
diff --git a/Documentation/ABI/testing/ima_policy b/Documentation/ABI/testing/ima_policy
index fc376a323908..29ebe9afdac4 100644
--- a/Documentation/ABI/testing/ima_policy
+++ b/Documentation/ABI/testing/ima_policy
@@ -37,7 +37,7 @@ Description:
37 euid:= decimal value 37 euid:= decimal value
38 fowner:= decimal value 38 fowner:= decimal value
39 lsm: are LSM specific 39 lsm: are LSM specific
40 option: appraise_type:= [imasig] 40 option: appraise_type:= [imasig] [imasig|modsig]
41 template:= name of a defined IMA template type 41 template:= name of a defined IMA template type
42 (eg, ima-ng). Only valid when action is "measure". 42 (eg, ima-ng). Only valid when action is "measure".
43 pcr:= decimal value 43 pcr:= decimal value
@@ -105,3 +105,7 @@ Description:
105 105
106 measure func=KEXEC_KERNEL_CHECK pcr=4 106 measure func=KEXEC_KERNEL_CHECK pcr=4
107 measure func=KEXEC_INITRAMFS_CHECK pcr=5 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
diff --git a/Documentation/security/IMA-templates.rst b/Documentation/security/IMA-templates.rst
index 3d1cca287aa4..c5a8432972ef 100644
--- a/Documentation/security/IMA-templates.rst
+++ b/Documentation/security/IMA-templates.rst
@@ -68,8 +68,10 @@ descriptors by adding their identifier to the format string
68 - 'd-ng': the digest of the event, calculated with an arbitrary hash 68 - 'd-ng': the digest of the event, calculated with an arbitrary hash
69 algorithm (field format: [<hash algo>:]digest, where the digest 69 algorithm (field format: [<hash algo>:]digest, where the digest
70 prefix is shown only if the hash algorithm is not SHA1 or MD5); 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 - 'n-ng': the name of the event, without size limitations; 72 - 'n-ng': the name of the event, without size limitations;
72 - 'sig': the file signature; 73 - 'sig': the file signature;
74 - 'modsig' the appended file signature;
73 - 'buf': the buffer data that was used to generate the hash without size limitations; 75 - 'buf': the buffer data that was used to generate the hash without size limitations;
74 76
75 77
@@ -79,6 +81,7 @@ Below, there is the list of defined template descriptors:
79 - "ima-ng" (default): its format is ``d-ng|n-ng``; 81 - "ima-ng" (default): its format is ``d-ng|n-ng``;
80 - "ima-sig": its format is ``d-ng|n-ng|sig``; 82 - "ima-sig": its format is ``d-ng|n-ng|sig``;
81 - "ima-buf": its format is ``d-ng|n-ng|buf``; 83 - "ima-buf": its format is ``d-ng|n-ng|buf``;
84 - "ima-modsig": its format is ``d-ng|n-ng|sig|d-modsig|modsig``;
82 85
83 86
84Use 87Use
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index f933a473b128..68f7c2b16ff7 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -556,7 +556,7 @@ config ARCH_HAS_KEXEC_PURGATORY
556 556
557config KEXEC_VERIFY_SIG 557config KEXEC_VERIFY_SIG
558 bool "Verify kernel signature during kexec_file_load() syscall" 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 help 560 help
561 This option makes kernel signature verification mandatory for 561 This option makes kernel signature verification mandatory for
562 the kexec_file_load() syscall. 562 the kexec_file_load() syscall.
diff --git a/arch/s390/kernel/machine_kexec_file.c b/arch/s390/kernel/machine_kexec_file.c
index fbdd3ea73667..1ac9fbc6e01e 100644
--- a/arch/s390/kernel/machine_kexec_file.c
+++ b/arch/s390/kernel/machine_kexec_file.c
@@ -10,7 +10,7 @@
10#include <linux/elf.h> 10#include <linux/elf.h>
11#include <linux/errno.h> 11#include <linux/errno.h>
12#include <linux/kexec.h> 12#include <linux/kexec.h>
13#include <linux/module.h> 13#include <linux/module_signature.h>
14#include <linux/verification.h> 14#include <linux/verification.h>
15#include <asm/boot_data.h> 15#include <asm/boot_data.h>
16#include <asm/ipl.h> 16#include <asm/ipl.h>
@@ -23,28 +23,6 @@ const struct kexec_file_ops * const kexec_file_loaders[] = {
23}; 23};
24 24
25#ifdef CONFIG_KEXEC_VERIFY_SIG 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 */
36struct 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
48int s390_verify_sig(const char *kernel, unsigned long kernel_len) 26int s390_verify_sig(const char *kernel, unsigned long kernel_len)
49{ 27{
50 const unsigned long marker_len = sizeof(MODULE_SIG_STRING) - 1; 28 const unsigned long marker_len = sizeof(MODULE_SIG_STRING) - 1;
diff --git a/certs/system_keyring.c b/certs/system_keyring.c
index 1eba08a1af82..798291177186 100644
--- a/certs/system_keyring.c
+++ b/certs/system_keyring.c
@@ -190,33 +190,27 @@ late_initcall(load_system_certificate_list);
190#ifdef CONFIG_SYSTEM_DATA_VERIFICATION 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 * @data: The data to be verified (NULL if expecting internal data). 194 * @data: The data to be verified (NULL if expecting internal data).
195 * @len: Size of @data. 195 * @len: Size of @data.
196 * @raw_pkcs7: The PKCS#7 message that is the signature. 196 * @pkcs7: The PKCS#7 message that is the signature.
197 * @pkcs7_len: The size of @raw_pkcs7.
198 * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only, 197 * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only,
199 * (void *)1UL for all trusted keys). 198 * (void *)1UL for all trusted keys).
200 * @usage: The use to which the key is being put. 199 * @usage: The use to which the key is being put.
201 * @view_content: Callback to gain access to content. 200 * @view_content: Callback to gain access to content.
202 * @ctx: Context for callback. 201 * @ctx: Context for callback.
203 */ 202 */
204int verify_pkcs7_signature(const void *data, size_t len, 203int verify_pkcs7_message_sig(const void *data, size_t len,
205 const void *raw_pkcs7, size_t pkcs7_len, 204 struct pkcs7_message *pkcs7,
206 struct key *trusted_keys, 205 struct key *trusted_keys,
207 enum key_being_used_for usage, 206 enum key_being_used_for usage,
208 int (*view_content)(void *ctx, 207 int (*view_content)(void *ctx,
209 const void *data, size_t len, 208 const void *data, size_t len,
210 size_t asn1hdrlen), 209 size_t asn1hdrlen),
211 void *ctx) 210 void *ctx)
212{ 211{
213 struct pkcs7_message *pkcs7;
214 int ret; 212 int ret;
215 213
216 pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len);
217 if (IS_ERR(pkcs7))
218 return PTR_ERR(pkcs7);
219
220 /* The data should be detached - so we need to supply it. */ 214 /* The data should be detached - so we need to supply it. */
221 if (data && pkcs7_supply_detached_data(pkcs7, data, len) < 0) { 215 if (data && pkcs7_supply_detached_data(pkcs7, data, len) < 0) {
222 pr_err("PKCS#7 signature with non-detached data\n"); 216 pr_err("PKCS#7 signature with non-detached data\n");
@@ -269,6 +263,41 @@ int verify_pkcs7_signature(const void *data, size_t len,
269 } 263 }
270 264
271error: 265error:
266 pr_devel("<==%s() = %d\n", __func__, ret);
267 return ret;
268}
269
270/**
271 * verify_pkcs7_signature - Verify a PKCS#7-based signature on system data.
272 * @data: The data to be verified (NULL if expecting internal data).
273 * @len: Size of @data.
274 * @raw_pkcs7: The PKCS#7 message that is the signature.
275 * @pkcs7_len: The size of @raw_pkcs7.
276 * @trusted_keys: Trusted keys to use (NULL for builtin trusted keys only,
277 * (void *)1UL for all trusted keys).
278 * @usage: The use to which the key is being put.
279 * @view_content: Callback to gain access to content.
280 * @ctx: Context for callback.
281 */
282int verify_pkcs7_signature(const void *data, size_t len,
283 const void *raw_pkcs7, size_t pkcs7_len,
284 struct key *trusted_keys,
285 enum key_being_used_for usage,
286 int (*view_content)(void *ctx,
287 const void *data, size_t len,
288 size_t asn1hdrlen),
289 void *ctx)
290{
291 struct pkcs7_message *pkcs7;
292 int ret;
293
294 pkcs7 = pkcs7_parse_message(raw_pkcs7, pkcs7_len);
295 if (IS_ERR(pkcs7))
296 return PTR_ERR(pkcs7);
297
298 ret = verify_pkcs7_message_sig(data, len, pkcs7, trusted_keys, usage,
299 view_content, ctx);
300
272 pkcs7_free_message(pkcs7); 301 pkcs7_free_message(pkcs7);
273 pr_devel("<==%s() = %d\n", __func__, ret); 302 pr_devel("<==%s() = %d\n", __func__, ret);
274 return ret; 303 return ret;
diff --git a/crypto/asymmetric_keys/pkcs7_verify.c b/crypto/asymmetric_keys/pkcs7_verify.c
index 11bee67fa9cc..ce49820caa97 100644
--- a/crypto/asymmetric_keys/pkcs7_verify.c
+++ b/crypto/asymmetric_keys/pkcs7_verify.c
@@ -12,6 +12,7 @@
12#include <linux/err.h> 12#include <linux/err.h>
13#include <linux/asn1.h> 13#include <linux/asn1.h>
14#include <crypto/hash.h> 14#include <crypto/hash.h>
15#include <crypto/hash_info.h>
15#include <crypto/public_key.h> 16#include <crypto/public_key.h>
16#include "pkcs7_parser.h" 17#include "pkcs7_parser.h"
17 18
@@ -29,6 +30,10 @@ static int pkcs7_digest(struct pkcs7_message *pkcs7,
29 30
30 kenter(",%u,%s", sinfo->index, sinfo->sig->hash_algo); 31 kenter(",%u,%s", sinfo->index, sinfo->sig->hash_algo);
31 32
33 /* The digest was calculated already. */
34 if (sig->digest)
35 return 0;
36
32 if (!sinfo->sig->hash_algo) 37 if (!sinfo->sig->hash_algo)
33 return -ENOPKG; 38 return -ENOPKG;
34 39
@@ -117,6 +122,34 @@ error_no_desc:
117 return ret; 122 return ret;
118} 123}
119 124
125int pkcs7_get_digest(struct pkcs7_message *pkcs7, const u8 **buf, u32 *len,
126 enum hash_algo *hash_algo)
127{
128 struct pkcs7_signed_info *sinfo = pkcs7->signed_infos;
129 int i, ret;
130
131 /*
132 * This function doesn't support messages with more than one signature.
133 */
134 if (sinfo == NULL || sinfo->next != NULL)
135 return -EBADMSG;
136
137 ret = pkcs7_digest(pkcs7, sinfo);
138 if (ret)
139 return ret;
140
141 *buf = sinfo->sig->digest;
142 *len = sinfo->sig->digest_size;
143
144 for (i = 0; i < HASH_ALGO__LAST; i++)
145 if (!strcmp(hash_algo_name[i], sinfo->sig->hash_algo)) {
146 *hash_algo = i;
147 break;
148 }
149
150 return 0;
151}
152
120/* 153/*
121 * Find the key (X.509 certificate) to use to verify a PKCS#7 message. PKCS#7 154 * Find the key (X.509 certificate) to use to verify a PKCS#7 message. PKCS#7
122 * uses the issuer's name and the issuing certificate serial number for 155 * uses the issuer's name and the issuing certificate serial number for
diff --git a/include/crypto/pkcs7.h b/include/crypto/pkcs7.h
index 96071bee03ac..38ec7f5f9041 100644
--- a/include/crypto/pkcs7.h
+++ b/include/crypto/pkcs7.h
@@ -9,6 +9,7 @@
9#define _CRYPTO_PKCS7_H 9#define _CRYPTO_PKCS7_H
10 10
11#include <linux/verification.h> 11#include <linux/verification.h>
12#include <linux/hash_info.h>
12#include <crypto/public_key.h> 13#include <crypto/public_key.h>
13 14
14struct key; 15struct key;
@@ -40,4 +41,7 @@ extern int pkcs7_verify(struct pkcs7_message *pkcs7,
40extern int pkcs7_supply_detached_data(struct pkcs7_message *pkcs7, 41extern int pkcs7_supply_detached_data(struct pkcs7_message *pkcs7,
41 const void *data, size_t datalen); 42 const void *data, size_t datalen);
42 43
44extern int pkcs7_get_digest(struct pkcs7_message *pkcs7, const u8 **buf,
45 u32 *len, enum hash_algo *hash_algo);
46
43#endif /* _CRYPTO_PKCS7_H */ 47#endif /* _CRYPTO_PKCS7_H */
diff --git a/include/linux/module.h b/include/linux/module.h
index b1a67352d2dc..6d20895e7739 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -26,9 +26,6 @@
26#include <linux/percpu.h> 26#include <linux/percpu.h>
27#include <asm/module.h> 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/* Not Yet Implemented */ 29/* Not Yet Implemented */
33#define MODULE_SUPPORTED_DEVICE(name) 30#define MODULE_SUPPORTED_DEVICE(name)
34 31
diff --git a/include/linux/module_signature.h b/include/linux/module_signature.h
new file mode 100644
index 000000000000..7eb4b00381ac
--- /dev/null
+++ b/include/linux/module_signature.h
@@ -0,0 +1,46 @@
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
17enum 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 */
33struct 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
43int mod_check_sig(const struct module_signature *ms, size_t file_len,
44 const char *name);
45
46#endif /* _LINUX_MODULE_SIGNATURE_H */
diff --git a/include/linux/verification.h b/include/linux/verification.h
index 32d990d163c4..911ab7c2b1ab 100644
--- a/include/linux/verification.h
+++ b/include/linux/verification.h
@@ -32,6 +32,7 @@ extern const char *const key_being_used_for[NR__KEY_BEING_USED_FOR];
32#ifdef CONFIG_SYSTEM_DATA_VERIFICATION 32#ifdef CONFIG_SYSTEM_DATA_VERIFICATION
33 33
34struct key; 34struct key;
35struct pkcs7_message;
35 36
36extern int verify_pkcs7_signature(const void *data, size_t len, 37extern int verify_pkcs7_signature(const void *data, size_t len,
37 const void *raw_pkcs7, size_t pkcs7_len, 38 const void *raw_pkcs7, size_t pkcs7_len,
@@ -41,6 +42,15 @@ extern int verify_pkcs7_signature(const void *data, size_t len,
41 const void *data, size_t len, 42 const void *data, size_t len,
42 size_t asn1hdrlen), 43 size_t asn1hdrlen),
43 void *ctx); 44 void *ctx);
45extern int verify_pkcs7_message_sig(const void *data, size_t len,
46 struct pkcs7_message *pkcs7,
47 struct key *trusted_keys,
48 enum key_being_used_for usage,
49 int (*view_content)(void *ctx,
50 const void *data,
51 size_t len,
52 size_t asn1hdrlen),
53 void *ctx);
44 54
45#ifdef CONFIG_SIGNED_PE_FILE_VERIFICATION 55#ifdef CONFIG_SIGNED_PE_FILE_VERIFICATION
46extern int verify_pefile_signature(const void *pebuf, unsigned pelen, 56extern int verify_pefile_signature(const void *pebuf, unsigned pelen,
diff --git a/init/Kconfig b/init/Kconfig
index 57123594a7ca..92c867e25a29 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1963,6 +1963,10 @@ config BASE_SMALL
1963 default 0 if BASE_FULL 1963 default 0 if BASE_FULL
1964 default 1 if !BASE_FULL 1964 default 1 if !BASE_FULL
1965 1965
1966config MODULE_SIG_FORMAT
1967 def_bool n
1968 select SYSTEM_DATA_VERIFICATION
1969
1966menuconfig MODULES 1970menuconfig MODULES
1967 bool "Enable loadable module support" 1971 bool "Enable loadable module support"
1968 option modules 1972 option modules
@@ -2047,7 +2051,7 @@ config MODULE_SRCVERSION_ALL
2047 2051
2048config MODULE_SIG 2052config MODULE_SIG
2049 bool "Module signature verification" 2053 bool "Module signature verification"
2050 select SYSTEM_DATA_VERIFICATION 2054 select MODULE_SIG_FORMAT
2051 help 2055 help
2052 Check modules for valid signatures upon load: the signature 2056 Check modules for valid signatures upon load: the signature
2053 is simply appended to the module. For more information see 2057 is simply appended to the module. For more information see
diff --git a/kernel/Makefile b/kernel/Makefile
index 25f9d83d1bbf..daad787fb795 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -58,6 +58,7 @@ endif
58obj-$(CONFIG_UID16) += uid16.o 58obj-$(CONFIG_UID16) += uid16.o
59obj-$(CONFIG_MODULES) += module.o 59obj-$(CONFIG_MODULES) += module.o
60obj-$(CONFIG_MODULE_SIG) += module_signing.o 60obj-$(CONFIG_MODULE_SIG) += module_signing.o
61obj-$(CONFIG_MODULE_SIG_FORMAT) += module_signature.o
61obj-$(CONFIG_KALLSYMS) += kallsyms.o 62obj-$(CONFIG_KALLSYMS) += kallsyms.o
62obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o 63obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
63obj-$(CONFIG_CRASH_CORE) += crash_core.o 64obj-$(CONFIG_CRASH_CORE) += crash_core.o
diff --git a/kernel/module.c b/kernel/module.c
index 32873bcce738..edbe42755a27 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -7,6 +7,7 @@
7#include <linux/export.h> 7#include <linux/export.h>
8#include <linux/extable.h> 8#include <linux/extable.h>
9#include <linux/moduleloader.h> 9#include <linux/moduleloader.h>
10#include <linux/module_signature.h>
10#include <linux/trace_events.h> 11#include <linux/trace_events.h>
11#include <linux/init.h> 12#include <linux/init.h>
12#include <linux/kallsyms.h> 13#include <linux/kallsyms.h>
diff --git a/kernel/module_signature.c b/kernel/module_signature.c
new file mode 100644
index 000000000000..4224a1086b7d
--- /dev/null
+++ b/kernel/module_signature.c
@@ -0,0 +1,46 @@
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 */
21int 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}
diff --git a/kernel/module_signing.c b/kernel/module_signing.c
index b10fb1986ca9..9d9fc678c91d 100644
--- a/kernel/module_signing.c
+++ b/kernel/module_signing.c
@@ -7,37 +7,13 @@
7 7
8#include <linux/kernel.h> 8#include <linux/kernel.h>
9#include <linux/errno.h> 9#include <linux/errno.h>
10#include <linux/module.h>
11#include <linux/module_signature.h>
10#include <linux/string.h> 12#include <linux/string.h>
11#include <linux/verification.h> 13#include <linux/verification.h>
12#include <crypto/public_key.h> 14#include <crypto/public_key.h>
13#include "module-internal.h" 15#include "module-internal.h"
14 16
15enum 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 */
31struct 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
41/* 17/*
42 * Verify the signature on a module. 18 * Verify the signature on a module.
43 */ 19 */
@@ -45,6 +21,7 @@ int mod_verify_sig(const void *mod, struct load_info *info)
45{ 21{
46 struct module_signature ms; 22 struct module_signature ms;
47 size_t sig_len, modlen = info->len; 23 size_t sig_len, modlen = info->len;
24 int ret;
48 25
49 pr_devel("==>%s(,%zu)\n", __func__, modlen); 26 pr_devel("==>%s(,%zu)\n", __func__, modlen);
50 27
@@ -52,32 +29,15 @@ int mod_verify_sig(const void *mod, struct load_info *info)
52 return -EBADMSG; 29 return -EBADMSG;
53 30
54 memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms)); 31 memcpy(&ms, mod + (modlen - sizeof(ms)), sizeof(ms));
55 modlen -= sizeof(ms); 32
33 ret = mod_check_sig(&ms, modlen, info->name);
34 if (ret)
35 return ret;
56 36
57 sig_len = be32_to_cpu(ms.sig_len); 37 sig_len = be32_to_cpu(ms.sig_len);
58 if (sig_len >= modlen) 38 modlen -= sig_len + sizeof(ms);
59 return -EBADMSG;
60 modlen -= sig_len;
61 info->len = modlen; 39 info->len = modlen;
62 40
63 if (ms.id_type != PKEY_ID_PKCS7) {
64 pr_err("%s: Module is not signed with expected PKCS#7 message\n",
65 info->name);
66 return -ENOPKG;
67 }
68
69 if (ms.algo != 0 ||
70 ms.hash != 0 ||
71 ms.signer_len != 0 ||
72 ms.key_id_len != 0 ||
73 ms.__pad[0] != 0 ||
74 ms.__pad[1] != 0 ||
75 ms.__pad[2] != 0) {
76 pr_err("%s: PKCS#7 signature info has unexpected non-zero params\n",
77 info->name);
78 return -EBADMSG;
79 }
80
81 return verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len, 41 return verify_pkcs7_signature(mod, modlen, mod + modlen, sig_len,
82 VERIFY_USE_SECONDARY_KEYRING, 42 VERIFY_USE_SECONDARY_KEYRING,
83 VERIFYING_MODULE_SIGNATURE, 43 VERIFYING_MODULE_SIGNATURE,
diff --git a/scripts/Makefile b/scripts/Makefile
index c42891e10ba3..3e86b300f5a1 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -17,7 +17,7 @@ hostprogs-$(CONFIG_VT) += conmakehash
17hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount 17hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount
18hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable 18hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable
19hostprogs-$(CONFIG_ASN1) += asn1_compiler 19hostprogs-$(CONFIG_ASN1) += asn1_compiler
20hostprogs-$(CONFIG_MODULE_SIG) += sign-file 20hostprogs-$(CONFIG_MODULE_SIG_FORMAT) += sign-file
21hostprogs-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert 21hostprogs-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert
22hostprogs-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert 22hostprogs-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert
23 23
diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index c352532b8f84..0bae6adb63a9 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig
@@ -18,8 +18,8 @@ if INTEGRITY
18 18
19config INTEGRITY_SIGNATURE 19config INTEGRITY_SIGNATURE
20 bool "Digital signature verification using multiple keyrings" 20 bool "Digital signature verification using multiple keyrings"
21 depends on KEYS
22 default n 21 default n
22 select KEYS
23 select SIGNATURE 23 select SIGNATURE
24 help 24 help
25 This option enables digital signature verification support 25 This option enables digital signature verification support
diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
index 868ade3e8970..ea1aae3d07b3 100644
--- a/security/integrity/digsig.c
+++ b/security/integrity/digsig.c
@@ -39,11 +39,10 @@ static const char * const keyring_name[INTEGRITY_KEYRING_MAX] = {
39#define restrict_link_to_ima restrict_link_by_builtin_trusted 39#define restrict_link_to_ima restrict_link_by_builtin_trusted
40#endif 40#endif
41 41
42int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, 42static struct key *integrity_keyring_from_id(const unsigned int id)
43 const char *digest, int digestlen)
44{ 43{
45 if (id >= INTEGRITY_KEYRING_MAX || siglen < 2) 44 if (id >= INTEGRITY_KEYRING_MAX)
46 return -EINVAL; 45 return ERR_PTR(-EINVAL);
47 46
48 if (!keyring[id]) { 47 if (!keyring[id]) {
49 keyring[id] = 48 keyring[id] =
@@ -52,23 +51,49 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
52 int err = PTR_ERR(keyring[id]); 51 int err = PTR_ERR(keyring[id]);
53 pr_err("no %s keyring: %d\n", keyring_name[id], err); 52 pr_err("no %s keyring: %d\n", keyring_name[id], err);
54 keyring[id] = NULL; 53 keyring[id] = NULL;
55 return err; 54 return ERR_PTR(err);
56 } 55 }
57 } 56 }
58 57
58 return keyring[id];
59}
60
61int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
62 const char *digest, int digestlen)
63{
64 struct key *keyring;
65
66 if (siglen < 2)
67 return -EINVAL;
68
69 keyring = integrity_keyring_from_id(id);
70 if (IS_ERR(keyring))
71 return PTR_ERR(keyring);
72
59 switch (sig[1]) { 73 switch (sig[1]) {
60 case 1: 74 case 1:
61 /* v1 API expect signature without xattr type */ 75 /* v1 API expect signature without xattr type */
62 return digsig_verify(keyring[id], sig + 1, siglen - 1, 76 return digsig_verify(keyring, sig + 1, siglen - 1, digest,
63 digest, digestlen); 77 digestlen);
64 case 2: 78 case 2:
65 return asymmetric_verify(keyring[id], sig, siglen, 79 return asymmetric_verify(keyring, sig, siglen, digest,
66 digest, digestlen); 80 digestlen);
67 } 81 }
68 82
69 return -EOPNOTSUPP; 83 return -EOPNOTSUPP;
70} 84}
71 85
86int integrity_modsig_verify(const unsigned int id, const struct modsig *modsig)
87{
88 struct key *keyring;
89
90 keyring = integrity_keyring_from_id(id);
91 if (IS_ERR(keyring))
92 return PTR_ERR(keyring);
93
94 return ima_modsig_verify(keyring, modsig);
95}
96
72static int __init __integrity_init_keyring(const unsigned int id, 97static int __init __integrity_init_keyring(const unsigned int id,
73 key_perm_t perm, 98 key_perm_t perm,
74 struct key_restriction *restriction) 99 struct key_restriction *restriction)
diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 2ced99dde694..897bafc59a33 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -233,6 +233,19 @@ config IMA_APPRAISE_BOOTPARAM
233 This option enables the different "ima_appraise=" modes 233 This option enables the different "ima_appraise=" modes
234 (eg. fix, log) from the boot command line. 234 (eg. fix, log) from the boot command line.
235 235
236config 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
236config IMA_TRUSTED_KEYRING 249config IMA_TRUSTED_KEYRING
237 bool "Require all keys on the .ima keyring be signed (deprecated)" 250 bool "Require all keys on the .ima keyring be signed (deprecated)"
238 depends on IMA_APPRAISE && SYSTEM_TRUSTED_KEYRING 251 depends on IMA_APPRAISE && SYSTEM_TRUSTED_KEYRING
diff --git a/security/integrity/ima/Makefile b/security/integrity/ima/Makefile
index d921dc4f9eb0..31d57cdf2421 100644
--- a/security/integrity/ima/Makefile
+++ b/security/integrity/ima/Makefile
@@ -9,5 +9,6 @@ obj-$(CONFIG_IMA) += ima.o
9ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \ 9ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \
10 ima_policy.o ima_template.o ima_template_lib.o 10 ima_policy.o ima_template.o ima_template_lib.o
11ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o 11ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o
12ima-$(CONFIG_IMA_APPRAISE_MODSIG) += ima_modsig.o
12ima-$(CONFIG_HAVE_IMA_KEXEC) += ima_kexec.o 13ima-$(CONFIG_HAVE_IMA_KEXEC) += ima_kexec.o
13obj-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o 14obj-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o
diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h
index 011b91c79351..19769bf5f6ab 100644
--- a/security/integrity/ima/ima.h
+++ b/security/integrity/ima/ima.h
@@ -60,6 +60,7 @@ struct ima_event_data {
60 const unsigned char *filename; 60 const unsigned char *filename;
61 struct evm_ima_xattr_data *xattr_value; 61 struct evm_ima_xattr_data *xattr_value;
62 int xattr_len; 62 int xattr_len;
63 const struct modsig *modsig;
63 const char *violation; 64 const char *violation;
64 const void *buf; 65 const void *buf;
65 int buf_len; 66 int buf_len;
@@ -149,6 +150,7 @@ int template_desc_init_fields(const char *template_fmt,
149 int *num_fields); 150 int *num_fields);
150struct ima_template_desc *ima_template_desc_current(void); 151struct ima_template_desc *ima_template_desc_current(void);
151struct ima_template_desc *lookup_template_desc(const char *name); 152struct ima_template_desc *lookup_template_desc(const char *name);
153bool ima_template_has_modsig(const struct ima_template_desc *ima_template);
152int ima_restore_measurement_entry(struct ima_template_entry *entry); 154int ima_restore_measurement_entry(struct ima_template_entry *entry);
153int ima_restore_measurement_list(loff_t bufsize, void *buf); 155int ima_restore_measurement_list(loff_t bufsize, void *buf);
154int ima_measurements_show(struct seq_file *m, void *v); 156int ima_measurements_show(struct seq_file *m, void *v);
@@ -196,6 +198,10 @@ enum ima_hooks {
196 __ima_hooks(__ima_hook_enumify) 198 __ima_hooks(__ima_hook_enumify)
197}; 199};
198 200
201extern const char *const func_tokens[];
202
203struct modsig;
204
199/* LIM API function definitions */ 205/* LIM API function definitions */
200int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid, 206int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
201 int mask, enum ima_hooks func, int *pcr, 207 int mask, enum ima_hooks func, int *pcr,
@@ -203,11 +209,11 @@ int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
203int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func); 209int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func);
204int ima_collect_measurement(struct integrity_iint_cache *iint, 210int ima_collect_measurement(struct integrity_iint_cache *iint,
205 struct file *file, void *buf, loff_t size, 211 struct file *file, void *buf, loff_t size,
206 enum hash_algo algo); 212 enum hash_algo algo, struct modsig *modsig);
207void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file, 213void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
208 const unsigned char *filename, 214 const unsigned char *filename,
209 struct evm_ima_xattr_data *xattr_value, 215 struct evm_ima_xattr_data *xattr_value,
210 int xattr_len, int pcr, 216 int xattr_len, const struct modsig *modsig, int pcr,
211 struct ima_template_desc *template_desc); 217 struct ima_template_desc *template_desc);
212void ima_audit_measurement(struct integrity_iint_cache *iint, 218void ima_audit_measurement(struct integrity_iint_cache *iint,
213 const unsigned char *filename); 219 const unsigned char *filename);
@@ -249,7 +255,7 @@ int ima_appraise_measurement(enum ima_hooks func,
249 struct integrity_iint_cache *iint, 255 struct integrity_iint_cache *iint,
250 struct file *file, const unsigned char *filename, 256 struct file *file, const unsigned char *filename,
251 struct evm_ima_xattr_data *xattr_value, 257 struct evm_ima_xattr_data *xattr_value,
252 int xattr_len); 258 int xattr_len, const struct modsig *modsig);
253int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func); 259int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func);
254void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file); 260void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
255enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint, 261enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
@@ -265,7 +271,8 @@ static inline int ima_appraise_measurement(enum ima_hooks func,
265 struct file *file, 271 struct file *file,
266 const unsigned char *filename, 272 const unsigned char *filename,
267 struct evm_ima_xattr_data *xattr_value, 273 struct evm_ima_xattr_data *xattr_value,
268 int xattr_len) 274 int xattr_len,
275 const struct modsig *modsig)
269{ 276{
270 return INTEGRITY_UNKNOWN; 277 return INTEGRITY_UNKNOWN;
271} 278}
@@ -302,6 +309,51 @@ static inline int ima_read_xattr(struct dentry *dentry,
302 309
303#endif /* CONFIG_IMA_APPRAISE */ 310#endif /* CONFIG_IMA_APPRAISE */
304 311
312#ifdef CONFIG_IMA_APPRAISE_MODSIG
313bool ima_hook_supports_modsig(enum ima_hooks func);
314int ima_read_modsig(enum ima_hooks func, const void *buf, loff_t buf_len,
315 struct modsig **modsig);
316void ima_collect_modsig(struct modsig *modsig, const void *buf, loff_t size);
317int ima_get_modsig_digest(const struct modsig *modsig, enum hash_algo *algo,
318 const u8 **digest, u32 *digest_size);
319int ima_get_raw_modsig(const struct modsig *modsig, const void **data,
320 u32 *data_len);
321void ima_free_modsig(struct modsig *modsig);
322#else
323static inline bool ima_hook_supports_modsig(enum ima_hooks func)
324{
325 return false;
326}
327
328static inline int ima_read_modsig(enum ima_hooks func, const void *buf,
329 loff_t buf_len, struct modsig **modsig)
330{
331 return -EOPNOTSUPP;
332}
333
334static inline void ima_collect_modsig(struct modsig *modsig, const void *buf,
335 loff_t size)
336{
337}
338
339static inline int ima_get_modsig_digest(const struct modsig *modsig,
340 enum hash_algo *algo, const u8 **digest,
341 u32 *digest_size)
342{
343 return -EOPNOTSUPP;
344}
345
346static inline int ima_get_raw_modsig(const struct modsig *modsig,
347 const void **data, u32 *data_len)
348{
349 return -EOPNOTSUPP;
350}
351
352static inline void ima_free_modsig(struct modsig *modsig)
353{
354}
355#endif /* CONFIG_IMA_APPRAISE_MODSIG */
356
305/* LSM based policy rules require audit */ 357/* LSM based policy rules require audit */
306#ifdef CONFIG_IMA_LSM_RULES 358#ifdef CONFIG_IMA_LSM_RULES
307 359
diff --git a/security/integrity/ima/ima_api.c b/security/integrity/ima/ima_api.c
index f614e22bf39f..610759fe63b8 100644
--- a/security/integrity/ima/ima_api.c
+++ b/security/integrity/ima/ima_api.c
@@ -45,8 +45,8 @@ int ima_alloc_init_template(struct ima_event_data *event_data,
45 else 45 else
46 template_desc = ima_template_desc_current(); 46 template_desc = ima_template_desc_current();
47 47
48 *entry = kzalloc(sizeof(**entry) + template_desc->num_fields * 48 *entry = kzalloc(struct_size(*entry, template_data,
49 sizeof(struct ima_field_data), GFP_NOFS); 49 template_desc->num_fields), GFP_NOFS);
50 if (!*entry) 50 if (!*entry)
51 return -ENOMEM; 51 return -ENOMEM;
52 52
@@ -205,7 +205,7 @@ int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
205 */ 205 */
206int ima_collect_measurement(struct integrity_iint_cache *iint, 206int ima_collect_measurement(struct integrity_iint_cache *iint,
207 struct file *file, void *buf, loff_t size, 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 const char *audit_cause = "failed"; 210 const char *audit_cause = "failed";
211 struct inode *inode = file_inode(file); 211 struct inode *inode = file_inode(file);
@@ -219,6 +219,14 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
219 char digest[IMA_MAX_DIGEST_SIZE]; 219 char digest[IMA_MAX_DIGEST_SIZE];
220 } hash; 220 } hash;
221 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);
229
222 if (iint->flags & IMA_COLLECTED) 230 if (iint->flags & IMA_COLLECTED)
223 goto out; 231 goto out;
224 232
@@ -285,7 +293,7 @@ out:
285void ima_store_measurement(struct integrity_iint_cache *iint, 293void ima_store_measurement(struct integrity_iint_cache *iint,
286 struct file *file, const unsigned char *filename, 294 struct file *file, const unsigned char *filename,
287 struct evm_ima_xattr_data *xattr_value, 295 struct evm_ima_xattr_data *xattr_value,
288 int xattr_len, int pcr, 296 int xattr_len, const struct modsig *modsig, int pcr,
289 struct ima_template_desc *template_desc) 297 struct ima_template_desc *template_desc)
290{ 298{
291 static const char op[] = "add_template_measure"; 299 static const char op[] = "add_template_measure";
@@ -297,10 +305,17 @@ void ima_store_measurement(struct integrity_iint_cache *iint,
297 .file = file, 305 .file = file,
298 .filename = filename, 306 .filename = filename,
299 .xattr_value = xattr_value, 307 .xattr_value = xattr_value,
300 .xattr_len = xattr_len }; 308 .xattr_len = xattr_len,
309 .modsig = modsig };
301 int violation = 0; 310 int violation = 0;
302 311
303 if (iint->measured_pcrs & (0x1 << pcr)) 312 /*
313 * We still need to store the measurement in the case of MODSIG because
314 * we only have its contents to put in the list at the time of
315 * appraisal, but a file measurement from earlier might already exist in
316 * the measurement list.
317 */
318 if (iint->measured_pcrs & (0x1 << pcr) && !modsig)
304 return; 319 return;
305 320
306 result = ima_alloc_init_template(&event_data, &entry, template_desc); 321 result = ima_alloc_init_template(&event_data, &entry, template_desc);
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 89b83194d1dc..136ae4e0ee92 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -200,6 +200,110 @@ int ima_read_xattr(struct dentry *dentry,
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 */
209static 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 */
286static 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 * ima_appraise_measurement - appraise file measurement 307 * ima_appraise_measurement - appraise file measurement
204 * 308 *
205 * Call evm_verifyxattr() to verify the integrity of 'security.ima'. 309 * Call evm_verifyxattr() to verify the integrity of 'security.ima'.
@@ -211,19 +315,22 @@ int ima_appraise_measurement(enum ima_hooks func,
211 struct integrity_iint_cache *iint, 315 struct integrity_iint_cache *iint,
212 struct file *file, const unsigned char *filename, 316 struct file *file, const unsigned char *filename,
213 struct evm_ima_xattr_data *xattr_value, 317 struct evm_ima_xattr_data *xattr_value,
214 int xattr_len) 318 int xattr_len, const struct modsig *modsig)
215{ 319{
216 static const char op[] = "appraise_data"; 320 static const char op[] = "appraise_data";
217 const char *cause = "unknown"; 321 const char *cause = "unknown";
218 struct dentry *dentry = file_dentry(file); 322 struct dentry *dentry = file_dentry(file);
219 struct inode *inode = d_backing_inode(dentry); 323 struct inode *inode = d_backing_inode(dentry);
220 enum integrity_status status = INTEGRITY_UNKNOWN; 324 enum integrity_status status = INTEGRITY_UNKNOWN;
221 int rc = xattr_len, hash_start = 0; 325 int rc = xattr_len;
326 bool try_modsig = iint->flags & IMA_MODSIG_ALLOWED && modsig;
222 327
223 if (!(inode->i_opflags & IOP_XATTR)) 328 /* If not appraising a modsig, we need an xattr. */
329 if (!(inode->i_opflags & IOP_XATTR) && !try_modsig)
224 return INTEGRITY_UNKNOWN; 330 return INTEGRITY_UNKNOWN;
225 331
226 if (rc <= 0) { 332 /* If reading the xattr failed and there's no modsig, error out. */
333 if (rc <= 0 && !try_modsig) {
227 if (rc && rc != -ENODATA) 334 if (rc && rc != -ENODATA)
228 goto out; 335 goto out;
229 336
@@ -246,6 +353,10 @@ int ima_appraise_measurement(enum ima_hooks func,
246 case INTEGRITY_UNKNOWN: 353 case INTEGRITY_UNKNOWN:
247 break; 354 break;
248 case INTEGRITY_NOXATTRS: /* No EVM protected xattrs. */ 355 case INTEGRITY_NOXATTRS: /* No EVM protected xattrs. */
356 /* It's fine not to have xattrs when using a modsig. */
357 if (try_modsig)
358 break;
359 /* fall through */
249 case INTEGRITY_NOLABEL: /* No security.evm xattr. */ 360 case INTEGRITY_NOLABEL: /* No security.evm xattr. */
250 cause = "missing-HMAC"; 361 cause = "missing-HMAC";
251 goto out; 362 goto out;
@@ -256,65 +367,18 @@ int ima_appraise_measurement(enum ima_hooks func,
256 WARN_ONCE(true, "Unexpected integrity status %d\n", status); 367 WARN_ONCE(true, "Unexpected integrity status %d\n", status);
257 } 368 }
258 369
259 switch (xattr_value->type) { 370 if (xattr_value)
260 case IMA_XATTR_DIGEST_NG: 371 rc = xattr_verify(func, iint, xattr_value, xattr_len, &status,
261 /* first byte contains algorithm id */ 372 &cause);
262 hash_start = 1; 373
263 /* fall through */ 374 /*
264 case IMA_XATTR_DIGEST: 375 * If we have a modsig and either no imasig or the imasig's key isn't
265 if (iint->flags & IMA_DIGSIG_REQUIRED) { 376 * known, then try verifying the modsig.
266 cause = "IMA-signature-required"; 377 */
267 status = INTEGRITY_FAIL; 378 if (try_modsig &&
268 break; 379 (!xattr_value || xattr_value->type == IMA_XATTR_DIGEST_NG ||
269 } 380 rc == -ENOKEY))
270 clear_bit(IMA_DIGSIG, &iint->atomic_flags); 381 rc = modsig_verify(func, modsig, &status, &cause);
271 if (xattr_len - sizeof(xattr_value->type) - hash_start >=
272 iint->ima_hash->length)
273 /* xattr length may be longer. md5 hash in previous
274 version occupied 20 bytes in xattr, instead of 16
275 */
276 rc = memcmp(&xattr_value->data[hash_start],
277 iint->ima_hash->digest,
278 iint->ima_hash->length);
279 else
280 rc = -EINVAL;
281 if (rc) {
282 cause = "invalid-hash";
283 status = INTEGRITY_FAIL;
284 break;
285 }
286 status = INTEGRITY_PASS;
287 break;
288 case EVM_IMA_XATTR_DIGSIG:
289 set_bit(IMA_DIGSIG, &iint->atomic_flags);
290 rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA,
291 (const char *)xattr_value,
292 xattr_len,
293 iint->ima_hash->digest,
294 iint->ima_hash->length);
295 if (rc == -EOPNOTSUPP) {
296 status = INTEGRITY_UNKNOWN;
297 break;
298 }
299 if (IS_ENABLED(CONFIG_INTEGRITY_PLATFORM_KEYRING) && rc &&
300 func == KEXEC_KERNEL_CHECK)
301 rc = integrity_digsig_verify(INTEGRITY_KEYRING_PLATFORM,
302 (const char *)xattr_value,
303 xattr_len,
304 iint->ima_hash->digest,
305 iint->ima_hash->length);
306 if (rc) {
307 cause = "invalid-signature";
308 status = INTEGRITY_FAIL;
309 } else {
310 status = INTEGRITY_PASS;
311 }
312 break;
313 default:
314 status = INTEGRITY_UNKNOWN;
315 cause = "unknown-ima-data";
316 break;
317 }
318 382
319out: 383out:
320 /* 384 /*
@@ -332,7 +396,7 @@ out:
332 op, cause, rc, 0); 396 op, cause, rc, 0);
333 } else if (status != INTEGRITY_PASS) { 397 } else if (status != INTEGRITY_PASS) {
334 /* Fix mode, but don't replace file signatures. */ 398 /* Fix mode, but don't replace file signatures. */
335 if ((ima_appraise & IMA_APPRAISE_FIX) && 399 if ((ima_appraise & IMA_APPRAISE_FIX) && !try_modsig &&
336 (!xattr_value || 400 (!xattr_value ||
337 xattr_value->type != EVM_IMA_XATTR_DIGSIG)) { 401 xattr_value->type != EVM_IMA_XATTR_DIGSIG)) {
338 if (!ima_fix_xattr(dentry, iint)) 402 if (!ima_fix_xattr(dentry, iint))
@@ -371,7 +435,7 @@ void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file)
371 !(iint->flags & IMA_HASH)) 435 !(iint->flags & IMA_HASH))
372 return; 436 return;
373 437
374 rc = ima_collect_measurement(iint, file, NULL, 0, ima_hash_algo); 438 rc = ima_collect_measurement(iint, file, NULL, 0, ima_hash_algo, NULL);
375 if (rc < 0) 439 if (rc < 0)
376 return; 440 return;
377 441
diff --git a/security/integrity/ima/ima_crypto.c b/security/integrity/ima/ima_crypto.c
index d4c7b8e1b083..73044fc6a952 100644
--- a/security/integrity/ima/ima_crypto.c
+++ b/security/integrity/ima/ima_crypto.c
@@ -268,8 +268,16 @@ static int ima_calc_file_hash_atfm(struct file *file,
268 rbuf_len = min_t(loff_t, i_size - offset, rbuf_size[active]); 268 rbuf_len = min_t(loff_t, i_size - offset, rbuf_size[active]);
269 rc = integrity_kernel_read(file, offset, rbuf[active], 269 rc = integrity_kernel_read(file, offset, rbuf[active],
270 rbuf_len); 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 goto out3; 279 goto out3;
280 }
273 281
274 if (rbuf[1] && offset) { 282 if (rbuf[1] && offset) {
275 /* Using two buffers, and it is not the first 283 /* Using two buffers, and it is not the first
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index 584019728660..79c01516211b 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -202,6 +202,7 @@ static int process_measurement(struct file *file, const struct cred *cred,
202 int rc = 0, action, must_appraise = 0; 202 int rc = 0, action, must_appraise = 0;
203 int pcr = CONFIG_IMA_MEASURE_PCR_IDX; 203 int pcr = CONFIG_IMA_MEASURE_PCR_IDX;
204 struct evm_ima_xattr_data *xattr_value = NULL; 204 struct evm_ima_xattr_data *xattr_value = NULL;
205 struct modsig *modsig = NULL;
205 int xattr_len = 0; 206 int xattr_len = 0;
206 bool violation_check; 207 bool violation_check;
207 enum hash_algo hash_algo; 208 enum hash_algo hash_algo;
@@ -302,13 +303,27 @@ static int process_measurement(struct file *file, const struct cred *cred,
302 } 303 }
303 304
304 if ((action & IMA_APPRAISE_SUBMASK) || 305 if ((action & IMA_APPRAISE_SUBMASK) ||
305 strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0) 306 strcmp(template_desc->name, IMA_TEMPLATE_IMA_NAME) != 0) {
306 /* read 'security.ima' */ 307 /* read 'security.ima' */
307 xattr_len = ima_read_xattr(file_dentry(file), &xattr_value); 308 xattr_len = ima_read_xattr(file_dentry(file), &xattr_value);
308 309
310 /*
311 * Read the appended modsig if allowed by the policy, and allow
312 * an additional measurement list entry, if needed, based on the
313 * template format and whether the file was already measured.
314 */
315 if (iint->flags & IMA_MODSIG_ALLOWED) {
316 rc = ima_read_modsig(func, buf, size, &modsig);
317
318 if (!rc && ima_template_has_modsig(template_desc) &&
319 iint->flags & IMA_MEASURED)
320 action |= IMA_MEASURE;
321 }
322 }
323
309 hash_algo = ima_get_hash_algo(xattr_value, xattr_len); 324 hash_algo = ima_get_hash_algo(xattr_value, xattr_len);
310 325
311 rc = ima_collect_measurement(iint, file, buf, size, hash_algo); 326 rc = ima_collect_measurement(iint, file, buf, size, hash_algo, modsig);
312 if (rc != 0 && rc != -EBADF && rc != -EINVAL) 327 if (rc != 0 && rc != -EBADF && rc != -EINVAL)
313 goto out_locked; 328 goto out_locked;
314 329
@@ -317,12 +332,12 @@ static int process_measurement(struct file *file, const struct cred *cred,
317 332
318 if (action & IMA_MEASURE) 333 if (action & IMA_MEASURE)
319 ima_store_measurement(iint, file, pathname, 334 ima_store_measurement(iint, file, pathname,
320 xattr_value, xattr_len, pcr, 335 xattr_value, xattr_len, modsig, pcr,
321 template_desc); 336 template_desc);
322 if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) { 337 if (rc == 0 && (action & IMA_APPRAISE_SUBMASK)) {
323 inode_lock(inode); 338 inode_lock(inode);
324 rc = ima_appraise_measurement(func, iint, file, pathname, 339 rc = ima_appraise_measurement(func, iint, file, pathname,
325 xattr_value, xattr_len); 340 xattr_value, xattr_len, modsig);
326 inode_unlock(inode); 341 inode_unlock(inode);
327 if (!rc) 342 if (!rc)
328 rc = mmap_violation_check(func, file, &pathbuf, 343 rc = mmap_violation_check(func, file, &pathbuf,
@@ -339,6 +354,7 @@ out_locked:
339 rc = -EACCES; 354 rc = -EACCES;
340 mutex_unlock(&iint->mutex); 355 mutex_unlock(&iint->mutex);
341 kfree(xattr_value); 356 kfree(xattr_value);
357 ima_free_modsig(modsig);
342out: 358out:
343 if (pathbuf) 359 if (pathbuf)
344 __putname(pathbuf); 360 __putname(pathbuf);
diff --git a/security/integrity/ima/ima_modsig.c b/security/integrity/ima/ima_modsig.c
new file mode 100644
index 000000000000..d106885cc495
--- /dev/null
+++ b/security/integrity/ima/ima_modsig.c
@@ -0,0 +1,168 @@
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
18struct 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 */
43bool 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 */
60int 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 */
117void 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
136int 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
142int 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
152int 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
161void ima_free_modsig(struct modsig *modsig)
162{
163 if (!modsig)
164 return;
165
166 pkcs7_free_message(modsig->pkcs7_msg);
167 kfree(modsig);
168}
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 6df7f641ff66..4badc4fcda98 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -6,6 +6,9 @@
6 * ima_policy.c 6 * ima_policy.c
7 * - initialize default measure policy rules 7 * - initialize default measure policy rules
8 */ 8 */
9
10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
11
9#include <linux/init.h> 12#include <linux/init.h>
10#include <linux/list.h> 13#include <linux/list.h>
11#include <linux/fs.h> 14#include <linux/fs.h>
@@ -491,6 +494,9 @@ int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
491 struct ima_rule_entry *entry; 494 struct ima_rule_entry *entry;
492 int action = 0, actmask = flags | (flags << 1); 495 int action = 0, actmask = flags | (flags << 1);
493 496
497 if (template_desc)
498 *template_desc = ima_template_desc_current();
499
494 rcu_read_lock(); 500 rcu_read_lock();
495 list_for_each_entry_rcu(entry, ima_rules, list) { 501 list_for_each_entry_rcu(entry, ima_rules, list) {
496 502
@@ -510,6 +516,7 @@ int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
510 action |= IMA_FAIL_UNVERIFIABLE_SIGS; 516 action |= IMA_FAIL_UNVERIFIABLE_SIGS;
511 } 517 }
512 518
519
513 if (entry->action & IMA_DO_MASK) 520 if (entry->action & IMA_DO_MASK)
514 actmask &= ~(entry->action | entry->action << 1); 521 actmask &= ~(entry->action | entry->action << 1);
515 else 522 else
@@ -520,8 +527,6 @@ int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
520 527
521 if (template_desc && entry->template) 528 if (template_desc && entry->template)
522 *template_desc = entry->template; 529 *template_desc = entry->template;
523 else if (template_desc)
524 *template_desc = ima_template_desc_current();
525 530
526 if (!actmask) 531 if (!actmask)
527 break; 532 break;
@@ -843,6 +848,38 @@ static void ima_log_string(struct audit_buffer *ab, char *key, char *value)
843 ima_log_string_op(ab, key, value, NULL); 848 ima_log_string_op(ab, key, value, NULL);
844} 849}
845 850
851/*
852 * Validating the appended signature included in the measurement list requires
853 * the file hash calculated without the appended signature (i.e., the 'd-modsig'
854 * field). Therefore, notify the user if they have the 'modsig' field but not
855 * the 'd-modsig' field in the template.
856 */
857static void check_template_modsig(const struct ima_template_desc *template)
858{
859#define MSG "template with 'modsig' field also needs 'd-modsig' field\n"
860 bool has_modsig, has_dmodsig;
861 static bool checked;
862 int i;
863
864 /* We only need to notify the user once. */
865 if (checked)
866 return;
867
868 has_modsig = has_dmodsig = false;
869 for (i = 0; i < template->num_fields; i++) {
870 if (!strcmp(template->fields[i]->field_id, "modsig"))
871 has_modsig = true;
872 else if (!strcmp(template->fields[i]->field_id, "d-modsig"))
873 has_dmodsig = true;
874 }
875
876 if (has_modsig && !has_dmodsig)
877 pr_notice(MSG);
878
879 checked = true;
880#undef MSG
881}
882
846static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) 883static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
847{ 884{
848 struct audit_buffer *ab; 885 struct audit_buffer *ab;
@@ -1128,6 +1165,10 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
1128 ima_log_string(ab, "appraise_type", args[0].from); 1165 ima_log_string(ab, "appraise_type", args[0].from);
1129 if ((strcmp(args[0].from, "imasig")) == 0) 1166 if ((strcmp(args[0].from, "imasig")) == 0)
1130 entry->flags |= IMA_DIGSIG_REQUIRED; 1167 entry->flags |= IMA_DIGSIG_REQUIRED;
1168 else if (ima_hook_supports_modsig(entry->func) &&
1169 strcmp(args[0].from, "imasig|modsig") == 0)
1170 entry->flags |= IMA_DIGSIG_REQUIRED |
1171 IMA_MODSIG_ALLOWED;
1131 else 1172 else
1132 result = -EINVAL; 1173 result = -EINVAL;
1133 break; 1174 break;
@@ -1181,6 +1222,12 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
1181 else if (entry->action == APPRAISE) 1222 else if (entry->action == APPRAISE)
1182 temp_ima_appraise |= ima_appraise_flag(entry->func); 1223 temp_ima_appraise |= ima_appraise_flag(entry->func);
1183 1224
1225 if (!result && entry->flags & IMA_MODSIG_ALLOWED) {
1226 template_desc = entry->template ? entry->template :
1227 ima_template_desc_current();
1228 check_template_modsig(template_desc);
1229 }
1230
1184 audit_log_format(ab, "res=%d", !result); 1231 audit_log_format(ab, "res=%d", !result);
1185 audit_log_end(ab); 1232 audit_log_end(ab);
1186 return result; 1233 return result;
@@ -1252,6 +1299,12 @@ void ima_delete_rules(void)
1252 } 1299 }
1253} 1300}
1254 1301
1302#define __ima_hook_stringify(str) (#str),
1303
1304const char *const func_tokens[] = {
1305 __ima_hooks(__ima_hook_stringify)
1306};
1307
1255#ifdef CONFIG_IMA_READ_POLICY 1308#ifdef CONFIG_IMA_READ_POLICY
1256enum { 1309enum {
1257 mask_exec = 0, mask_write, mask_read, mask_append 1310 mask_exec = 0, mask_write, mask_read, mask_append
@@ -1264,12 +1317,6 @@ static const char *const mask_tokens[] = {
1264 "^MAY_APPEND" 1317 "^MAY_APPEND"
1265}; 1318};
1266 1319
1267#define __ima_hook_stringify(str) (#str),
1268
1269static const char *const func_tokens[] = {
1270 __ima_hooks(__ima_hook_stringify)
1271};
1272
1273void *ima_policy_start(struct seq_file *m, loff_t *pos) 1320void *ima_policy_start(struct seq_file *m, loff_t *pos)
1274{ 1321{
1275 loff_t l = *pos; 1322 loff_t l = *pos;
@@ -1447,8 +1494,12 @@ int ima_policy_show(struct seq_file *m, void *v)
1447 } 1494 }
1448 if (entry->template) 1495 if (entry->template)
1449 seq_printf(m, "template=%s ", entry->template->name); 1496 seq_printf(m, "template=%s ", entry->template->name);
1450 if (entry->flags & IMA_DIGSIG_REQUIRED) 1497 if (entry->flags & IMA_DIGSIG_REQUIRED) {
1451 seq_puts(m, "appraise_type=imasig "); 1498 if (entry->flags & IMA_MODSIG_ALLOWED)
1499 seq_puts(m, "appraise_type=imasig|modsig ");
1500 else
1501 seq_puts(m, "appraise_type=imasig ");
1502 }
1452 if (entry->flags & IMA_PERMIT_DIRECTIO) 1503 if (entry->flags & IMA_PERMIT_DIRECTIO)
1453 seq_puts(m, "permit_directio "); 1504 seq_puts(m, "permit_directio ");
1454 rcu_read_unlock(); 1505 rcu_read_unlock();
diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c
index cb349d7b2601..6aa6408603e3 100644
--- a/security/integrity/ima/ima_template.c
+++ b/security/integrity/ima/ima_template.c
@@ -23,6 +23,7 @@ static struct ima_template_desc builtin_templates[] = {
23 {.name = "ima-ng", .fmt = "d-ng|n-ng"}, 23 {.name = "ima-ng", .fmt = "d-ng|n-ng"},
24 {.name = "ima-sig", .fmt = "d-ng|n-ng|sig"}, 24 {.name = "ima-sig", .fmt = "d-ng|n-ng|sig"},
25 {.name = "ima-buf", .fmt = "d-ng|n-ng|buf"}, 25 {.name = "ima-buf", .fmt = "d-ng|n-ng|buf"},
26 {.name = "ima-modsig", .fmt = "d-ng|n-ng|sig|d-modsig|modsig"},
26 {.name = "", .fmt = ""}, /* placeholder for a custom format */ 27 {.name = "", .fmt = ""}, /* placeholder for a custom format */
27}; 28};
28 29
@@ -42,6 +43,10 @@ static const struct ima_template_field supported_fields[] = {
42 .field_show = ima_show_template_sig}, 43 .field_show = ima_show_template_sig},
43 {.field_id = "buf", .field_init = ima_eventbuf_init, 44 {.field_id = "buf", .field_init = ima_eventbuf_init,
44 .field_show = ima_show_template_buf}, 45 .field_show = ima_show_template_buf},
46 {.field_id = "d-modsig", .field_init = ima_eventdigest_modsig_init,
47 .field_show = ima_show_template_digest_ng},
48 {.field_id = "modsig", .field_init = ima_eventmodsig_init,
49 .field_show = ima_show_template_sig},
45}; 50};
46 51
47/* 52/*
@@ -49,10 +54,29 @@ static const struct ima_template_field supported_fields[] = {
49 * need to be accounted for since they shouldn't be defined in the same template 54 * need to be accounted for since they shouldn't be defined in the same template
50 * description as 'd-ng' and 'n-ng' respectively. 55 * description as 'd-ng' and 'n-ng' respectively.
51 */ 56 */
52#define MAX_TEMPLATE_NAME_LEN sizeof("d-ng|n-ng|sig|buf") 57#define MAX_TEMPLATE_NAME_LEN sizeof("d-ng|n-ng|sig|buf|d-modisg|modsig")
53 58
54static struct ima_template_desc *ima_template; 59static struct ima_template_desc *ima_template;
55 60
61/**
62 * ima_template_has_modsig - Check whether template has modsig-related fields.
63 * @ima_template: IMA template to check.
64 *
65 * Tells whether the given template has fields referencing a file's appended
66 * signature.
67 */
68bool ima_template_has_modsig(const struct ima_template_desc *ima_template)
69{
70 int i;
71
72 for (i = 0; i < ima_template->num_fields; i++)
73 if (!strcmp(ima_template->fields[i]->field_id, "modsig") ||
74 !strcmp(ima_template->fields[i]->field_id, "d-modsig"))
75 return true;
76
77 return false;
78}
79
56static int __init ima_template_setup(char *str) 80static int __init ima_template_setup(char *str)
57{ 81{
58 struct ima_template_desc *template_desc; 82 struct ima_template_desc *template_desc;
@@ -282,9 +306,8 @@ static int ima_restore_template_data(struct ima_template_desc *template_desc,
282 int ret = 0; 306 int ret = 0;
283 int i; 307 int i;
284 308
285 *entry = kzalloc(sizeof(**entry) + 309 *entry = kzalloc(struct_size(*entry, template_data,
286 template_desc->num_fields * sizeof(struct ima_field_data), 310 template_desc->num_fields), GFP_NOFS);
287 GFP_NOFS);
288 if (!*entry) 311 if (!*entry)
289 return -ENOMEM; 312 return -ENOMEM;
290 313
diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c
index 2fb9a10bc6b7..32ae05d88257 100644
--- a/security/integrity/ima/ima_template_lib.c
+++ b/security/integrity/ima/ima_template_lib.c
@@ -225,7 +225,8 @@ int ima_parse_buf(void *bufstartp, void *bufendp, void **bufcurp,
225 return 0; 225 return 0;
226} 226}
227 227
228static int ima_eventdigest_init_common(u8 *digest, u32 digestsize, u8 hash_algo, 228static int ima_eventdigest_init_common(const u8 *digest, u32 digestsize,
229 u8 hash_algo,
229 struct ima_field_data *field_data) 230 struct ima_field_data *field_data)
230{ 231{
231 /* 232 /*
@@ -328,6 +329,41 @@ out:
328 hash_algo, field_data); 329 hash_algo, field_data);
329} 330}
330 331
332/*
333 * This function writes the digest of the file which is expected to match the
334 * digest contained in the file's appended signature.
335 */
336int ima_eventdigest_modsig_init(struct ima_event_data *event_data,
337 struct ima_field_data *field_data)
338{
339 enum hash_algo hash_algo;
340 const u8 *cur_digest;
341 u32 cur_digestsize;
342
343 if (!event_data->modsig)
344 return 0;
345
346 if (event_data->violation) {
347 /* Recording a violation. */
348 hash_algo = HASH_ALGO_SHA1;
349 cur_digest = NULL;
350 cur_digestsize = 0;
351 } else {
352 int rc;
353
354 rc = ima_get_modsig_digest(event_data->modsig, &hash_algo,
355 &cur_digest, &cur_digestsize);
356 if (rc)
357 return rc;
358 else if (hash_algo == HASH_ALGO__LAST || cur_digestsize == 0)
359 /* There was some error collecting the digest. */
360 return -EINVAL;
361 }
362
363 return ima_eventdigest_init_common(cur_digest, cur_digestsize,
364 hash_algo, field_data);
365}
366
331static int ima_eventname_init_common(struct ima_event_data *event_data, 367static int ima_eventname_init_common(struct ima_event_data *event_data,
332 struct ima_field_data *field_data, 368 struct ima_field_data *field_data,
333 bool size_limit) 369 bool size_limit)
@@ -406,3 +442,29 @@ int ima_eventbuf_init(struct ima_event_data *event_data,
406 event_data->buf_len, DATA_FMT_HEX, 442 event_data->buf_len, DATA_FMT_HEX,
407 field_data); 443 field_data);
408} 444}
445
446/*
447 * ima_eventmodsig_init - include the appended file signature as part of the
448 * template data
449 */
450int ima_eventmodsig_init(struct ima_event_data *event_data,
451 struct ima_field_data *field_data)
452{
453 const void *data;
454 u32 data_len;
455 int rc;
456
457 if (!event_data->modsig)
458 return 0;
459
460 /*
461 * modsig is a runtime structure containing pointers. Get its raw data
462 * instead.
463 */
464 rc = ima_get_raw_modsig(event_data->modsig, &data, &data_len);
465 if (rc)
466 return rc;
467
468 return ima_write_template_field_data(data, data_len, DATA_FMT_HEX,
469 field_data);
470}
diff --git a/security/integrity/ima/ima_template_lib.h b/security/integrity/ima/ima_template_lib.h
index 652aa5de81ef..9a88c79a7a61 100644
--- a/security/integrity/ima/ima_template_lib.h
+++ b/security/integrity/ima/ima_template_lib.h
@@ -36,10 +36,14 @@ int ima_eventname_init(struct ima_event_data *event_data,
36 struct ima_field_data *field_data); 36 struct ima_field_data *field_data);
37int ima_eventdigest_ng_init(struct ima_event_data *event_data, 37int ima_eventdigest_ng_init(struct ima_event_data *event_data,
38 struct ima_field_data *field_data); 38 struct ima_field_data *field_data);
39int ima_eventdigest_modsig_init(struct ima_event_data *event_data,
40 struct ima_field_data *field_data);
39int ima_eventname_ng_init(struct ima_event_data *event_data, 41int ima_eventname_ng_init(struct ima_event_data *event_data,
40 struct ima_field_data *field_data); 42 struct ima_field_data *field_data);
41int ima_eventsig_init(struct ima_event_data *event_data, 43int ima_eventsig_init(struct ima_event_data *event_data,
42 struct ima_field_data *field_data); 44 struct ima_field_data *field_data);
43int ima_eventbuf_init(struct ima_event_data *event_data, 45int ima_eventbuf_init(struct ima_event_data *event_data,
44 struct ima_field_data *field_data); 46 struct ima_field_data *field_data);
47int ima_eventmodsig_init(struct ima_event_data *event_data,
48 struct ima_field_data *field_data);
45#endif /* __LINUX_IMA_TEMPLATE_LIB_H */ 49#endif /* __LINUX_IMA_TEMPLATE_LIB_H */
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index ed12d8e13d04..d9323d31a3a8 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -31,6 +31,7 @@
31#define IMA_NEW_FILE 0x04000000 31#define IMA_NEW_FILE 0x04000000
32#define EVM_IMMUTABLE_DIGSIG 0x08000000 32#define EVM_IMMUTABLE_DIGSIG 0x08000000
33#define IMA_FAIL_UNVERIFIABLE_SIGS 0x10000000 33#define IMA_FAIL_UNVERIFIABLE_SIGS 0x10000000
34#define IMA_MODSIG_ALLOWED 0x20000000
34 35
35#define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \ 36#define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \
36 IMA_HASH | IMA_APPRAISE_SUBMASK) 37 IMA_HASH | IMA_APPRAISE_SUBMASK)
@@ -147,10 +148,13 @@ int integrity_kernel_read(struct file *file, loff_t offset,
147 148
148extern struct dentry *integrity_dir; 149extern struct dentry *integrity_dir;
149 150
151struct modsig;
152
150#ifdef CONFIG_INTEGRITY_SIGNATURE 153#ifdef CONFIG_INTEGRITY_SIGNATURE
151 154
152int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen, 155int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
153 const char *digest, int digestlen); 156 const char *digest, int digestlen);
157int integrity_modsig_verify(unsigned int id, const struct modsig *modsig);
154 158
155int __init integrity_init_keyring(const unsigned int id); 159int __init integrity_init_keyring(const unsigned int id);
156int __init integrity_load_x509(const unsigned int id, const char *path); 160int __init integrity_load_x509(const unsigned int id, const char *path);
@@ -165,6 +169,12 @@ static inline int integrity_digsig_verify(const unsigned int id,
165 return -EOPNOTSUPP; 169 return -EOPNOTSUPP;
166} 170}
167 171
172static inline int integrity_modsig_verify(unsigned int id,
173 const struct modsig *modsig)
174{
175 return -EOPNOTSUPP;
176}
177
168static inline int integrity_init_keyring(const unsigned int id) 178static inline int integrity_init_keyring(const unsigned int id)
169{ 179{
170 return 0; 180 return 0;
@@ -190,6 +200,16 @@ static inline int asymmetric_verify(struct key *keyring, const char *sig,
190} 200}
191#endif 201#endif
192 202
203#ifdef CONFIG_IMA_APPRAISE_MODSIG
204int ima_modsig_verify(struct key *keyring, const struct modsig *modsig);
205#else
206static inline int ima_modsig_verify(struct key *keyring,
207 const struct modsig *modsig)
208{
209 return -EOPNOTSUPP;
210}
211#endif
212
193#ifdef CONFIG_IMA_LOAD_X509 213#ifdef CONFIG_IMA_LOAD_X509
194void __init ima_load_x509(void); 214void __init ima_load_x509(void);
195#else 215#else
diff --git a/tools/testing/selftests/kexec/test_kexec_file_load.sh b/tools/testing/selftests/kexec/test_kexec_file_load.sh
index fa7c24e8eefb..2ff600388c30 100755
--- a/tools/testing/selftests/kexec/test_kexec_file_load.sh
+++ b/tools/testing/selftests/kexec/test_kexec_file_load.sh
@@ -37,11 +37,20 @@ is_ima_sig_required()
37 # sequentially. As a result, a policy rule may be defined, but 37 # sequentially. As a result, a policy rule may be defined, but
38 # might not necessarily be used. This test assumes if a policy 38 # might not necessarily be used. This test assumes if a policy
39 # rule is specified, that is the intent. 39 # rule is specified, that is the intent.
40
41 # First check for appended signature (modsig), then xattr
40 if [ $ima_read_policy -eq 1 ]; then 42 if [ $ima_read_policy -eq 1 ]; then
41 check_ima_policy "appraise" "func=KEXEC_KERNEL_CHECK" \ 43 check_ima_policy "appraise" "func=KEXEC_KERNEL_CHECK" \
42 "appraise_type=imasig" 44 "appraise_type=imasig|modsig"
43 ret=$? 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 fi 54 fi
46 return $ret 55 return $ret
47} 56}
@@ -84,6 +93,22 @@ check_for_imasig()
84 return $ret 93 return $ret
85} 94}
86 95
96# Return 1 for appended signature (modsig) found and 0 for not found.
97check_for_modsig()
98{
99 local module_sig_string="~Module signature appended~"
100 local sig="$(tail --bytes $((${#module_sig_string} + 1)) $KERNEL_IMAGE)"
101 local ret=0
102
103 if [ "$sig" == "$module_sig_string" ]; then
104 ret=1
105 log_info "kexec kernel image modsig signed"
106 else
107 log_info "kexec kernel image not modsig signed"
108 fi
109 return $ret
110}
111
87kexec_file_load_test() 112kexec_file_load_test()
88{ 113{
89 local succeed_msg="kexec_file_load succeeded" 114 local succeed_msg="kexec_file_load succeeded"
@@ -98,7 +123,8 @@ kexec_file_load_test()
98 # In secureboot mode with an architecture specific 123 # In secureboot mode with an architecture specific
99 # policy, make sure either an IMA or PE signature exists. 124 # policy, make sure either an IMA or PE signature exists.
100 if [ $secureboot -eq 1 ] && [ $arch_policy -eq 1 ] && \ 125 if [ $secureboot -eq 1 ] && [ $arch_policy -eq 1 ] && \
101 [ $ima_signed -eq 0 ] && [ $pe_signed -eq 0 ]; then 126 [ $ima_signed -eq 0 ] && [ $pe_signed -eq 0 ] \
127 && [ $ima_modsig -eq 0 ]; then
102 log_fail "$succeed_msg (missing sig)" 128 log_fail "$succeed_msg (missing sig)"
103 fi 129 fi
104 130
@@ -107,7 +133,8 @@ kexec_file_load_test()
107 log_fail "$succeed_msg (missing PE sig)" 133 log_fail "$succeed_msg (missing PE sig)"
108 fi 134 fi
109 135
110 if [ $ima_sig_required -eq 1 ] && [ $ima_signed -eq 0 ]; then 136 if [ $ima_sig_required -eq 1 ] && [ $ima_signed -eq 0 ] \
137 && [ $ima_modsig -eq 0 ]; then
111 log_fail "$succeed_msg (missing IMA sig)" 138 log_fail "$succeed_msg (missing IMA sig)"
112 fi 139 fi
113 140
@@ -204,5 +231,8 @@ pe_signed=$?
204check_for_imasig 231check_for_imasig
205ima_signed=$? 232ima_signed=$?
206 233
234check_for_modsig
235ima_modsig=$?
236
207# Test loading the kernel image via kexec_file_load syscall 237# Test loading the kernel image via kexec_file_load syscall
208kexec_file_load_test 238kexec_file_load_test