From: Eric Paris <eparis(a)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.
RGB: Put audit_alloc_mark() arguments in same order as watch, tree and inode.
Signed-off-by: Eric Paris <eparis(a)redhat.com>
Signed-off-by: Richard Guy Briggs <rgb(a)redhat.com>
---
include/linux/audit.h | 2 +-
kernel/audit.h | 34 +++---------------
kernel/audit_exe.c | 87 ++++++----------------------------------------
kernel/audit_fsnotify.c | 2 +-
kernel/auditfilter.c | 15 +++++---
5 files changed, 29 insertions(+), 111 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 1eed1ed..7bf3138 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;
@@ -284,16 +283,13 @@ extern void audit_remove_watch_rule(struct audit_krule *krule);
extern char *audit_watch_path(struct audit_watch *watch);
extern int audit_watch_compare(struct audit_watch *watch, unsigned long ino, dev_t dev);
-struct audit_fsnotify_mark *audit_alloc_mark(char *pathname, int len, struct audit_krule
*krule);
+struct audit_fsnotify_mark *audit_alloc_mark(struct audit_krule *krule, char *pathname,
int len);
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,36 +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)
-{
- 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 ec3231b..0c7ee8d 100644
--- a/kernel/audit_exe.c
+++ b/kernel/audit_exe.c
@@ -17,93 +17,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(new, pathname, strlen(pathname));
+ 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/audit_fsnotify.c b/kernel/audit_fsnotify.c
index 3492b9c..704ce46 100644
--- a/kernel/audit_fsnotify.c
+++ b/kernel/audit_fsnotify.c
@@ -87,7 +87,7 @@ int audit_mark_compare(struct audit_fsnotify_mark *mark, unsigned long
ino, dev_
return (mark->ino == ino) && (mark->dev == dev);
}
-struct audit_fsnotify_mark *audit_alloc_mark(char *pathname, int len, struct audit_krule
*krule)
+struct audit_fsnotify_mark *audit_alloc_mark(struct audit_krule *krule, char *pathname,
int len)
{
struct audit_fsnotify_mark *audit_mark;
struct path path;
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 0fe1f72..149588d 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -413,6 +413,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))
@@ -561,11 +562,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(&entry->rule, str, f->val);
+ kfree(str);
+ if (IS_ERR(audit_mark)) {
+ err = PTR_ERR(audit_mark);
goto exit_free;
}
+ entry->rule.exe = audit_mark;
break;
}
}
@@ -648,7 +651,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;
@@ -708,8 +711,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:
--
1.7.1