Skip to content

Commit

Permalink
ima: re-initialize IMA policy LSM info
Browse files Browse the repository at this point in the history
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.  This patch updates the IMA LSM based rules
to reflect the reloaded LSM policy.

Reported-by: Sven Vermeulen <[email protected]>
tested-by: Sven Vermeulen <[email protected]>
Signed-off-by: Mimi Zohar <[email protected]>
Cc: Eric Paris <[email protected]>
Cc: Casey Schaufler <[email protected]>
  • Loading branch information
Mimi Zohar committed Jan 16, 2013
1 parent cf9ce94 commit 7163a99
Showing 1 changed file with 58 additions and 10 deletions.
68 changes: 58 additions & 10 deletions security/integrity/ima/ima_policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -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];
};
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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:
Expand All @@ -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;
}
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}
Expand Down

0 comments on commit 7163a99

Please sign in to comment.