Skip to content

Commit eb0782b

Browse files
liqiongmimizohar
authored andcommitted
ima: fix deadlock when traversing "ima_default_rules".
The current IMA ruleset is identified by the variable "ima_rules" that default to "&ima_default_rules". When loading a custom policy for the first time, the variable is updated to "&ima_policy_rules" instead. That update isn't RCU-safe, and deadlocks are possible. Indeed, some functions like ima_match_policy() may loop indefinitely when traversing "ima_default_rules" with list_for_each_entry_rcu(). When iterating over the default ruleset back to head, if the list head is "ima_default_rules", and "ima_rules" have been updated to "&ima_policy_rules", the loop condition (&entry->list != ima_rules) stays always true, traversing won't terminate, causing a soft lockup and RCU stalls. Introduce a temporary value for "ima_rules" when iterating over the ruleset to avoid the deadlocks. Signed-off-by: liqiong <[email protected]> Reviewed-by: THOBY Simon <[email protected]> Fixes: 38d859f ("IMA: policy can now be updated multiple times") Reported-by: kernel test robot <[email protected]> (Fix sparse: incompatible types in comparison expression.) Signed-off-by: Mimi Zohar <[email protected]>
1 parent 6880fa6 commit eb0782b

File tree

1 file changed

+18
-9
lines changed

1 file changed

+18
-9
lines changed

security/integrity/ima/ima_policy.c

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -228,7 +228,7 @@ static struct ima_rule_entry *arch_policy_entry __ro_after_init;
228228
static LIST_HEAD(ima_default_rules);
229229
static LIST_HEAD(ima_policy_rules);
230230
static LIST_HEAD(ima_temp_rules);
231-
static struct list_head *ima_rules = &ima_default_rules;
231+
static struct list_head __rcu *ima_rules = (struct list_head __rcu *)(&ima_default_rules);
232232

233233
static int ima_policy __initdata;
234234

@@ -675,12 +675,14 @@ int ima_match_policy(struct user_namespace *mnt_userns, struct inode *inode,
675675
{
676676
struct ima_rule_entry *entry;
677677
int action = 0, actmask = flags | (flags << 1);
678+
struct list_head *ima_rules_tmp;
678679

679680
if (template_desc && !*template_desc)
680681
*template_desc = ima_template_desc_current();
681682

682683
rcu_read_lock();
683-
list_for_each_entry_rcu(entry, ima_rules, list) {
684+
ima_rules_tmp = rcu_dereference(ima_rules);
685+
list_for_each_entry_rcu(entry, ima_rules_tmp, list) {
684686

685687
if (!(entry->action & actmask))
686688
continue;
@@ -741,9 +743,11 @@ void ima_update_policy_flags(void)
741743
{
742744
struct ima_rule_entry *entry;
743745
int new_policy_flag = 0;
746+
struct list_head *ima_rules_tmp;
744747

745748
rcu_read_lock();
746-
list_for_each_entry(entry, ima_rules, list) {
749+
ima_rules_tmp = rcu_dereference(ima_rules);
750+
list_for_each_entry_rcu(entry, ima_rules_tmp, list) {
747751
/*
748752
* SETXATTR_CHECK rules do not implement a full policy check
749753
* because rule checking would probably have an important
@@ -968,10 +972,10 @@ void ima_update_policy(void)
968972

969973
list_splice_tail_init_rcu(&ima_temp_rules, policy, synchronize_rcu);
970974

971-
if (ima_rules != policy) {
975+
if (ima_rules != (struct list_head __rcu *)policy) {
972976
ima_policy_flag = 0;
973-
ima_rules = policy;
974977

978+
rcu_assign_pointer(ima_rules, policy);
975979
/*
976980
* IMA architecture specific policy rules are specified
977981
* as strings and converted to an array of ima_entry_rules
@@ -1061,7 +1065,7 @@ static int ima_lsm_rule_init(struct ima_rule_entry *entry,
10611065
pr_warn("rule for LSM \'%s\' is undefined\n",
10621066
entry->lsm[lsm_rule].args_p);
10631067

1064-
if (ima_rules == &ima_default_rules) {
1068+
if (ima_rules == (struct list_head __rcu *)(&ima_default_rules)) {
10651069
kfree(entry->lsm[lsm_rule].args_p);
10661070
entry->lsm[lsm_rule].args_p = NULL;
10671071
result = -EINVAL;
@@ -1768,9 +1772,11 @@ void *ima_policy_start(struct seq_file *m, loff_t *pos)
17681772
{
17691773
loff_t l = *pos;
17701774
struct ima_rule_entry *entry;
1775+
struct list_head *ima_rules_tmp;
17711776

17721777
rcu_read_lock();
1773-
list_for_each_entry_rcu(entry, ima_rules, list) {
1778+
ima_rules_tmp = rcu_dereference(ima_rules);
1779+
list_for_each_entry_rcu(entry, ima_rules_tmp, list) {
17741780
if (!l--) {
17751781
rcu_read_unlock();
17761782
return entry;
@@ -1789,7 +1795,8 @@ void *ima_policy_next(struct seq_file *m, void *v, loff_t *pos)
17891795
rcu_read_unlock();
17901796
(*pos)++;
17911797

1792-
return (&entry->list == ima_rules) ? NULL : entry;
1798+
return (&entry->list == &ima_default_rules ||
1799+
&entry->list == &ima_policy_rules) ? NULL : entry;
17931800
}
17941801

17951802
void ima_policy_stop(struct seq_file *m, void *v)
@@ -2014,14 +2021,16 @@ bool ima_appraise_signature(enum kernel_read_file_id id)
20142021
struct ima_rule_entry *entry;
20152022
bool found = false;
20162023
enum ima_hooks func;
2024+
struct list_head *ima_rules_tmp;
20172025

20182026
if (id >= READING_MAX_ID)
20192027
return false;
20202028

20212029
func = read_idmap[id] ?: FILE_CHECK;
20222030

20232031
rcu_read_lock();
2024-
list_for_each_entry_rcu(entry, ima_rules, list) {
2032+
ima_rules_tmp = rcu_dereference(ima_rules);
2033+
list_for_each_entry_rcu(entry, ima_rules_tmp, list) {
20252034
if (entry->action != APPRAISE)
20262035
continue;
20272036

0 commit comments

Comments
 (0)