ima: Handle -ESTALE returned by ima_filter_rule_match()
[platform/kernel/linux-starfive.git] / security / integrity / ima / ima_policy.c
index a8802b8..bb37071 100644 (file)
@@ -549,6 +549,9 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
                            const char *func_data)
 {
        int i;
+       bool result = false;
+       struct ima_rule_entry *lsm_rule = rule;
+       bool rule_reinitialized = false;
 
        if ((rule->flags & IMA_FUNC) &&
            (rule->func != func && func != POST_SETATTR))
@@ -610,35 +613,55 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
                int rc = 0;
                u32 osid;
 
-               if (!rule->lsm[i].rule) {
-                       if (!rule->lsm[i].args_p)
+               if (!lsm_rule->lsm[i].rule) {
+                       if (!lsm_rule->lsm[i].args_p)
                                continue;
                        else
                                return false;
                }
+
+retry:
                switch (i) {
                case LSM_OBJ_USER:
                case LSM_OBJ_ROLE:
                case LSM_OBJ_TYPE:
                        security_inode_getsecid(inode, &osid);
-                       rc = ima_filter_rule_match(osid, rule->lsm[i].type,
+                       rc = ima_filter_rule_match(osid, lsm_rule->lsm[i].type,
                                                   Audit_equal,
-                                                  rule->lsm[i].rule);
+                                                  lsm_rule->lsm[i].rule);
                        break;
                case LSM_SUBJ_USER:
                case LSM_SUBJ_ROLE:
                case LSM_SUBJ_TYPE:
-                       rc = ima_filter_rule_match(secid, rule->lsm[i].type,
+                       rc = ima_filter_rule_match(secid, lsm_rule->lsm[i].type,
                                                   Audit_equal,
-                                                  rule->lsm[i].rule);
+                                                  lsm_rule->lsm[i].rule);
                        break;
                default:
                        break;
                }
-               if (!rc)
-                       return false;
+
+               if (rc == -ESTALE && !rule_reinitialized) {
+                       lsm_rule = ima_lsm_copy_rule(rule);
+                       if (lsm_rule) {
+                               rule_reinitialized = true;
+                               goto retry;
+                       }
+               }
+               if (!rc) {
+                       result = false;
+                       goto out;
+               }
        }
-       return true;
+       result = true;
+
+out:
+       if (rule_reinitialized) {
+               for (i = 0; i < MAX_LSM_RULES; i++)
+                       ima_filter_rule_free(lsm_rule->lsm[i].rule);
+               kfree(lsm_rule);
+       }
+       return result;
 }
 
 /*