Skip to content

Commit f47825c

Browse files
committed
Merge branch 'next-integrity.measure-keys' into next-integrity
From "KEYS: Measure keys when they are created or updated" cover letter: Keys created or updated in the system are currently not measured. Therefore an attestation service, for instance, would not be able to attest whether or not the trusted keys keyring(s), for instance, contain only known good (trusted) keys. IMA measures system files, command line arguments passed to kexec, boot aggregate, etc. It can be used to measure keys as well. But there is no mechanism available in the kernel for IMA to know when a key is created or updated. This change aims to address measuring keys created or updated in the system. To achieve the above the following changes have been made: - Added a new IMA hook namely, ima_post_key_create_or_update, which measures the key. This IMA hook is called from key_create_or_update function. The key measurement can be controlled through IMA policy. A new IMA policy function KEY_CHECK has been added to measure keys. "keyrings=" option can be specified for KEY_CHECK to limit measuring the keys loaded onto the specified keyrings only. uid can be specified to further restrict key measurement for keys created by specific user. # measure keys loaded onto any keyring measure func=KEY_CHECK # measure keys loaded onto the IMA keyring only for root user measure func=KEY_CHECK uid=0 keyring=".ima" # measure keys on the BUILTIN and IMA keyrings into a different PCR measure func=KEY_CHECK keyring=".builtin_trusted_keys|.ima" pcr=11
2 parents 96c9e1d + 2b60c0e commit f47825c

File tree

10 files changed

+207
-20
lines changed

10 files changed

+207
-20
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: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,20 @@ static inline void ima_add_kexec_buffer(struct kimage *image)
101101
{}
102102
#endif
103103

104+
#if defined(CONFIG_IMA) && defined(CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE)
105+
extern void ima_post_key_create_or_update(struct key *keyring,
106+
struct key *key,
107+
const void *payload, size_t plen,
108+
unsigned long flags, bool create);
109+
#else
110+
static inline void ima_post_key_create_or_update(struct key *keyring,
111+
struct key *key,
112+
const void *payload,
113+
size_t plen,
114+
unsigned long flags,
115+
bool create) {}
116+
#endif /* CONFIG_IMA && CONFIG_ASYMMETRIC_PUBLIC_KEY_SUBTYPE */
117+
104118
#ifdef CONFIG_IMA_APPRAISE
105119
extern bool is_ima_appraise_enabled(void);
106120
extern void ima_inode_post_setattr(struct dentry *dentry);

security/integrity/ima/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,3 +12,4 @@ 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_ASYMMETRIC_PUBLIC_KEY_SUBTYPE) += ima_asymmetric_keys.o

security/integrity/ima/ima.h

Lines changed: 6 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

@@ -207,7 +208,8 @@ struct modsig;
207208
/* LIM API function definitions */
208209
int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
209210
int mask, enum ima_hooks func, int *pcr,
210-
struct ima_template_desc **template_desc);
211+
struct ima_template_desc **template_desc,
212+
const char *keyring);
211213
int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func);
212214
int ima_collect_measurement(struct integrity_iint_cache *iint,
213215
struct file *file, void *buf, loff_t size,
@@ -219,7 +221,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
219221
struct ima_template_desc *template_desc);
220222
void process_buffer_measurement(const void *buf, int size,
221223
const char *eventname, enum ima_hooks func,
222-
int pcr);
224+
int pcr, const char *keyring);
223225
void ima_audit_measurement(struct integrity_iint_cache *iint,
224226
const unsigned char *filename);
225227
int ima_alloc_init_template(struct ima_event_data *event_data,
@@ -234,7 +236,8 @@ const char *ima_d_path(const struct path *path, char **pathbuf, char *filename);
234236
/* IMA policy related functions */
235237
int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
236238
enum ima_hooks func, int mask, int flags, int *pcr,
237-
struct ima_template_desc **template_desc);
239+
struct ima_template_desc **template_desc,
240+
const char *keyring);
238241
void ima_init_policy(void);
239242
void ima_update_policy(void);
240243
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: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
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+
/* Only asymmetric keys are handled by this hook. */
34+
if (key->type != &key_type_asymmetric)
35+
return;
36+
37+
if (!payload || (payload_len == 0))
38+
return;
39+
40+
/*
41+
* keyring->description points to the name of the keyring
42+
* (such as ".builtin_trusted_keys", ".ima", etc.) to
43+
* which the given key is linked to.
44+
*
45+
* The name of the keyring is passed in the "eventname"
46+
* parameter to process_buffer_measurement() and is set
47+
* in the "eventname" field in ima_event_data for
48+
* the key measurement IMA event.
49+
*
50+
* The name of the keyring is also passed in the "keyring"
51+
* parameter to process_buffer_measurement() to check
52+
* if the IMA policy is configured to measure a key linked
53+
* to the given keyring.
54+
*/
55+
process_buffer_measurement(payload, payload_len,
56+
keyring->description, KEY_CHECK, 0,
57+
keyring->description);
58+
}

security/integrity/ima/ima_main.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ static int process_measurement(struct file *file, const struct cred *cred,
215215
* Included is the appraise submask.
216216
*/
217217
action = ima_get_action(inode, cred, secid, mask, func, &pcr,
218-
&template_desc);
218+
&template_desc, NULL);
219219
violation_check = ((func == FILE_CHECK || func == MMAP_CHECK) &&
220220
(ima_policy_flag & IMA_MEASURE));
221221
if (!action && !violation_check)
@@ -632,12 +632,13 @@ int ima_load_data(enum kernel_load_data_id id)
632632
* @eventname: event name to be used for the buffer entry.
633633
* @func: IMA hook
634634
* @pcr: pcr to extend the measurement
635+
* @keyring: keyring name to determine the action to be performed
635636
*
636637
* Based on policy, the buffer is measured into the ima log.
637638
*/
638639
void process_buffer_measurement(const void *buf, int size,
639640
const char *eventname, enum ima_hooks func,
640-
int pcr)
641+
int pcr, const char *keyring)
641642
{
642643
int ret = 0;
643644
struct ima_template_entry *entry = NULL;
@@ -655,6 +656,9 @@ void process_buffer_measurement(const void *buf, int size,
655656
int action = 0;
656657
u32 secid;
657658

659+
if (!ima_policy_flag)
660+
return;
661+
658662
/*
659663
* Both LSM hooks and auxilary based buffer measurements are
660664
* based on policy. To avoid code duplication, differentiate
@@ -665,7 +669,7 @@ void process_buffer_measurement(const void *buf, int size,
665669
if (func) {
666670
security_task_getsecid(current, &secid);
667671
action = ima_get_action(NULL, current_cred(), secid, 0, func,
668-
&pcr, &template);
672+
&pcr, &template, keyring);
669673
if (!(action & IMA_MEASURE))
670674
return;
671675
}
@@ -718,7 +722,7 @@ void ima_kexec_cmdline(const void *buf, int size)
718722
{
719723
if (buf && size != 0)
720724
process_buffer_measurement(buf, size, "kexec-cmdline",
721-
KEXEC_CMDLINE, 0);
725+
KEXEC_CMDLINE, 0, NULL);
722726
}
723727

724728
static int __init init_ima(void)

0 commit comments

Comments
 (0)