aboutsummaryrefslogtreecommitdiffstats
path: root/security/integrity/ima/ima_policy.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/integrity/ima/ima_policy.c')
-rw-r--r--security/integrity/ima/ima_policy.c138
1 files changed, 124 insertions, 14 deletions
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index 479fca940bb5..b27535a13a79 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -16,6 +16,7 @@
16#include <linux/magic.h> 16#include <linux/magic.h>
17#include <linux/parser.h> 17#include <linux/parser.h>
18#include <linux/slab.h> 18#include <linux/slab.h>
19#include <linux/genhd.h>
19 20
20#include "ima.h" 21#include "ima.h"
21 22
@@ -25,6 +26,7 @@
25#define IMA_FSMAGIC 0x0004 26#define IMA_FSMAGIC 0x0004
26#define IMA_UID 0x0008 27#define IMA_UID 0x0008
27#define IMA_FOWNER 0x0010 28#define IMA_FOWNER 0x0010
29#define IMA_FSUUID 0x0020
28 30
29#define UNKNOWN 0 31#define UNKNOWN 0
30#define MEASURE 0x0001 /* same as IMA_MEASURE */ 32#define MEASURE 0x0001 /* same as IMA_MEASURE */
@@ -45,10 +47,12 @@ struct ima_rule_entry {
45 enum ima_hooks func; 47 enum ima_hooks func;
46 int mask; 48 int mask;
47 unsigned long fsmagic; 49 unsigned long fsmagic;
50 u8 fsuuid[16];
48 kuid_t uid; 51 kuid_t uid;
49 kuid_t fowner; 52 kuid_t fowner;
50 struct { 53 struct {
51 void *rule; /* LSM file metadata specific */ 54 void *rule; /* LSM file metadata specific */
55 void *args_p; /* audit value */
52 int type; /* audit type */ 56 int type; /* audit type */
53 } lsm[MAX_LSM_RULES]; 57 } lsm[MAX_LSM_RULES];
54}; 58};
@@ -74,7 +78,7 @@ static struct ima_rule_entry default_rules[] = {
74 {.action = DONT_MEASURE,.fsmagic = BINFMTFS_MAGIC,.flags = IMA_FSMAGIC}, 78 {.action = DONT_MEASURE,.fsmagic = BINFMTFS_MAGIC,.flags = IMA_FSMAGIC},
75 {.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC}, 79 {.action = DONT_MEASURE,.fsmagic = SECURITYFS_MAGIC,.flags = IMA_FSMAGIC},
76 {.action = DONT_MEASURE,.fsmagic = SELINUX_MAGIC,.flags = IMA_FSMAGIC}, 80 {.action = DONT_MEASURE,.fsmagic = SELINUX_MAGIC,.flags = IMA_FSMAGIC},
77 {.action = MEASURE,.func = FILE_MMAP,.mask = MAY_EXEC, 81 {.action = MEASURE,.func = MMAP_CHECK,.mask = MAY_EXEC,
78 .flags = IMA_FUNC | IMA_MASK}, 82 .flags = IMA_FUNC | IMA_MASK},
79 {.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC, 83 {.action = MEASURE,.func = BPRM_CHECK,.mask = MAY_EXEC,
80 .flags = IMA_FUNC | IMA_MASK}, 84 .flags = IMA_FUNC | IMA_MASK},
@@ -119,6 +123,35 @@ static int __init default_appraise_policy_setup(char *str)
119} 123}
120__setup("ima_appraise_tcb", default_appraise_policy_setup); 124__setup("ima_appraise_tcb", default_appraise_policy_setup);
121 125
126/*
127 * Although the IMA policy does not change, the LSM policy can be
128 * reloaded, leaving the IMA LSM based rules referring to the old,
129 * stale LSM policy.
130 *
131 * Update the IMA LSM based rules to reflect the reloaded LSM policy.
132 * We assume the rules still exist; and BUG_ON() if they don't.
133 */
134static void ima_lsm_update_rules(void)
135{
136 struct ima_rule_entry *entry, *tmp;
137 int result;
138 int i;
139
140 mutex_lock(&ima_rules_mutex);
141 list_for_each_entry_safe(entry, tmp, &ima_policy_rules, list) {
142 for (i = 0; i < MAX_LSM_RULES; i++) {
143 if (!entry->lsm[i].rule)
144 continue;
145 result = security_filter_rule_init(entry->lsm[i].type,
146 Audit_equal,
147 entry->lsm[i].args_p,
148 &entry->lsm[i].rule);
149 BUG_ON(!entry->lsm[i].rule);
150 }
151 }
152 mutex_unlock(&ima_rules_mutex);
153}
154
122/** 155/**
123 * ima_match_rules - determine whether an inode matches the measure rule. 156 * ima_match_rules - determine whether an inode matches the measure rule.
124 * @rule: a pointer to a rule 157 * @rule: a pointer to a rule
@@ -142,6 +175,9 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
142 if ((rule->flags & IMA_FSMAGIC) 175 if ((rule->flags & IMA_FSMAGIC)
143 && rule->fsmagic != inode->i_sb->s_magic) 176 && rule->fsmagic != inode->i_sb->s_magic)
144 return false; 177 return false;
178 if ((rule->flags & IMA_FSUUID) &&
179 memcmp(rule->fsuuid, inode->i_sb->s_uuid, sizeof(rule->fsuuid)))
180 return false;
145 if ((rule->flags & IMA_UID) && !uid_eq(rule->uid, cred->uid)) 181 if ((rule->flags & IMA_UID) && !uid_eq(rule->uid, cred->uid))
146 return false; 182 return false;
147 if ((rule->flags & IMA_FOWNER) && !uid_eq(rule->fowner, inode->i_uid)) 183 if ((rule->flags & IMA_FOWNER) && !uid_eq(rule->fowner, inode->i_uid))
@@ -149,10 +185,11 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
149 for (i = 0; i < MAX_LSM_RULES; i++) { 185 for (i = 0; i < MAX_LSM_RULES; i++) {
150 int rc = 0; 186 int rc = 0;
151 u32 osid, sid; 187 u32 osid, sid;
188 int retried = 0;
152 189
153 if (!rule->lsm[i].rule) 190 if (!rule->lsm[i].rule)
154 continue; 191 continue;
155 192retry:
156 switch (i) { 193 switch (i) {
157 case LSM_OBJ_USER: 194 case LSM_OBJ_USER:
158 case LSM_OBJ_ROLE: 195 case LSM_OBJ_ROLE:
@@ -176,12 +213,39 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
176 default: 213 default:
177 break; 214 break;
178 } 215 }
216 if ((rc < 0) && (!retried)) {
217 retried = 1;
218 ima_lsm_update_rules();
219 goto retry;
220 }
179 if (!rc) 221 if (!rc)
180 return false; 222 return false;
181 } 223 }
182 return true; 224 return true;
183} 225}
184 226
227/*
228 * In addition to knowing that we need to appraise the file in general,
229 * we need to differentiate between calling hooks, for hook specific rules.
230 */
231static int get_subaction(struct ima_rule_entry *rule, int func)
232{
233 if (!(rule->flags & IMA_FUNC))
234 return IMA_FILE_APPRAISE;
235
236 switch(func) {
237 case MMAP_CHECK:
238 return IMA_MMAP_APPRAISE;
239 case BPRM_CHECK:
240 return IMA_BPRM_APPRAISE;
241 case MODULE_CHECK:
242 return IMA_MODULE_APPRAISE;
243 case FILE_CHECK:
244 default:
245 return IMA_FILE_APPRAISE;
246 }
247}
248
185/** 249/**
186 * ima_match_policy - decision based on LSM and other conditions 250 * ima_match_policy - decision based on LSM and other conditions
187 * @inode: pointer to an inode for which the policy decision is being made 251 * @inode: pointer to an inode for which the policy decision is being made
@@ -209,7 +273,12 @@ int ima_match_policy(struct inode *inode, enum ima_hooks func, int mask,
209 if (!ima_match_rules(entry, inode, func, mask)) 273 if (!ima_match_rules(entry, inode, func, mask))
210 continue; 274 continue;
211 275
276 action |= entry->flags & IMA_ACTION_FLAGS;
277
212 action |= entry->action & IMA_DO_MASK; 278 action |= entry->action & IMA_DO_MASK;
279 if (entry->action & IMA_APPRAISE)
280 action |= get_subaction(entry, func);
281
213 if (entry->action & IMA_DO_MASK) 282 if (entry->action & IMA_DO_MASK)
214 actmask &= ~(entry->action | entry->action << 1); 283 actmask &= ~(entry->action | entry->action << 1);
215 else 284 else
@@ -282,7 +351,8 @@ enum {
282 Opt_audit, 351 Opt_audit,
283 Opt_obj_user, Opt_obj_role, Opt_obj_type, 352 Opt_obj_user, Opt_obj_role, Opt_obj_type,
284 Opt_subj_user, Opt_subj_role, Opt_subj_type, 353 Opt_subj_user, Opt_subj_role, Opt_subj_type,
285 Opt_func, Opt_mask, Opt_fsmagic, Opt_uid, Opt_fowner 354 Opt_func, Opt_mask, Opt_fsmagic, Opt_uid, Opt_fowner,
355 Opt_appraise_type, Opt_fsuuid
286}; 356};
287 357
288static match_table_t policy_tokens = { 358static match_table_t policy_tokens = {
@@ -300,25 +370,35 @@ static match_table_t policy_tokens = {
300 {Opt_func, "func=%s"}, 370 {Opt_func, "func=%s"},
301 {Opt_mask, "mask=%s"}, 371 {Opt_mask, "mask=%s"},
302 {Opt_fsmagic, "fsmagic=%s"}, 372 {Opt_fsmagic, "fsmagic=%s"},
373 {Opt_fsuuid, "fsuuid=%s"},
303 {Opt_uid, "uid=%s"}, 374 {Opt_uid, "uid=%s"},
304 {Opt_fowner, "fowner=%s"}, 375 {Opt_fowner, "fowner=%s"},
376 {Opt_appraise_type, "appraise_type=%s"},
305 {Opt_err, NULL} 377 {Opt_err, NULL}
306}; 378};
307 379
308static int ima_lsm_rule_init(struct ima_rule_entry *entry, 380static int ima_lsm_rule_init(struct ima_rule_entry *entry,
309 char *args, int lsm_rule, int audit_type) 381 substring_t *args, int lsm_rule, int audit_type)
310{ 382{
311 int result; 383 int result;
312 384
313 if (entry->lsm[lsm_rule].rule) 385 if (entry->lsm[lsm_rule].rule)
314 return -EINVAL; 386 return -EINVAL;
315 387
388 entry->lsm[lsm_rule].args_p = match_strdup(args);
389 if (!entry->lsm[lsm_rule].args_p)
390 return -ENOMEM;
391
316 entry->lsm[lsm_rule].type = audit_type; 392 entry->lsm[lsm_rule].type = audit_type;
317 result = security_filter_rule_init(entry->lsm[lsm_rule].type, 393 result = security_filter_rule_init(entry->lsm[lsm_rule].type,
318 Audit_equal, args, 394 Audit_equal,
395 entry->lsm[lsm_rule].args_p,
319 &entry->lsm[lsm_rule].rule); 396 &entry->lsm[lsm_rule].rule);
320 if (!entry->lsm[lsm_rule].rule) 397 if (!entry->lsm[lsm_rule].rule) {
398 kfree(entry->lsm[lsm_rule].args_p);
321 return -EINVAL; 399 return -EINVAL;
400 }
401
322 return result; 402 return result;
323} 403}
324 404
@@ -404,8 +484,9 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
404 entry->func = FILE_CHECK; 484 entry->func = FILE_CHECK;
405 else if (strcmp(args[0].from, "MODULE_CHECK") == 0) 485 else if (strcmp(args[0].from, "MODULE_CHECK") == 0)
406 entry->func = MODULE_CHECK; 486 entry->func = MODULE_CHECK;
407 else if (strcmp(args[0].from, "FILE_MMAP") == 0) 487 else if ((strcmp(args[0].from, "FILE_MMAP") == 0)
408 entry->func = FILE_MMAP; 488 || (strcmp(args[0].from, "MMAP_CHECK") == 0))
489 entry->func = MMAP_CHECK;
409 else if (strcmp(args[0].from, "BPRM_CHECK") == 0) 490 else if (strcmp(args[0].from, "BPRM_CHECK") == 0)
410 entry->func = BPRM_CHECK; 491 entry->func = BPRM_CHECK;
411 else 492 else
@@ -445,6 +526,19 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
445 if (!result) 526 if (!result)
446 entry->flags |= IMA_FSMAGIC; 527 entry->flags |= IMA_FSMAGIC;
447 break; 528 break;
529 case Opt_fsuuid:
530 ima_log_string(ab, "fsuuid", args[0].from);
531
532 if (memchr_inv(entry->fsuuid, 0x00,
533 sizeof(entry->fsuuid))) {
534 result = -EINVAL;
535 break;
536 }
537
538 part_pack_uuid(args[0].from, entry->fsuuid);
539 entry->flags |= IMA_FSUUID;
540 result = 0;
541 break;
448 case Opt_uid: 542 case Opt_uid:
449 ima_log_string(ab, "uid", args[0].from); 543 ima_log_string(ab, "uid", args[0].from);
450 544
@@ -481,40 +575,52 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry)
481 break; 575 break;
482 case Opt_obj_user: 576 case Opt_obj_user:
483 ima_log_string(ab, "obj_user", args[0].from); 577 ima_log_string(ab, "obj_user", args[0].from);
484 result = ima_lsm_rule_init(entry, args[0].from, 578 result = ima_lsm_rule_init(entry, args,
485 LSM_OBJ_USER, 579 LSM_OBJ_USER,
486 AUDIT_OBJ_USER); 580 AUDIT_OBJ_USER);
487 break; 581 break;
488 case Opt_obj_role: 582 case Opt_obj_role:
489 ima_log_string(ab, "obj_role", args[0].from); 583 ima_log_string(ab, "obj_role", args[0].from);
490 result = ima_lsm_rule_init(entry, args[0].from, 584 result = ima_lsm_rule_init(entry, args,
491 LSM_OBJ_ROLE, 585 LSM_OBJ_ROLE,
492 AUDIT_OBJ_ROLE); 586 AUDIT_OBJ_ROLE);
493 break; 587 break;
494 case Opt_obj_type: 588 case Opt_obj_type:
495 ima_log_string(ab, "obj_type", args[0].from); 589 ima_log_string(ab, "obj_type", args[0].from);
496 result = ima_lsm_rule_init(entry, args[0].from, 590 result = ima_lsm_rule_init(entry, args,
497 LSM_OBJ_TYPE, 591 LSM_OBJ_TYPE,
498 AUDIT_OBJ_TYPE); 592 AUDIT_OBJ_TYPE);
499 break; 593 break;
500 case Opt_subj_user: 594 case Opt_subj_user:
501 ima_log_string(ab, "subj_user", args[0].from); 595 ima_log_string(ab, "subj_user", args[0].from);
502 result = ima_lsm_rule_init(entry, args[0].from, 596 result = ima_lsm_rule_init(entry, args,
503 LSM_SUBJ_USER, 597 LSM_SUBJ_USER,
504 AUDIT_SUBJ_USER); 598 AUDIT_SUBJ_USER);
505 break; 599 break;
506 case Opt_subj_role: 600 case Opt_subj_role:
507 ima_log_string(ab, "subj_role", args[0].from); 601 ima_log_string(ab, "subj_role", args[0].from);
508 result = ima_lsm_rule_init(entry, args[0].from, 602 result = ima_lsm_rule_init(entry, args,
509 LSM_SUBJ_ROLE, 603 LSM_SUBJ_ROLE,
510 AUDIT_SUBJ_ROLE); 604 AUDIT_SUBJ_ROLE);
511 break; 605 break;
512 case Opt_subj_type: 606 case Opt_subj_type:
513 ima_log_string(ab, "subj_type", args[0].from); 607 ima_log_string(ab, "subj_type", args[0].from);
514 result = ima_lsm_rule_init(entry, args[0].from, 608 result = ima_lsm_rule_init(entry, args,
515 LSM_SUBJ_TYPE, 609 LSM_SUBJ_TYPE,
516 AUDIT_SUBJ_TYPE); 610 AUDIT_SUBJ_TYPE);
517 break; 611 break;
612 case Opt_appraise_type:
613 if (entry->action != APPRAISE) {
614 result = -EINVAL;
615 break;
616 }
617
618 ima_log_string(ab, "appraise_type", args[0].from);
619 if ((strcmp(args[0].from, "imasig")) == 0)
620 entry->flags |= IMA_DIGSIG_REQUIRED;
621 else
622 result = -EINVAL;
623 break;
518 case Opt_err: 624 case Opt_err:
519 ima_log_string(ab, "UNKNOWN", p); 625 ima_log_string(ab, "UNKNOWN", p);
520 result = -EINVAL; 626 result = -EINVAL;
@@ -590,9 +696,13 @@ ssize_t ima_parse_add_rule(char *rule)
590void ima_delete_rules(void) 696void ima_delete_rules(void)
591{ 697{
592 struct ima_rule_entry *entry, *tmp; 698 struct ima_rule_entry *entry, *tmp;
699 int i;
593 700
594 mutex_lock(&ima_rules_mutex); 701 mutex_lock(&ima_rules_mutex);
595 list_for_each_entry_safe(entry, tmp, &ima_policy_rules, list) { 702 list_for_each_entry_safe(entry, tmp, &ima_policy_rules, list) {
703 for (i = 0; i < MAX_LSM_RULES; i++)
704 kfree(entry->lsm[i].args_p);
705
596 list_del(&entry->list); 706 list_del(&entry->list);
597 kfree(entry); 707 kfree(entry);
598 } 708 }