Skip to content

Commit 73a0bff

Browse files
committed
Merge branch 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity
Pull IMA updates from Mimi Zohar: "Two new features - measuring certificates and querying IMA for a file hash - and three bug fixes: - Measuring certificates is like the rest of IMA, based on policy, but requires loading a custom policy. Certificates loaded onto a keyring, for example during early boot, before a custom policy has been loaded, are queued and only processed after loading the custom policy. - IMA calculates and caches files hashes. Other kernel subsystems, and possibly kernel modules, are interested in accessing these cached file hashes. The bug fixes prevent classifying a file short read (e.g. shutdown) as an invalid file signature, add a missing blank when displaying the securityfs policy rules containing LSM labels, and, lastly, fix the handling of the IMA policy information for unknown LSM labels" * 'next-integrity' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity: IMA: Defined delayed workqueue to free the queued keys IMA: Call workqueue functions to measure queued keys IMA: Define workqueue for early boot key measurements IMA: pre-allocate buffer to hold keyrings string ima: ima/lsm policy rule loading logic bug fixes ima: add the ability to query the cached hash of a given file ima: Add a space after printing LSM rules for readability IMA: fix measuring asymmetric keys Kconfig IMA: Read keyrings= option from the IMA policy IMA: Add support to limit measuring keys KEYS: Call the IMA hook to measure keys IMA: Define an IMA hook to measure keys IMA: Add KEY_CHECK func to measure keys IMA: Check IMA policy flag ima: avoid appraise error for hash calc interrupt
2 parents 2cf64d7 + d54e17b commit 73a0bff

File tree

14 files changed

+540
-40
lines changed

14 files changed

+540
-40
lines changed

Documentation/ABI/testing/ima_policy

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ Description:
2525
lsm: [[subj_user=] [subj_role=] [subj_type=]
2626
[obj_user=] [obj_role=] [obj_type=]]
2727
option: [[appraise_type=]] [template=] [permit_directio]
28-
[appraise_flag=]
28+
[appraise_flag=] [keyrings=]
2929
base: func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK]
3030
[FIRMWARE_CHECK]
3131
[KEXEC_KERNEL_CHECK] [KEXEC_INITRAMFS_CHECK]
32-
[KEXEC_CMDLINE]
32+
[KEXEC_CMDLINE] [KEY_CHECK]
3333
mask:= [[^]MAY_READ] [[^]MAY_WRITE] [[^]MAY_APPEND]
3434
[[^]MAY_EXEC]
3535
fsmagic:= hex value
@@ -42,6 +42,9 @@ Description:
4242
appraise_flag:= [check_blacklist]
4343
Currently, blacklist check is only for files signed with appended
4444
signature.
45+
keyrings:= list of keyrings
46+
(eg, .builtin_trusted_keys|.ima). Only valid
47+
when action is "measure" and func is KEY_CHECK.
4548
template:= name of a defined IMA template type
4649
(eg, ima-ng). Only valid when action is "measure".
4750
pcr:= decimal value
@@ -113,3 +116,12 @@ Description:
113116
Example of appraise rule allowing modsig appended signatures:
114117

115118
appraise func=KEXEC_KERNEL_CHECK appraise_type=imasig|modsig
119+
120+
Example of measure rule using KEY_CHECK to measure all keys:
121+
122+
measure func=KEY_CHECK
123+
124+
Example of measure rule using KEY_CHECK to only measure
125+
keys added to .builtin_trusted_keys or .ima keyring:
126+
127+
measure func=KEY_CHECK keyrings=.builtin_trusted_keys|.ima

include/linux/ima.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ extern int ima_read_file(struct file *file, enum kernel_read_file_id id);
2323
extern int ima_post_read_file(struct file *file, void *buf, loff_t size,
2424
enum kernel_read_file_id id);
2525
extern void ima_post_path_mknod(struct dentry *dentry);
26+
extern int ima_file_hash(struct file *file, char *buf, size_t buf_size);
2627
extern void ima_kexec_cmdline(const void *buf, int size);
2728

2829
#ifdef CONFIG_IMA_KEXEC
@@ -91,6 +92,11 @@ static inline void ima_post_path_mknod(struct dentry *dentry)
9192
return;
9293
}
9394

95+
static inline int ima_file_hash(struct file *file, char *buf, size_t buf_size)
96+
{
97+
return -EOPNOTSUPP;
98+
}
99+
94100
static inline void ima_kexec_cmdline(const void *buf, int size) {}
95101
#endif /* CONFIG_IMA */
96102

@@ -101,6 +107,20 @@ static inline void ima_add_kexec_buffer(struct kimage *image)
101107
{}
102108
#endif
103109

110+
#ifdef CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS
111+
extern void ima_post_key_create_or_update(struct key *keyring,
112+
struct key *key,
113+
const void *payload, size_t plen,
114+
unsigned long flags, bool create);
115+
#else
116+
static inline void ima_post_key_create_or_update(struct key *keyring,
117+
struct key *key,
118+
const void *payload,
119+
size_t plen,
120+
unsigned long flags,
121+
bool create) {}
122+
#endif /* CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS */
123+
104124
#ifdef CONFIG_IMA_APPRAISE
105125
extern bool is_ima_appraise_enabled(void);
106126
extern void ima_inode_post_setattr(struct dentry *dentry);

security/integrity/ima/Kconfig

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -310,3 +310,15 @@ config IMA_APPRAISE_SIGNED_INIT
310310
default n
311311
help
312312
This option requires user-space init to be signed.
313+
314+
config IMA_MEASURE_ASYMMETRIC_KEYS
315+
bool
316+
depends on IMA
317+
depends on ASYMMETRIC_PUBLIC_KEY_SUBTYPE=y
318+
default y
319+
320+
config IMA_QUEUE_EARLY_BOOT_KEYS
321+
bool
322+
depends on IMA_MEASURE_ASYMMETRIC_KEYS
323+
depends on SYSTEM_TRUSTED_KEYRING
324+
default y

security/integrity/ima/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,5 @@ ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o
1212
ima-$(CONFIG_IMA_APPRAISE_MODSIG) += ima_modsig.o
1313
ima-$(CONFIG_HAVE_IMA_KEXEC) += ima_kexec.o
1414
obj-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o
15+
obj-$(CONFIG_IMA_MEASURE_ASYMMETRIC_KEYS) += ima_asymmetric_keys.o
16+
obj-$(CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS) += ima_queue_keys.o

security/integrity/ima/ima.h

Lines changed: 30 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ static inline unsigned long ima_hash_key(u8 *digest)
193193
hook(KEXEC_INITRAMFS_CHECK) \
194194
hook(POLICY_CHECK) \
195195
hook(KEXEC_CMDLINE) \
196+
hook(KEY_CHECK) \
196197
hook(MAX_CHECK)
197198
#define __ima_hook_enumify(ENUM) ENUM,
198199

@@ -204,10 +205,35 @@ extern const char *const func_tokens[];
204205

205206
struct modsig;
206207

208+
#ifdef CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS
209+
/*
210+
* To track keys that need to be measured.
211+
*/
212+
struct ima_key_entry {
213+
struct list_head list;
214+
void *payload;
215+
size_t payload_len;
216+
char *keyring_name;
217+
};
218+
void ima_init_key_queue(void);
219+
bool ima_should_queue_key(void);
220+
bool ima_queue_key(struct key *keyring, const void *payload,
221+
size_t payload_len);
222+
void ima_process_queued_keys(void);
223+
#else
224+
static inline void ima_init_key_queue(void) {}
225+
static inline bool ima_should_queue_key(void) { return false; }
226+
static inline bool ima_queue_key(struct key *keyring,
227+
const void *payload,
228+
size_t payload_len) { return false; }
229+
static inline void ima_process_queued_keys(void) {}
230+
#endif /* CONFIG_IMA_QUEUE_EARLY_BOOT_KEYS */
231+
207232
/* LIM API function definitions */
208233
int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
209234
int mask, enum ima_hooks func, int *pcr,
210-
struct ima_template_desc **template_desc);
235+
struct ima_template_desc **template_desc,
236+
const char *keyring);
211237
int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func);
212238
int ima_collect_measurement(struct integrity_iint_cache *iint,
213239
struct file *file, void *buf, loff_t size,
@@ -219,7 +245,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
219245
struct ima_template_desc *template_desc);
220246
void process_buffer_measurement(const void *buf, int size,
221247
const char *eventname, enum ima_hooks func,
222-
int pcr);
248+
int pcr, const char *keyring);
223249
void ima_audit_measurement(struct integrity_iint_cache *iint,
224250
const unsigned char *filename);
225251
int ima_alloc_init_template(struct ima_event_data *event_data,
@@ -234,7 +260,8 @@ const char *ima_d_path(const struct path *path, char **pathbuf, char *filename);
234260
/* IMA policy related functions */
235261
int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
236262
enum ima_hooks func, int mask, int flags, int *pcr,
237-
struct ima_template_desc **template_desc);
263+
struct ima_template_desc **template_desc,
264+
const char *keyring);
238265
void ima_init_policy(void);
239266
void ima_update_policy(void);
240267
void ima_update_policy_flag(void);

security/integrity/ima/ima_api.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -169,12 +169,13 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
169169
* @func: caller identifier
170170
* @pcr: pointer filled in if matched measure policy sets pcr=
171171
* @template_desc: pointer filled in if matched measure policy sets template=
172+
* @keyring: keyring name used to determine the action
172173
*
173174
* The policy is defined in terms of keypairs:
174175
* subj=, obj=, type=, func=, mask=, fsmagic=
175176
* subj,obj, and type: are LSM specific.
176177
* func: FILE_CHECK | BPRM_CHECK | CREDS_CHECK | MMAP_CHECK | MODULE_CHECK
177-
* | KEXEC_CMDLINE
178+
* | KEXEC_CMDLINE | KEY_CHECK
178179
* mask: contains the permission mask
179180
* fsmagic: hex value
180181
*
@@ -183,14 +184,15 @@ void ima_add_violation(struct file *file, const unsigned char *filename,
183184
*/
184185
int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
185186
int mask, enum ima_hooks func, int *pcr,
186-
struct ima_template_desc **template_desc)
187+
struct ima_template_desc **template_desc,
188+
const char *keyring)
187189
{
188190
int flags = IMA_MEASURE | IMA_AUDIT | IMA_APPRAISE | IMA_HASH;
189191

190192
flags &= ima_policy_flag;
191193

192194
return ima_match_policy(inode, cred, secid, func, mask, flags, pcr,
193-
template_desc);
195+
template_desc, keyring);
194196
}
195197

196198
/*

security/integrity/ima/ima_appraise.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ int ima_must_appraise(struct inode *inode, int mask, enum ima_hooks func)
5555

5656
security_task_getsecid(current, &secid);
5757
return ima_match_policy(inode, current_cred(), secid, func, mask,
58-
IMA_APPRAISE | IMA_HASH, NULL, NULL);
58+
IMA_APPRAISE | IMA_HASH, NULL, NULL, NULL);
5959
}
6060

6161
static int ima_fix_xattr(struct dentry *dentry,
@@ -330,7 +330,7 @@ int ima_check_blacklist(struct integrity_iint_cache *iint,
330330
if ((rc == -EPERM) && (iint->flags & IMA_MEASURE))
331331
process_buffer_measurement(digest, digestsize,
332332
"blacklisted-hash", NONE,
333-
pcr);
333+
pcr, NULL);
334334
}
335335

336336
return rc;
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// SPDX-License-Identifier: GPL-2.0+
2+
/*
3+
* Copyright (C) 2019 Microsoft Corporation
4+
*
5+
* Author: Lakshmi Ramasubramanian ([email protected])
6+
*
7+
* File: ima_asymmetric_keys.c
8+
* Defines an IMA hook to measure asymmetric keys on key
9+
* create or update.
10+
*/
11+
12+
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
13+
14+
#include <keys/asymmetric-type.h>
15+
#include "ima.h"
16+
17+
/**
18+
* ima_post_key_create_or_update - measure asymmetric keys
19+
* @keyring: keyring to which the key is linked to
20+
* @key: created or updated key
21+
* @payload: The data used to instantiate or update the key.
22+
* @payload_len: The length of @payload.
23+
* @flags: key flags
24+
* @create: flag indicating whether the key was created or updated
25+
*
26+
* Keys can only be measured, not appraised.
27+
* The payload data used to instantiate or update the key is measured.
28+
*/
29+
void ima_post_key_create_or_update(struct key *keyring, struct key *key,
30+
const void *payload, size_t payload_len,
31+
unsigned long flags, bool create)
32+
{
33+
bool queued = false;
34+
35+
/* Only asymmetric keys are handled by this hook. */
36+
if (key->type != &key_type_asymmetric)
37+
return;
38+
39+
if (!payload || (payload_len == 0))
40+
return;
41+
42+
if (ima_should_queue_key())
43+
queued = ima_queue_key(keyring, payload, payload_len);
44+
45+
if (queued)
46+
return;
47+
48+
/*
49+
* keyring->description points to the name of the keyring
50+
* (such as ".builtin_trusted_keys", ".ima", etc.) to
51+
* which the given key is linked to.
52+
*
53+
* The name of the keyring is passed in the "eventname"
54+
* parameter to process_buffer_measurement() and is set
55+
* in the "eventname" field in ima_event_data for
56+
* the key measurement IMA event.
57+
*
58+
* The name of the keyring is also passed in the "keyring"
59+
* parameter to process_buffer_measurement() to check
60+
* if the IMA policy is configured to measure a key linked
61+
* to the given keyring.
62+
*/
63+
process_buffer_measurement(payload, payload_len,
64+
keyring->description, KEY_CHECK, 0,
65+
keyring->description);
66+
}

security/integrity/ima/ima_crypto.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,8 +362,10 @@ static int ima_calc_file_hash_tfm(struct file *file,
362362
rc = rbuf_len;
363363
break;
364364
}
365-
if (rbuf_len == 0)
365+
if (rbuf_len == 0) { /* unexpected EOF */
366+
rc = -EINVAL;
366367
break;
368+
}
367369
offset += rbuf_len;
368370

369371
rc = crypto_shash_update(shash, rbuf, rbuf_len);

security/integrity/ima/ima_init.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,5 +131,11 @@ int __init ima_init(void)
131131

132132
ima_init_policy();
133133

134-
return ima_fs_init();
134+
rc = ima_fs_init();
135+
if (rc != 0)
136+
return rc;
137+
138+
ima_init_key_queue();
139+
140+
return rc;
135141
}

0 commit comments

Comments
 (0)