kuid_t fowner;
        struct {
                void *rule;     /* LSM file metadata specific */
+               void *args_p;   /* audit value */
                int type;       /* audit type */
        } lsm[MAX_LSM_RULES];
 };
 }
 __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
        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:
                default:
                        break;
                }
+               if ((rc < 0) && (!retried)) {
+                       retried = 1;
+                       ima_lsm_update_rules();
+                       goto retry;
+               } 
                if (!rc)
                        return false;
        }
 };
 
 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;
 }
 
                        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;
 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);
        }