History

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

Linus Torvalds committed 7 years ago

Commit f1f2f612 parents 298fb76 2a7f0e532 files · +871 −203Browse files

Unified · Split

32 files
  1. Documentation/ABI/testing/ima_policy +5 −1
  2. Documentation/security/IMA-templates.rst +3 −0
  3. arch/s390/Kconfig +1 −1
  4. arch/s390/kernel/machine_kexec_file.c +1 −23
  5. certs/system_keyring.c +45 −16
  6. crypto/asymmetric_keys/pkcs7_verify.c +33 −0
  7. include/crypto/pkcs7.h +4 −0
  8. include/linux/module.h +0 −3
  9. include/linux/module_signature.h +46 −0
  10. include/linux/verification.h +10 −0
  11. init/Kconfig +5 −1
  12. kernel/Makefile +1 −0
  13. kernel/module.c +1 −0
  14. kernel/module_signature.c +46 −0
  15. kernel/module_signing.c +8 −48
  16. scripts/Makefile +1 −1
  17. security/integrity/Kconfig +1 −1
  18. security/integrity/digsig.c +34 −9
  19. security/integrity/ima/Kconfig +13 −0
  20. security/integrity/ima/Makefile +1 −0
  21. security/integrity/ima/ima.h +56 −4
  22. security/integrity/ima/ima_api.c +21 −6
  23. security/integrity/ima/ima_appraise.c +129 −65
  24. security/integrity/ima/ima_crypto.c +9 −1
  25. security/integrity/ima/ima_main.c +20 −4
  26. security/integrity/ima/ima_modsig.c +168 −0
  27. security/integrity/ima/ima_policy.c +61 −10
  28. security/integrity/ima/ima_template.c +27 −4
  29. security/integrity/ima/ima_template_lib.c +63 −1
  30. security/integrity/ima/ima_template_lib.h +4 −0
  31. security/integrity/integrity.h +20 −0
  32. tools/testing/selftests/kexec/test_kexec_file_load.sh +34 −4
Documentation/ABI/testing/ima_policy+5−1
@@ -37,7 +37,7 @@ Description: · 36 unmodified lines
37 euid:= decimal value37 euid:= decimal value
38 fowner:= decimal value38 fowner:= decimal value
39 lsm: are LSM specific39 lsm: are LSM specific
40 option: appraise_type:= [imasig]40 option: appraise_type:= [imasig] [imasig|modsig]
41 template:= name of a defined IMA template type41 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 value43 pcr:= decimal value
@@ -105,3 +105,7 @@ Description: · 61 unmodified lines
105 105
106 measure func=KEXEC_KERNEL_CHECK pcr=4106 measure func=KEXEC_KERNEL_CHECK pcr=4
107 measure func=KEXEC_INITRAMFS_CHECK pcr=5107 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
Documentation/security/IMA-templates.rst+3−0
@@ -68,8 +68,10 @@ descriptors by adding their identifier to the format string · 67 unmodified lines
68 - 'd-ng': the digest of the event, calculated with an arbitrary hash68 - 'd-ng': the digest of the event, calculated with an arbitrary hash
69 algorithm (field format: [<hash algo>:]digest, where the digest69 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: · 3 unmodified lines
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
84Use87Use
arch/s390/Kconfig+1−1
@@ -556,7 +556,7 @@ config ARCH_HAS_KEXEC_PURGATORY · 555 unmodified lines
556 556
557config KEXEC_VERIFY_SIG557config 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_VERIFICATION559 depends on KEXEC_FILE && MODULE_SIG_FORMAT
560 help560 help
561 This option makes kernel signature verification mandatory for561 This option makes kernel signature verification mandatory for
562 the kexec_file_load() syscall.562 the kexec_file_load() syscall.
arch/s390/kernel/machine_kexec_file.c+1−23
@@ -10,7 +10,7 @@ · 9 unmodified lines
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[] = { · 6 unmodified lines
23};23};
24 24
25#ifdef CONFIG_KEXEC_VERIFY_SIG25#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;
certs/system_keyring.c+45−16
@@ -190,33 +190,27 @@ late_initcall(load_system_certificate_list); · 189 unmodified lines
190#ifdef CONFIG_SYSTEM_DATA_VERIFICATION190#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, · 46 unmodified lines
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;
crypto/asymmetric_keys/pkcs7_verify.c+33−0
@@ -12,6 +12,7 @@ · 11 unmodified lines
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, · 11 unmodified lines
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: · 82 unmodified lines
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#7154 * 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 for155 * uses the issuer's name and the issuing certificate serial number for
include/crypto/pkcs7.h+4−0
@@ -9,6 +9,7 @@ · 8 unmodified lines
9#define _CRYPTO_PKCS7_H9#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, · 25 unmodified lines
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 */
include/linux/module.h+0−3
@@ -26,9 +26,6 @@ · 25 unmodified lines
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
include/linux/module_signature.h+46−0
@@ -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 */
include/linux/verification.h+10−0
@@ -32,6 +32,7 @@ extern const char *const key_being_used_for[NR__KEY_BEING_USED_FOR]; · 31 unmodified lines
32#ifdef CONFIG_SYSTEM_DATA_VERIFICATION32#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, · 3 unmodified lines
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_VERIFICATION55#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,
init/Kconfig+5−1
@@ -1963,6 +1963,10 @@ config BASE_SMALL · 1962 unmodified lines
1963 default 0 if BASE_FULL1963 default 0 if BASE_FULL
1964 default 1 if !BASE_FULL1964 default 1 if !BASE_FULL
1965 1965
1966config MODULE_SIG_FORMAT
1967 def_bool n
1968 select SYSTEM_DATA_VERIFICATION
1969
1966menuconfig MODULES1970menuconfig MODULES
1967 bool "Enable loadable module support"1971 bool "Enable loadable module support"
1968 option modules1972 option modules
@@ -2047,7 +2051,7 @@ config MODULE_SRCVERSION_ALL · 78 unmodified lines
2047 2051
2048config MODULE_SIG2052config MODULE_SIG
2049 bool "Module signature verification"2053 bool "Module signature verification"
2050 select SYSTEM_DATA_VERIFICATION2054 select MODULE_SIG_FORMAT
2051 help2055 help
2052 Check modules for valid signatures upon load: the signature2056 Check modules for valid signatures upon load: the signature
2053 is simply appended to the module. For more information see2057 is simply appended to the module. For more information see
kernel/Makefile+1−0
@@ -58,6 +58,7 @@ endif · 57 unmodified lines
58obj-$(CONFIG_UID16) += uid16.o58obj-$(CONFIG_UID16) += uid16.o
59obj-$(CONFIG_MODULES) += module.o59obj-$(CONFIG_MODULES) += module.o
60obj-$(CONFIG_MODULE_SIG) += module_signing.o60obj-$(CONFIG_MODULE_SIG) += module_signing.o
61obj-$(CONFIG_MODULE_SIG_FORMAT) += module_signature.o
61obj-$(CONFIG_KALLSYMS) += kallsyms.o62obj-$(CONFIG_KALLSYMS) += kallsyms.o
62obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o63obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
63obj-$(CONFIG_CRASH_CORE) += crash_core.o64obj-$(CONFIG_CRASH_CORE) += crash_core.o
kernel/module.c+1−0
@@ -7,6 +7,7 @@ · 6 unmodified lines
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>
kernel/module_signature.c+46−0
@@ -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}
kernel/module_signing.c+8−48
@@ -7,37 +7,13 @@ · 6 unmodified lines
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) · 1 unmodified line
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) · 1 unmodified line
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,
scripts/Makefile+1−1
@@ -17,7 +17,7 @@ hostprogs-$(CONFIG_VT) += conmakehash · 16 unmodified lines
17hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount17hostprogs-$(BUILD_C_RECORDMCOUNT) += recordmcount
18hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable18hostprogs-$(CONFIG_BUILDTIME_EXTABLE_SORT) += sortextable
19hostprogs-$(CONFIG_ASN1) += asn1_compiler19hostprogs-$(CONFIG_ASN1) += asn1_compiler
20hostprogs-$(CONFIG_MODULE_SIG) += sign-file20hostprogs-$(CONFIG_MODULE_SIG_FORMAT) += sign-file
21hostprogs-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert21hostprogs-$(CONFIG_SYSTEM_TRUSTED_KEYRING) += extract-cert
22hostprogs-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert22hostprogs-$(CONFIG_SYSTEM_EXTRA_CERTIFICATE) += insert-sys-cert
23 23
security/integrity/Kconfig+1−1
@@ -18,8 +18,8 @@ if INTEGRITY · 17 unmodified lines
18 18
19config INTEGRITY_SIGNATURE19config INTEGRITY_SIGNATURE
20 bool "Digital signature verification using multiple keyrings"20 bool "Digital signature verification using multiple keyrings"
21 depends on KEYS
22 default n21 default n
22 select KEYS
23 select SIGNATURE23 select SIGNATURE
24 help24 help
25 This option enables digital signature verification support25 This option enables digital signature verification support
security/integrity/digsig.c+34−9
@@ -39,11 +39,10 @@ static const char * const keyring_name[INTEGRITY_KEYRING_MAX] = { · 38 unmodified lines
39#define restrict_link_to_ima restrict_link_by_builtin_trusted39#define restrict_link_to_ima restrict_link_by_builtin_trusted
40#endif40#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, · 2 unmodified lines
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)
security/integrity/ima/Kconfig+13−0
@@ -233,6 +233,19 @@ config IMA_APPRAISE_BOOTPARAM · 232 unmodified lines
233 This option enables the different "ima_appraise=" modes233 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_KEYRING249config 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_KEYRING251 depends on IMA_APPRAISE && SYSTEM_TRUSTED_KEYRING
security/integrity/ima/Makefile+1−0
@@ -9,5 +9,6 @@ obj-$(CONFIG_IMA) += ima.o · 8 unmodified lines
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.o10 ima_policy.o ima_template.o ima_template_lib.o
11ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o11ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o
12ima-$(CONFIG_IMA_APPRAISE_MODSIG) += ima_modsig.o
12ima-$(CONFIG_HAVE_IMA_KEXEC) += ima_kexec.o13ima-$(CONFIG_HAVE_IMA_KEXEC) += ima_kexec.o
13obj-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o14obj-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o
security/integrity/ima/ima.h+56−4
@@ -60,6 +60,7 @@ struct ima_event_data { · 59 unmodified lines
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, · 83 unmodified lines
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 { · 41 unmodified lines
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, · 1 unmodified line
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, · 35 unmodified lines
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, · 9 unmodified lines
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, · 30 unmodified lines
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_RULES358#ifdef CONFIG_IMA_LSM_RULES
307 359
security/integrity/ima/ima_api.c+21−6
@@ -45,8 +45,8 @@ int ima_alloc_init_template(struct ima_event_data *event_data, · 44 unmodified lines
45 else45 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, · 152 unmodified lines
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, · 7 unmodified lines
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: · 60 unmodified lines
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, · 5 unmodified lines
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);
security/integrity/ima/ima_appraise.c+129−65
@@ -199,6 +199,110 @@ int ima_read_xattr(struct dentry *dentry, · 198 unmodified lines
199 return ret;199 return ret;
200}200}
201 201
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
202/*306/*
203 * ima_appraise_measurement - appraise file measurement307 * ima_appraise_measurement - appraise file measurement
204 *308 *
@@ -211,19 +315,22 @@ int ima_appraise_measurement(enum ima_hooks func, · 6 unmodified lines
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, · 16 unmodified lines
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, · 4 unmodified lines
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: · 11 unmodified lines
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) · 32 unmodified lines
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
security/integrity/ima/ima_crypto.c+9−1
@@ -268,8 +268,16 @@ static int ima_calc_file_hash_atfm(struct file *file, · 267 unmodified lines
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 first283 /* Using two buffers, and it is not the first
security/integrity/ima/ima_main.c+20−4
@@ -202,6 +202,7 @@ static int process_measurement(struct file *file, const struct cred *cred, · 201 unmodified lines
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, · 94 unmodified lines
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, · 2 unmodified lines
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: · 10 unmodified lines
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);
security/integrity/ima/ima_modsig.c+168−0
@@ -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}
security/integrity/ima/ima_policy.c+61−10
@@ -6,6 +6,9 @@ · 5 unmodified lines
6 * ima_policy.c6 * ima_policy.c
7 * - initialize default measure policy rules7 * - 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, · 479 unmodified lines
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, · 13 unmodified lines
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 else522 else
@@ -520,8 +527,6 @@ int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid, · 4 unmodified lines
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) · 315 unmodified lines
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) · 279 unmodified lines
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 else1172 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) · 47 unmodified lines
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) · 65 unmodified lines
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_POLICY1308#ifdef CONFIG_IMA_READ_POLICY
1256enum {1309enum {
1257 mask_exec = 0, mask_write, mask_read, mask_append1310 mask_exec = 0, mask_write, mask_read, mask_append
@@ -1264,12 +1317,6 @@ static const char *const mask_tokens[] = { · 6 unmodified lines
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) · 171 unmodified lines
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();
security/integrity/ima/ima_template.c+27−4
@@ -23,6 +23,7 @@ static struct ima_template_desc builtin_templates[] = { · 22 unmodified lines
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[] = { · 13 unmodified lines
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[] = { · 1 unmodified line
49 * need to be accounted for since they shouldn't be defined in the same template54 * 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, · 223 unmodified lines
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
security/integrity/ima/ima_template_lib.c+63−1
@@ -225,7 +225,8 @@ int ima_parse_buf(void *bufstartp, void *bufendp, void **bufcurp, · 224 unmodified lines
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: · 96 unmodified lines
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, · 72 unmodified lines
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}
security/integrity/ima/ima_template_lib.h+4−0
@@ -36,10 +36,14 @@ int ima_eventname_init(struct ima_event_data *event_data, · 35 unmodified lines
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 */
security/integrity/integrity.h+20−0
@@ -31,6 +31,7 @@ · 30 unmodified lines
31#define IMA_NEW_FILE 0x0400000031#define IMA_NEW_FILE 0x04000000
32#define EVM_IMMUTABLE_DIGSIG 0x0800000032#define EVM_IMMUTABLE_DIGSIG 0x08000000
33#define IMA_FAIL_UNVERIFIABLE_SIGS 0x1000000033#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, · 110 unmodified lines
147 148
148extern struct dentry *integrity_dir;149extern struct dentry *integrity_dir;
149 150
151struct modsig;
152
150#ifdef CONFIG_INTEGRITY_SIGNATURE153#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, · 8 unmodified lines
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, · 19 unmodified lines
190}200}
191#endif201#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_X509213#ifdef CONFIG_IMA_LOAD_X509
194void __init ima_load_x509(void);214void __init ima_load_x509(void);
195#else215#else
tools/testing/selftests/kexec/test_kexec_file_load.sh+34−4
@@ -37,11 +37,20 @@ is_ima_sig_required() · 36 unmodified lines
37 # sequentially. As a result, a policy rule may be defined, but37 # sequentially. As a result, a policy rule may be defined, but
38 # might not necessarily be used. This test assumes if a policy38 # 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 ]; then42 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 fi54 fi
46 return $ret55 return $ret
47}56}
@@ -84,6 +93,22 @@ check_for_imasig() · 36 unmodified lines
84 return $ret93 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() · 8 unmodified lines
98 # In secureboot mode with an architecture specific123 # 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 ]; then126 [ $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 fi129 fi
104 130
@@ -107,7 +133,8 @@ kexec_file_load_test() · 2 unmodified lines
107 log_fail "$succeed_msg (missing PE sig)"133 log_fail "$succeed_msg (missing PE sig)"
108 fi134 fi
109 135
110 if [ $ima_sig_required -eq 1 ] && [ $ima_signed -eq 0 ]; then136 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 fi139 fi
113 140
@@ -204,5 +231,8 @@ pe_signed=$? · 90 unmodified lines
204check_for_imasig231check_for_imasig
205ima_signed=$?232ima_signed=$?
206 233
234check_for_modsig
235ima_modsig=$?
236
207# Test loading the kernel image via kexec_file_load syscall237# Test loading the kernel image via kexec_file_load syscall
208kexec_file_load_test238kexec_file_load_test