On Thu, Aug 23, 2012 at 12:24:00PM -0700, Peter Moody wrote: > This adds the ability audit the actions of a not-yet-running process, > as well as the children of a not-yet-running process.
Hi Peter, I've gone back over the discussion of this feature and some of the background in the past couple of years on this list... We've got a kernel deadline coming up in the next month if we want to get something included in RHEL7 if you have the interest and time to evolve this patch (the userspace patch can follow...). As has been discussed, passing in an inode reference is incomplete, since it would need to be qualified by a device reference at minimum. And even then, it isn't atomic and could change by the time the kernel even sees this rule request. So, the next step is to convert the path to a device/inode in the kernel. If this is done at the time of registering the filter rule, if/when the rule is invalidated then the rule would be dropped, logged. It also means that anything else also hardlinked to it would be acted upon. Going one step further, if instead we can arrange an fsnotify() hook on rule registration, we could act on that path when it is executed, renamed, unlinked (and destroyed if the refcount goes to zero), etc. So, it should be passed as a path, logging the rule addition with path only at first. When the rule is triggered then log the requested path, effective path, device/inode along with the user context. The user, carefully crafting other rules can give other information. A watch on the containing directory (/usr/bin) could help in case that executable pathname disappears and re-appears since the containing directory is less likely to go away, but it will be noisy. Does all this make sense? Let's deal later with namespaces, containers, mounts, chroots, bind mounts, etc... > Signed-off-by: Peter Moody <pmo...@google.com> > --- > include/linux/audit.h | 2 ++ > kernel/auditfilter.c | 6 ++++++ > kernel/auditsc.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 55 insertions(+), 0 deletions(-) > > diff --git a/include/linux/audit.h b/include/linux/audit.h > index 22f292a..5506cb1 100644 > --- a/include/linux/audit.h > +++ b/include/linux/audit.h > @@ -260,6 +260,8 @@ > #define AUDIT_OBJ_UID 109 > #define AUDIT_OBJ_GID 110 > #define AUDIT_FIELD_COMPARE 111 > +#define AUDIT_EXE 112 > +#define AUDIT_EXE_CHILDREN 113 > > #define AUDIT_ARG0 200 > #define AUDIT_ARG1 (AUDIT_ARG0+1) > diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c > index a6c3f1a..1e6c571 100644 > --- a/kernel/auditfilter.c > +++ b/kernel/auditfilter.c > @@ -546,6 +546,12 @@ static struct audit_entry *audit_data_to_entry(struct > audit_rule_data *data, > if (f->val > AUDIT_MAX_FIELD_COMPARE) > goto exit_free; > break; > + case AUDIT_EXE: > + case AUDIT_EXE_CHILDREN: > + if (f->op != Audit_equal) { > + goto exit_free; > + } > + break; > default: > goto exit_free; > } > diff --git a/kernel/auditsc.c b/kernel/auditsc.c > index 4b96415..9cebe95 100644 > --- a/kernel/auditsc.c > +++ b/kernel/auditsc.c > @@ -46,6 +46,7 @@ > #include <asm/types.h> > #include <linux/atomic.h> > #include <linux/fs.h> > +#include <linux/dcache.h> > #include <linux/namei.h> > #include <linux/mm.h> > #include <linux/export.h> > @@ -68,6 +69,7 @@ > #include <linux/capability.h> > #include <linux/fs_struct.h> > #include <linux/compat.h> > +#include <linux/sched.h> > > #include "audit.h" > > @@ -592,6 +594,35 @@ static int audit_field_compare(struct task_struct *tsk, > return 0; > } > > +int audit_match_exe(struct task_struct *tsk, struct audit_field *f) > +{ > + int result = 0; > + struct mm_struct *mm; > + struct vm_area_struct *vma; > + > + if (!tsk) > + goto out; > + > + mm = tsk->mm; > + if (!mm) > + goto out; > + > + down_read(&mm->mmap_sem); > + vma = mm->mmap; > + while (vma) { > + if ((vma->vm_flags & VM_EXECUTABLE) && > + vma->vm_file) { > + struct inode *ino = > vma->vm_file->f_path.dentry->d_inode; > + result = audit_comparator(ino->i_ino, f->op, f->val); > + break; > + } > + vma = vma->vm_next; > + } > + up_read(&mm->mmap_sem); > +out: > + return result; > +} > + > /* Determine if any context name data matches a rule's watch data */ > /* Compare a task_struct with an audit_rule. Return 1 on match, 0 > * otherwise. > @@ -629,6 +660,22 @@ static int audit_filter_rules(struct task_struct *tsk, > result = audit_comparator(ctx->ppid, f->op, > f->val); > } > break; > + case AUDIT_EXE: > + result = audit_match_exe(tsk, f); > + break; > + case AUDIT_EXE_CHILDREN: > + { > + struct task_struct *ptsk; > + for (ptsk = tsk; > + ptsk->parent->pid > 0; > + ptsk = find_task_by_vpid(ptsk->parent->pid)) { > + if (audit_match_exe(ptsk, f)) { > + ++result; > + break; > + } > + } > + } > + break; > case AUDIT_UID: > result = audit_comparator(cred->uid, f->op, f->val); > break; > -- > 1.7.7.3 - RGB -- Richard Guy Briggs <rbri...@redhat.com> Senior Software Engineer Kernel Security AMER ENG Base Operating Systems Remote, Ottawa, Canada Voice: +1.647.777.2635 Internal: (81) 32635 Alt: +1.613.693.0684x3545 -- Linux-audit mailing list Linux-audit@redhat.com https://www.redhat.com/mailman/listinfo/linux-audit