aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2009-06-11 14:31:34 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2009-06-23 23:50:36 -0400
commite85188f424c8eec7f311deed9a70bec57aeed741 (patch)
tree3456260b54bc8fd8d336d5e8865104480d5ac0fe
parentb87ce6e4187c24b06483c8266822ce5e6b7fa7f3 (diff)
Audit: dereferencing krule as if it were an audit_watch
audit_update_watch() runs all of the rules for a given watch and duplicates them, attaches a new watch to them, and then when it finishes that process and has called free on all of the old rules (ok maybe still inside the rcu grace period) it proceeds to use the last element from list_for_each_entry_safe() as if it were a krule rather than being the audit_watch which was anchoring the list to output a message about audit rules changing. This patch unfies the audit message from two different places into a helper function and calls it from the correct location in audit_update_rules(). We will now get an audit message about the config changing for each rule (with each rules filterkey) rather than the previous garbage. Signed-off-by: Eric Paris <eparis@redhat.com>
-rw-r--r--kernel/auditfilter.c58
1 files changed, 24 insertions, 34 deletions
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 19c0a0a2cede..e7466dd145c9 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -977,6 +977,27 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old,
977 return entry; 977 return entry;
978} 978}
979 979
980static void audit_watch_log_rule_change(struct audit_krule *r, struct audit_watch *w, char *op)
981{
982 if (audit_enabled) {
983 struct audit_buffer *ab;
984 ab = audit_log_start(NULL, GFP_NOFS, AUDIT_CONFIG_CHANGE);
985 audit_log_format(ab, "auid=%u ses=%u op=",
986 audit_get_loginuid(current),
987 audit_get_sessionid(current));
988 audit_log_string(ab, op);
989 audit_log_format(ab, " path=");
990 audit_log_untrustedstring(ab, w->path);
991 if (r->filterkey) {
992 audit_log_format(ab, " key=");
993 audit_log_untrustedstring(ab, r->filterkey);
994 } else
995 audit_log_format(ab, " key=(null)");
996 audit_log_format(ab, " list=%d res=1", r->listnr);
997 audit_log_end(ab);
998 }
999}
1000
980/* Update inode info in audit rules based on filesystem event. */ 1001/* Update inode info in audit rules based on filesystem event. */
981static void audit_update_watch(struct audit_parent *parent, 1002static void audit_update_watch(struct audit_parent *parent,
982 const char *dname, dev_t dev, 1003 const char *dname, dev_t dev,
@@ -1023,24 +1044,11 @@ static void audit_update_watch(struct audit_parent *parent,
1023 &nentry->rule.list); 1044 &nentry->rule.list);
1024 } 1045 }
1025 1046
1047 audit_watch_log_rule_change(r, owatch, "updated rules");
1048
1026 call_rcu(&oentry->rcu, audit_free_rule_rcu); 1049 call_rcu(&oentry->rcu, audit_free_rule_rcu);
1027 } 1050 }
1028 1051
1029 if (audit_enabled) {
1030 struct audit_buffer *ab;
1031 ab = audit_log_start(NULL, GFP_NOFS,
1032 AUDIT_CONFIG_CHANGE);
1033 audit_log_format(ab, "auid=%u ses=%u",
1034 audit_get_loginuid(current),
1035 audit_get_sessionid(current));
1036 audit_log_format(ab,
1037 " op=updated rules specifying path=");
1038 audit_log_untrustedstring(ab, owatch->path);
1039 audit_log_format(ab, " with dev=%u ino=%lu\n",
1040 dev, ino);
1041 audit_log_format(ab, " list=%d res=1", r->listnr);
1042 audit_log_end(ab);
1043 }
1044 audit_remove_watch(owatch); 1052 audit_remove_watch(owatch);
1045 goto add_watch_to_parent; /* event applies to a single watch */ 1053 goto add_watch_to_parent; /* event applies to a single watch */
1046 } 1054 }
@@ -1065,25 +1073,7 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
1065 list_for_each_entry_safe(w, nextw, &parent->watches, wlist) { 1073 list_for_each_entry_safe(w, nextw, &parent->watches, wlist) {
1066 list_for_each_entry_safe(r, nextr, &w->rules, rlist) { 1074 list_for_each_entry_safe(r, nextr, &w->rules, rlist) {
1067 e = container_of(r, struct audit_entry, rule); 1075 e = container_of(r, struct audit_entry, rule);
1068 if (audit_enabled) { 1076 audit_watch_log_rule_change(r, w, "remove rule");
1069 struct audit_buffer *ab;
1070 ab = audit_log_start(NULL, GFP_NOFS,
1071 AUDIT_CONFIG_CHANGE);
1072 audit_log_format(ab, "auid=%u ses=%u",
1073 audit_get_loginuid(current),
1074 audit_get_sessionid(current));
1075 audit_log_format(ab, " op=remove rule path=");
1076 audit_log_untrustedstring(ab, w->path);
1077 if (r->filterkey) {
1078 audit_log_format(ab, " key=");
1079 audit_log_untrustedstring(ab,
1080 r->filterkey);
1081 } else
1082 audit_log_format(ab, " key=(null)");
1083 audit_log_format(ab, " list=%d res=1",
1084 r->listnr);
1085 audit_log_end(ab);
1086 }
1087 list_del(&r->rlist); 1077 list_del(&r->rlist);
1088 list_del(&r->list); 1078 list_del(&r->list);
1089 list_del_rcu(&e->list); 1079 list_del_rcu(&e->list);