From mboxrd@z Thu Jan 1 00:00:00 1970 From: Richard Guy Briggs Subject: [PATCH 03/12] [V3] audit: convert audit_exe to audit_fsnotify Date: Wed, 2 Jul 2014 14:05:11 -0400 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: In-Reply-To: References: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-audit-bounces@redhat.com Errors-To: linux-audit-bounces@redhat.com To: linux-audit@redhat.com Cc: Richard Guy Briggs List-Id: linux-audit@redhat.com From: Eric Paris 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 Signed-off-by: Richard Guy Briggs --- include/linux/audit.h | 2 +- kernel/audit.h | 32 +++--------------- kernel/audit_exe.c | 87 +++++++------------------------------------------ kernel/auditfilter.c | 18 ++++++---- 4 files changed, 29 insertions(+), 110 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..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,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..b33a09a 100644 --- a/kernel/audit_exe.c +++ b/kernel/audit_exe.c @@ -17,93 +17,30 @@ #include #include -#include #include #include #include #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