From: Eric Paris <epa...@redhat.com>

Instead of just hard coding the ino and dev of the executable we care
about at the moment the rule is inserted into the kernel, use the new
audit_fsnotify infrastructure.  This means that if the inode in question
is unlinked and creat'd (aka updated) the rule will just continue to
work.

Signed-off-by: Eric Paris <epa...@redhat.com>
Signed-off-by: Richard Guy Briggs <r...@redhat.com>
---
 include/linux/audit.h |    2 +-
 kernel/audit.h        |   31 ++++-------------
 kernel/audit_exe.c    |   87 +++++++------------------------------------------
 kernel/auditfilter.c  |   18 ++++++----
 4 files changed, 31 insertions(+), 107 deletions(-)

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 227171c..f2a8044 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -59,7 +59,7 @@ struct audit_krule {
        struct audit_field      *inode_f; /* quick access to an inode field */
        struct audit_watch      *watch; /* associated watch */
        struct audit_tree       *tree;  /* associated watched tree */
-       struct audit_exe        *exe;
+       struct audit_fsnotify_mark      *exe;
        struct list_head        rlist;  /* entry in audit_{watch,tree}.rules 
list */
        struct list_head        list;   /* for AUDIT_LIST* purposes only */
        u64                     prio;
diff --git a/kernel/audit.h b/kernel/audit.h
index 8d863d4..61688ba 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -57,7 +57,6 @@ enum audit_state {
 /* Rule lists */
 struct audit_watch;
 struct audit_fsnotify_mark;
-struct audit_exe;
 struct audit_tree;
 struct audit_chunk;
 
@@ -289,11 +288,8 @@ char *audit_mark_path(struct audit_fsnotify_mark *mark);
 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);
 
-int audit_make_exe_rule(struct audit_krule *krule, char *pathname, int len, 
u32 op);
-void audit_remove_exe_rule(struct audit_krule *krule);
-char *audit_exe_path(struct audit_exe *exe);
 int audit_dup_exe(struct audit_krule *new, struct audit_krule *old);
-int audit_exe_compare(struct task_struct *tsk, struct audit_exe *exe);
+int audit_exe_compare(struct task_struct *tsk, struct audit_fsnotify_mark 
*mark);
 
 #else
 #define audit_put_watch(w) {}
@@ -320,31 +316,18 @@ static inline void audit_remove_mark(struct 
audit_fsnotify_mark *audit_mark)
        BUG();
 }
 
-static inline int audit_mark_compare(struct audit_fsnotify_mark *mark, 
unsigned long ino, dev_t dev)
+static inline int audit_exe_compare(struct task_struct *tsk, struct 
audit_fsnotify_mark *mark)
 {
        BUG();
-       return 0;
-}
-
-static inline int audit_make_exe_rule(struct audit_krule *krule, char 
*pathname, int len, u32 op) {
        return -EINVAL;
 }
-static inline void audit_remove_exe_rule(struct audit_krule *krule) {
-       BUG();
-       return 0;
-}
-static inline char *audit_exe_path(struct audit_exe *exe) {
-       BUG();
-       return "";
-}
-static inline int audit_dup_exe(struct audit_krule *new, struct audit_krule 
*old) {
-       BUG();
-       return -EINVAL
-}
-static inline int audit_exe_compare(struct task_struct *tsk, struct audit_exe 
*exe) {
+
+static inline int audit_dup_exe(struct audit_krule *new, struct audit_krule 
*old)
+{
        BUG();
-       return 0;
+       return -EINVAL;
 }
+
 #endif /* CONFIG_AUDIT_WATCH */
 
 #ifdef CONFIG_AUDIT_TREE
diff --git a/kernel/audit_exe.c b/kernel/audit_exe.c
index 09c436c..d704a54 100644
--- a/kernel/audit_exe.c
+++ b/kernel/audit_exe.c
@@ -21,93 +21,30 @@
 
 #include <linux/kernel.h>
 #include <linux/audit.h>
-#include <linux/mutex.h>
 #include <linux/fs.h>
 #include <linux/namei.h>
 #include <linux/slab.h>
 #include "audit.h"
 
-struct audit_exe {
-       char *pathname;
-       unsigned long ino;
-       dev_t dev;
-};
-
-/* Translate a watch string to kernel respresentation. */
-int audit_make_exe_rule(struct audit_krule *krule, char *pathname, int len, 
u32 op)
-{
-       struct audit_exe *exe;
-       struct path path;
-       struct dentry *dentry;
-       unsigned long ino;
-       dev_t dev;
-
-       if (pathname[0] != '/' || pathname[len-1] == '/')
-               return -EINVAL;
-
-       dentry = kern_path_locked(pathname, &path);
-       if (IS_ERR(dentry))
-               return PTR_ERR(dentry);
-       mutex_unlock(&path.dentry->d_inode->i_mutex);
-
-       if (!dentry->d_inode)
-               return -ENOENT;
-       dev = dentry->d_inode->i_sb->s_dev;
-       ino = dentry->d_inode->i_ino;
-       dput(dentry);
-
-       exe = kmalloc(sizeof(*exe), GFP_KERNEL);
-       if (!exe)
-               return -ENOMEM;
-       exe->ino = ino;
-       exe->dev = dev;
-       exe->pathname = pathname;
-       krule->exe = exe;
-
-       return 0;
-}
-
-void audit_remove_exe_rule(struct audit_krule *krule)
-{
-       struct audit_exe *exe;
-
-       exe = krule->exe;
-       krule->exe = NULL;
-       kfree(exe->pathname);
-       kfree(exe);
-}
-
-char *audit_exe_path(struct audit_exe *exe)
-{
-       return exe->pathname;
-}
-
 int audit_dup_exe(struct audit_krule *new, struct audit_krule *old)
 {
-       struct audit_exe *exe;
-
-       exe = kmalloc(sizeof(*exe), GFP_KERNEL);
-       if (!exe)
-               return -ENOMEM;
+       struct audit_fsnotify_mark *audit_mark;
+       char *pathname;
 
-       exe->pathname = kstrdup(old->exe->pathname, GFP_KERNEL);
-       if (!exe->pathname) {
-               kfree(exe);
-               return -ENOMEM;
-       }
+       pathname = audit_mark_path(old->exe);
 
-       exe->ino = old->exe->ino;
-       exe->dev = old->exe->dev;
-       new->exe = exe;
+       audit_mark = audit_alloc_mark(pathname, strlen(pathname), new);
+       if (IS_ERR(audit_mark))
+               return PTR_ERR(audit_mark);
+       new->exe = audit_mark;
 
        return 0;
 }
 
-int audit_exe_compare(struct task_struct *tsk, struct audit_exe *exe)
+int audit_exe_compare(struct task_struct *tsk, struct audit_fsnotify_mark 
*mark)
 {
-       if (tsk->mm->exe_file->f_inode->i_ino != exe->ino)
-               return 0;
-       if (tsk->mm->exe_file->f_inode->i_sb->s_dev != exe->dev)
-               return 0;
-       return 1;
+       unsigned long ino = tsk->mm->exe_file->f_inode->i_ino;
+       dev_t dev = tsk->mm->exe_file->f_inode->i_sb->s_dev;
+
+       return audit_mark_compare(mark, ino, dev);
 }
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 5c1951a..30091ce 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -411,6 +411,7 @@ static struct audit_entry *audit_data_to_entry(struct 
audit_rule_data *data,
        size_t remain = datasz - sizeof(struct audit_rule_data);
        int i;
        char *str;
+       struct audit_fsnotify_mark *audit_mark;
 
        entry = audit_to_entry_common(data);
        if (IS_ERR(entry))
@@ -550,6 +551,7 @@ static struct audit_entry *audit_data_to_entry(struct 
audit_rule_data *data,
                        break;
                case AUDIT_EXE:
                case AUDIT_EXE_CHILDREN:
+
                        if (entry->rule.exe || f->val > PATH_MAX)
                                goto exit_free;
                        str = audit_unpack_string(&bufp, &remain, f->val);
@@ -559,11 +561,13 @@ static struct audit_entry *audit_data_to_entry(struct 
audit_rule_data *data,
                        }
                        entry->rule.buflen += f->val;
 
-                       err = audit_make_exe_rule(&entry->rule, str, f->val, 
f->op);
-                       if (err) {
-                               kfree(str);
+                       audit_mark = audit_alloc_mark(str, f->val, 
&entry->rule);
+                       kfree(str);
+                       if (IS_ERR(audit_mark)) {
+                               err = PTR_ERR(audit_mark);
                                goto exit_free;
                        }
+                       entry->rule.exe = audit_mark;
                        break;
                }
        }
@@ -646,7 +650,7 @@ static struct audit_rule_data *audit_krule_to_data(struct 
audit_krule *krule)
                case AUDIT_EXE:
                case AUDIT_EXE_CHILDREN:
                        data->buflen += data->values[i] =
-                               audit_pack_string(&bufp, 
audit_exe_path(krule->exe));
+                               audit_pack_string(&bufp, 
audit_mark_path(krule->exe));
                        break;
                default:
                        data->values[i] = f->val;
@@ -706,8 +710,8 @@ static int audit_compare_rule(struct audit_krule *a, struct 
audit_krule *b)
                case AUDIT_EXE:
                case AUDIT_EXE_CHILDREN:
                        /* both paths exist based on above type compare */
-                       if (strcmp(audit_exe_path(a->exe),
-                                  audit_exe_path(b->exe)))
+                       if (strcmp(audit_mark_path(a->exe),
+                                  audit_mark_path(b->exe)))
                                return 1;
                        break;
                case AUDIT_UID:
@@ -1008,7 +1012,7 @@ int audit_del_rule(struct audit_entry *entry)
                audit_remove_tree_rule(&e->rule);
 
        if (e->rule.exe)
-               audit_remove_exe_rule(&e->rule);
+               audit_remove_mark(e->rule.exe);
        list_del_rcu(&e->list);
        list_del(&e->rule.list);
        call_rcu(&e->rcu, audit_free_rule_rcu);
-- 
1.7.1

--
Linux-audit mailing list
Linux-audit@redhat.com
https://www.redhat.com/mailman/listinfo/linux-audit

Reply via email to