Skip to content

Commit e9085e0

Browse files
nramasmimizohar
authored andcommitted
IMA: Add support to limit measuring keys
Limit measuring keys to those keys being loaded onto a given set of keyrings only and when the user id (uid) matches if uid is specified in the policy. This patch defines a new IMA policy option namely "keyrings=" that can be used to specify a set of keyrings. If this option is specified in the policy for "measure func=KEY_CHECK" then only the keys loaded onto a keyring given in the "keyrings=" option are measured. If uid is specified in the policy then the key is measured only if the current user id matches the one specified in the policy. Added a new parameter namely "keyring" (name of the keyring) to process_buffer_measurement(). The keyring name is passed to ima_get_action() to determine the required action. ima_match_rules() is updated to check keyring in the policy, if specified, for KEY_CHECK function. Signed-off-by: Lakshmi Ramasubramanian <[email protected]> Signed-off-by: Mimi Zohar <[email protected]>
1 parent cb1aa38 commit e9085e0

File tree

7 files changed

+91
-18
lines changed

7 files changed

+91
-18
lines changed

Documentation/ABI/testing/ima_policy

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ 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]
@@ -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
@@ -117,3 +120,8 @@ Description:
117120
Example of measure rule using KEY_CHECK to measure all keys:
118121

119122
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

security/integrity/ima/ima.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,8 @@ struct modsig;
208208
/* LIM API function definitions */
209209
int ima_get_action(struct inode *inode, const struct cred *cred, u32 secid,
210210
int mask, enum ima_hooks func, int *pcr,
211-
struct ima_template_desc **template_desc);
211+
struct ima_template_desc **template_desc,
212+
const char *keyring);
212213
int ima_must_measure(struct inode *inode, int mask, enum ima_hooks func);
213214
int ima_collect_measurement(struct integrity_iint_cache *iint,
214215
struct file *file, void *buf, loff_t size,
@@ -220,7 +221,7 @@ void ima_store_measurement(struct integrity_iint_cache *iint, struct file *file,
220221
struct ima_template_desc *template_desc);
221222
void process_buffer_measurement(const void *buf, int size,
222223
const char *eventname, enum ima_hooks func,
223-
int pcr);
224+
int pcr, const char *keyring);
224225
void ima_audit_measurement(struct integrity_iint_cache *iint,
225226
const unsigned char *filename);
226227
int ima_alloc_init_template(struct ima_event_data *event_data,
@@ -235,7 +236,8 @@ const char *ima_d_path(const struct path *path, char **pathbuf, char *filename);
235236
/* IMA policy related functions */
236237
int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
237238
enum ima_hooks func, int mask, int flags, int *pcr,
238-
struct ima_template_desc **template_desc);
239+
struct ima_template_desc **template_desc,
240+
const char *keyring);
239241
void ima_init_policy(void);
240242
void ima_update_policy(void);
241243
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;

security/integrity/ima/ima_asymmetric_keys.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,13 @@ void ima_post_key_create_or_update(struct key *keyring, struct key *key,
4646
* parameter to process_buffer_measurement() and is set
4747
* in the "eventname" field in ima_event_data for
4848
* 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.
4954
*/
5055
process_buffer_measurement(payload, payload_len,
51-
keyring->description, KEY_CHECK, 0);
56+
keyring->description, KEY_CHECK, 0,
57+
keyring->description);
5258
}

security/integrity/ima/ima_main.c

Lines changed: 5 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;
@@ -668,7 +669,7 @@ void process_buffer_measurement(const void *buf, int size,
668669
if (func) {
669670
security_task_getsecid(current, &secid);
670671
action = ima_get_action(NULL, current_cred(), secid, 0, func,
671-
&pcr, &template);
672+
&pcr, &template, keyring);
672673
if (!(action & IMA_MEASURE))
673674
return;
674675
}
@@ -721,7 +722,7 @@ void ima_kexec_cmdline(const void *buf, int size)
721722
{
722723
if (buf && size != 0)
723724
process_buffer_measurement(buf, size, "kexec-cmdline",
724-
KEXEC_CMDLINE, 0);
725+
KEXEC_CMDLINE, 0, NULL);
725726
}
726727

727728
static int __init init_ima(void)

security/integrity/ima/ima_policy.c

Lines changed: 58 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ struct ima_rule_entry {
7979
int type; /* audit type */
8080
} lsm[MAX_LSM_RULES];
8181
char *fsname;
82+
char *keyrings; /* Measure keys added to these keyrings */
8283
struct ima_template_desc *template;
8384
};
8485

@@ -356,6 +357,50 @@ int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event,
356357
return NOTIFY_OK;
357358
}
358359

360+
/**
361+
* ima_match_keyring - determine whether the keyring matches the measure rule
362+
* @rule: a pointer to a rule
363+
* @keyring: name of the keyring to match against the measure rule
364+
* @cred: a pointer to a credentials structure for user validation
365+
*
366+
* Returns true if keyring matches one in the rule, false otherwise.
367+
*/
368+
static bool ima_match_keyring(struct ima_rule_entry *rule,
369+
const char *keyring, const struct cred *cred)
370+
{
371+
char *keyrings, *next_keyring, *keyrings_ptr;
372+
bool matched = false;
373+
374+
if ((rule->flags & IMA_UID) && !rule->uid_op(cred->uid, rule->uid))
375+
return false;
376+
377+
if (!rule->keyrings)
378+
return true;
379+
380+
if (!keyring)
381+
return false;
382+
383+
keyrings = kstrdup(rule->keyrings, GFP_KERNEL);
384+
if (!keyrings)
385+
return false;
386+
387+
/*
388+
* "keyrings=" is specified in the policy in the format below:
389+
* keyrings=.builtin_trusted_keys|.ima|.evm
390+
*/
391+
keyrings_ptr = keyrings;
392+
while ((next_keyring = strsep(&keyrings_ptr, "|")) != NULL) {
393+
if (!strcmp(next_keyring, keyring)) {
394+
matched = true;
395+
break;
396+
}
397+
}
398+
399+
kfree(keyrings);
400+
401+
return matched;
402+
}
403+
359404
/**
360405
* ima_match_rules - determine whether an inode matches the measure rule.
361406
* @rule: a pointer to a rule
@@ -364,18 +409,23 @@ int ima_lsm_policy_change(struct notifier_block *nb, unsigned long event,
364409
* @secid: the secid of the task to be validated
365410
* @func: LIM hook identifier
366411
* @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
412+
* @keyring: keyring name to check in policy for KEY_CHECK func
367413
*
368414
* Returns true on rule match, false on failure.
369415
*/
370416
static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
371417
const struct cred *cred, u32 secid,
372-
enum ima_hooks func, int mask)
418+
enum ima_hooks func, int mask,
419+
const char *keyring)
373420
{
374421
int i;
375422

376423
if ((func == KEXEC_CMDLINE) || (func == KEY_CHECK)) {
377-
if ((rule->flags & IMA_FUNC) && (rule->func == func))
424+
if ((rule->flags & IMA_FUNC) && (rule->func == func)) {
425+
if (func == KEY_CHECK)
426+
return ima_match_keyring(rule, keyring, cred);
378427
return true;
428+
}
379429
return false;
380430
}
381431
if ((rule->flags & IMA_FUNC) &&
@@ -479,6 +529,8 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
479529
* @mask: requested action (MAY_READ | MAY_WRITE | MAY_APPEND | MAY_EXEC)
480530
* @pcr: set the pcr to extend
481531
* @template_desc: the template that should be used for this rule
532+
* @keyring: the keyring name, if given, to be used to check in the policy.
533+
* keyring can be NULL if func is anything other than KEY_CHECK.
482534
*
483535
* Measure decision based on func/mask/fsmagic and LSM(subj/obj/type)
484536
* conditions.
@@ -489,7 +541,8 @@ static int get_subaction(struct ima_rule_entry *rule, enum ima_hooks func)
489541
*/
490542
int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
491543
enum ima_hooks func, int mask, int flags, int *pcr,
492-
struct ima_template_desc **template_desc)
544+
struct ima_template_desc **template_desc,
545+
const char *keyring)
493546
{
494547
struct ima_rule_entry *entry;
495548
int action = 0, actmask = flags | (flags << 1);
@@ -503,7 +556,8 @@ int ima_match_policy(struct inode *inode, const struct cred *cred, u32 secid,
503556
if (!(entry->action & actmask))
504557
continue;
505558

506-
if (!ima_match_rules(entry, inode, cred, secid, func, mask))
559+
if (!ima_match_rules(entry, inode, cred, secid, func, mask,
560+
keyring))
507561
continue;
508562

509563
action |= entry->flags & IMA_ACTION_FLAGS;

0 commit comments

Comments
 (0)