---
include/linux/audit.h | 1 +
kernel/audit.h | 1 +
kernel/audit_fsnotify.c | 15 +++++++++++++++
kernel/auditfilter.c | 21 ++++++++++++++++++++-
4 files changed, 37 insertions(+), 1 deletions(-)
diff --git a/include/linux/audit.h b/include/linux/audit.h
index f2a8044..0bb9ea6 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -43,6 +43,7 @@ struct mq_attr;
struct mqstat;
struct audit_watch;
struct audit_tree;
+struct audit_fsnotify_mark;
struct sk_buff;
struct audit_krule {
diff --git a/kernel/audit.h b/kernel/audit.h
index 7bf3138..2093c5e 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -285,6 +285,7 @@ extern int audit_watch_compare(struct audit_watch *watch, unsigned
long ino, dev
struct audit_fsnotify_mark *audit_alloc_mark(struct audit_krule *krule, char *pathname,
int len);
char *audit_mark_path(struct audit_fsnotify_mark *mark);
+int audit_add_mark_rule(struct audit_krule *krule, struct list_head **list);
void audit_remove_mark(struct audit_fsnotify_mark *audit_mark);
int audit_mark_compare(struct audit_fsnotify_mark *mark, unsigned long ino, dev_t dev);
diff --git a/kernel/audit_fsnotify.c b/kernel/audit_fsnotify.c
index efefa16..cc4175a 100644
--- a/kernel/audit_fsnotify.c
+++ b/kernel/audit_fsnotify.c
@@ -161,6 +161,21 @@ static void audit_mark_log_rule_change(struct audit_fsnotify_mark
*audit_mark, c
audit_log_end(ab);
}
+int audit_add_mark_rule(struct audit_krule *krule, struct list_head **list)
+{
+ struct audit_fsnotify_mark *audit_mark;
+ int h, ret = 0;
+
+ if (krule->exe)
+ audit_mark = krule->exe;
+ else
+ return -EINVAL; //XXX
+
+ h = audit_hash_ino((u32)audit_mark->ino);
+ *list = &audit_inode_hash[h];
+ return ret;
+}
+
static int audit_update_mark(struct audit_fsnotify_mark *audit_mark,
struct inode *inode)
{
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index f40c13b..7b6e892 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -34,6 +34,7 @@
#include <net/net_namespace.h>
#include <net/sock.h>
#include "audit.h"
+#include <linux/fsnotify_backend.h>
/*
* Locking model:
@@ -79,6 +80,8 @@ static inline void audit_free_rule(struct audit_entry *e)
/* some rules don't have associated watches */
if (erule->watch)
audit_put_watch(erule->watch);
+ if (erule->exe)
+ fsnotify_put_mark(erule->exe->mark);
if (erule->fields)
for (i = 0; i < erule->field_count; i++) {
struct audit_field *f = &erule->fields[i];
@@ -566,6 +569,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data
*data,
err = PTR_ERR(audit_mark);
goto exit_free;
}
+ fsnotify_get_mark(audit_mark->mark);
entry->rule.exe = audit_mark;
break;
}
@@ -582,6 +586,8 @@ exit_free:
audit_put_watch(entry->rule.watch); /* matches initial get */
if (entry->rule.tree)
audit_put_tree(entry->rule.tree); /* that's the temporary one */
+ if (entry->rule.exe)
+ fsnotify_put_mark(entry->rule.exe->mark); /* matches initial get */
audit_free_rule(entry);
return ERR_PTR(err);
}
@@ -866,7 +872,7 @@ static struct audit_entry *audit_find_rule(struct audit_entry *entry,
if (entry->rule.inode_f) {
h = audit_hash_ino(entry->rule.inode_f->val);
*p = list = &audit_inode_hash[h];
- } else if (entry->rule.watch) {
+ } else if (entry->rule.watch || entry->rule.exe) {
/* we don't know the inode number, so must walk entire hash */
for (h = 0; h < AUDIT_INODE_BUCKETS; h++) {
list = &audit_inode_hash[h];
@@ -900,6 +906,7 @@ static inline int audit_add_rule(struct audit_entry *entry)
struct audit_entry *e;
struct audit_watch *watch = entry->rule.watch;
struct audit_tree *tree = entry->rule.tree;
+ struct audit_fsnotify_mark *exe = entry->rule.exe;
struct list_head *list;
int err;
#ifdef CONFIG_AUDITSYSCALL
@@ -943,6 +950,13 @@ static inline int audit_add_rule(struct audit_entry *entry)
goto error;
}
}
+ if (exe) {
+ err = audit_add_mark_rule(&entry->rule, &list);
+ if (err) {
+ mutex_unlock(&audit_filter_mutex);
+ goto error;
+ }
+ }
entry->rule.prio = ~0ULL;
if (entry->rule.listnr == AUDIT_FILTER_EXIT) {
@@ -976,6 +990,8 @@ static inline int audit_add_rule(struct audit_entry *entry)
error:
if (watch)
audit_put_watch(watch); /* tmp watch, matches initial get */
+ if (exe)
+ fsnotify_put_mark(exe->mark); /* tmp mark, matches initial get */
return err;
}
@@ -985,6 +1001,7 @@ int audit_del_rule(struct audit_entry *entry)
struct audit_entry *e;
struct audit_watch *watch = entry->rule.watch;
struct audit_tree *tree = entry->rule.tree;
+ struct audit_fsnotify_mark *exe = entry->rule.exe;
struct list_head *list;
int ret = 0;
#ifdef CONFIG_AUDITSYSCALL
@@ -1031,6 +1048,8 @@ out:
audit_put_watch(watch); /* match initial get */
if (tree)
audit_put_tree(tree); /* that's the temporary one */
+ if (exe)
+ fsnotify_put_mark(exe->mark); /* match initial get */
return ret;
}
--
1.7.1