diff options
Diffstat (limited to 'security')
-rw-r--r-- | security/integrity/ima/ima_policy.c | 68 |
1 files changed, 58 insertions, 10 deletions
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index af7d182..70f888d 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -49,6 +49,7 @@ struct ima_rule_entry { kuid_t fowner; struct { void *rule; /* LSM file metadata specific */ + void *args_p; /* audit value */ int type; /* audit type */ } lsm[MAX_LSM_RULES]; }; @@ -119,6 +120,35 @@ static int __init default_appraise_policy_setup(char *str) } __setup("ima_appraise_tcb", default_appraise_policy_setup); +/* + * Although the IMA policy does not change, the LSM policy can be + * reloaded, leaving the IMA LSM based rules referring to the old, + * stale LSM policy. + * + * Update the IMA LSM based rules to reflect the reloaded LSM policy. + * We assume the rules still exist; and BUG_ON() if they don't. + */ +static void ima_lsm_update_rules(void) +{ + struct ima_rule_entry *entry, *tmp; + int result; + int i; + + mutex_lock(&ima_rules_mutex); + list_for_each_entry_safe(entry, tmp, &ima_policy_rules, list) { + for (i = 0; i < MAX_LSM_RULES; i++) { + if (!entry->lsm[i].rule) + continue; + result = security_filter_rule_init(entry->lsm[i].type, + Audit_equal, + entry->lsm[i].args_p, + &entry->lsm[i].rule); + BUG_ON(!entry->lsm[i].rule); + } + } + mutex_unlock(&ima_rules_mutex); +} + /** * ima_match_rules - determine whether an inode matches the measure rule. * @rule: a pointer to a rule @@ -149,10 +179,11 @@ static bool ima_match_rules(struct ima_rule_entry *rule, for (i = 0; i < MAX_LSM_RULES; i++) { int rc = 0; u32 osid, sid; + int retried = 0; if (!rule->lsm[i].rule) continue; - +retry: switch (i) { case LSM_OBJ_USER: case LSM_OBJ_ROLE: @@ -176,6 +207,11 @@ static bool ima_match_rules(struct ima_rule_entry *rule, default: break; } + if ((rc < 0) && (!retried)) { + retried = 1; + ima_lsm_update_rules(); + goto retry; + } if (!rc) return false; } @@ -306,19 +342,27 @@ static match_table_t policy_tokens = { }; static int ima_lsm_rule_init(struct ima_rule_entry *entry, - char *args, int lsm_rule, int audit_type) + substring_t *args, int lsm_rule, int audit_type) { int result; if (entry->lsm[lsm_rule].rule) return -EINVAL; + entry->lsm[lsm_rule].args_p = match_strdup(args); + if (!entry->lsm[lsm_rule].args_p) + return -ENOMEM; + entry->lsm[lsm_rule].type = audit_type; result = security_filter_rule_init(entry->lsm[lsm_rule].type, - Audit_equal, args, + Audit_equal, + entry->lsm[lsm_rule].args_p, &entry->lsm[lsm_rule].rule); - if (!entry->lsm[lsm_rule].rule) + if (!entry->lsm[lsm_rule].rule) { + kfree(entry->lsm[lsm_rule].args_p); return -EINVAL; + } + return result; } @@ -481,37 +525,37 @@ static int ima_parse_rule(char *rule, struct ima_rule_entry *entry) break; case Opt_obj_user: ima_log_string(ab, "obj_user", args[0].from); - result = ima_lsm_rule_init(entry, args[0].from, + result = ima_lsm_rule_init(entry, args, LSM_OBJ_USER, AUDIT_OBJ_USER); break; case Opt_obj_role: ima_log_string(ab, "obj_role", args[0].from); - result = ima_lsm_rule_init(entry, args[0].from, + result = ima_lsm_rule_init(entry, args, LSM_OBJ_ROLE, AUDIT_OBJ_ROLE); break; case Opt_obj_type: ima_log_string(ab, "obj_type", args[0].from); - result = ima_lsm_rule_init(entry, args[0].from, + result = ima_lsm_rule_init(entry, args, LSM_OBJ_TYPE, AUDIT_OBJ_TYPE); break; case Opt_subj_user: ima_log_string(ab, "subj_user", args[0].from); - result = ima_lsm_rule_init(entry, args[0].from, + result = ima_lsm_rule_init(entry, args, LSM_SUBJ_USER, AUDIT_SUBJ_USER); break; case Opt_subj_role: ima_log_string(ab, "subj_role", args[0].from); - result = ima_lsm_rule_init(entry, args[0].from, + result = ima_lsm_rule_init(entry, args, LSM_SUBJ_ROLE, AUDIT_SUBJ_ROLE); break; case Opt_subj_type: ima_log_string(ab, "subj_type", args[0].from); - result = ima_lsm_rule_init(entry, args[0].from, + result = ima_lsm_rule_init(entry, args, LSM_SUBJ_TYPE, AUDIT_SUBJ_TYPE); break; @@ -589,9 +633,13 @@ ssize_t ima_parse_add_rule(char *rule) void ima_delete_rules(void) { struct ima_rule_entry *entry, *tmp; + int i; mutex_lock(&ima_rules_mutex); list_for_each_entry_safe(entry, tmp, &ima_policy_rules, list) { + for (i = 0; i < MAX_LSM_RULES; i++) + kfree(entry->lsm[i].args_p); + list_del(&entry->list); kfree(entry); } |