Linux-audit Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH V6 4/4] audit: avoid double copying the audit_exe path string
From: Richard Guy Briggs @ 2015-07-17 16:48 UTC (permalink / raw)
  To: Paul Moore; +Cc: linux-audit, linux-kernel
In-Reply-To: <4796630.rR8ukBJnXA@sifl>

On 15/07/16, Paul Moore wrote:
> On Thursday, July 16, 2015 10:01:30 PM Eric Paris wrote:
> > I have to admit, I'm partial to not merging this (with the other
> > patches).  Changing object lifetimes in what i seem to remember is long
> > standing code (auditfilter, not auditexe) seems to me like something we
> > really would want to be git bisectable, not mushed with an unrelated
> > feature addition. But it ain't my tree   :)
> 
> It's been a long day, and maybe I'm missing something here, but this patch 
> only affects the new code, no?

Correct.  However, it aims to follow the approach used in watch and tree
code, rather than making yet another copy.

> > On Thu, 2015-07-16 at 22:01 -0400, Richard Guy Briggs wrote:
> > > On 15/07/16, Paul Moore wrote:
> > > > On Tuesday, July 14, 2015 11:50:26 AM Richard Guy Briggs wrote:
> > > > > Make this interface consistent with watch and filter key,
> > > > > avoiding the extra
> > > > > string copy and simply consume the new string pointer.
> > > > > 
> > > > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > > > ---
> > > > > 
> > > > >  kernel/audit_exe.c      |    8 ++++++--
> > > > >  kernel/audit_fsnotify.c |    9 +--------
> > > > >  kernel/auditfilter.c    |    2 +-
> > > > >  3 files changed, 8 insertions(+), 11 deletions(-)
> > > > 
> > > > Merge this patch too, there is no reason why these needs to be its
> > > > own patch.
> > > 
> > > I wanted to keep this patch seperate until it is well understood and
> > > accepted rather than mix it in.
> > > 
> > > I'm fine merging it if you prefer.
> > > 
> > > > > diff --git a/kernel/audit_exe.c b/kernel/audit_exe.c
> > > > > index 75ad4f2..09e4eb4 100644
> > > > > --- a/kernel/audit_exe.c
> > > > > +++ b/kernel/audit_exe.c
> > > > > @@ -27,11 +27,15 @@ int audit_dupe_exe(struct audit_krule *new,
> > > > > struct
> > > > > audit_krule *old) struct audit_fsnotify_mark *audit_mark;
> > > > > 
> > > > >  	char *pathname;
> > > > > 
> > > > > -	pathname = audit_mark_path(old->exe);
> > > > > +	pathname = kstrdup(audit_mark_path(old->exe),
> > > > > GFP_KERNEL);
> > > > > +	if (!pathname)
> > > > > +		return -ENOMEM;
> > > > > 
> > > > >  	audit_mark = audit_alloc_mark(new, pathname,
> > > > > 
> > > > > strlen(pathname));
> > > > > -	if (IS_ERR(audit_mark))
> > > > > +	if (IS_ERR(audit_mark)) {
> > > > > +		kfree(pathname);
> > > > > 
> > > > >  		return PTR_ERR(audit_mark);
> > > > > 
> > > > > +	}
> > > > > 
> > > > >  	new->exe = audit_mark;
> > > > >  	
> > > > >  	return 0;
> > > > > 
> > > > > diff --git a/kernel/audit_fsnotify.c b/kernel/audit_fsnotify.c
> > > > > index a4e7b16..e57e08a 100644
> > > > > --- a/kernel/audit_fsnotify.c
> > > > > +++ b/kernel/audit_fsnotify.c
> > > > > @@ -94,7 +94,6 @@ struct audit_fsnotify_mark
> > > > > *audit_alloc_mark(struct
> > > > > audit_krule *krule, char *pa struct dentry *dentry;
> > > > > 
> > > > >  	struct inode *inode;
> > > > >  	unsigned long ino;
> > > > > 
> > > > > -	char *local_pathname;
> > > > > 
> > > > >  	dev_t dev;
> > > > >  	int ret;
> > > > > 
> > > > > @@ -115,21 +114,15 @@ struct audit_fsnotify_mark
> > > > > *audit_alloc_mark(struct
> > > > > audit_krule *krule, char *pa ino = dentry->d_inode->i_ino;
> > > > > 
> > > > >  	}
> > > > > 
> > > > > -	audit_mark = ERR_PTR(-ENOMEM);
> > > > > -	local_pathname = kstrdup(pathname, GFP_KERNEL);
> > > > > -	if (!local_pathname)
> > > > > -		goto out;
> > > > > -
> > > > > 
> > > > >  	audit_mark = kzalloc(sizeof(*audit_mark), GFP_KERNEL);
> > > > >  	if (unlikely(!audit_mark)) {
> > > > > 
> > > > > -		kfree(local_pathname);
> > > > > 
> > > > >  		audit_mark = ERR_PTR(-ENOMEM);
> > > > >  		goto out;
> > > > >  	
> > > > >  	}
> > > > >  	
> > > > >  	fsnotify_init_mark(&audit_mark->mark,
> > > > > 
> > > > > audit_fsnotify_free_mark);
> > > > > 
> > > > >  	audit_mark->mark.mask = AUDIT_FS_EVENTS;
> > > > > 
> > > > > -	audit_mark->path = local_pathname;
> > > > > +	audit_mark->path = pathname;
> > > > > 
> > > > >  	audit_mark->ino = ino;
> > > > >  	audit_mark->dev = dev;
> > > > >  	audit_mark->rule = krule;
> > > > > 
> > > > > diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
> > > > > index f65c97f..f46ed69 100644
> > > > > --- a/kernel/auditfilter.c
> > > > > +++ b/kernel/auditfilter.c
> > > > > @@ -559,8 +559,8 @@ static struct audit_entry
> > > > > *audit_data_to_entry(struct
> > > > > audit_rule_data *data, entry->rule.buflen += f->val;
> > > > > 
> > > > >  			audit_mark = audit_alloc_mark(&entry
> > > > > 
> > > > > ->rule, str, f->val);
> > > > > -			kfree(str);
> > > > > 
> > > > >  			if (IS_ERR(audit_mark)) {
> > > > > 
> > > > > +				kfree(str);
> > > > > 
> > > > >  				err = PTR_ERR(audit_mark);
> > > > >  				goto exit_free;
> > > > >  			
> > > > >  			}
> 
> -- 
> paul moore
> security @ redhat
> 

- RGB

--
Richard Guy Briggs <rbriggs@redhat.com>
Senior Software Engineer, Kernel Security, AMER ENG Base Operating Systems, Red Hat
Remote, Ottawa, Canada
Voice: +1.647.777.2635, Internal: (81) 32635, Alt: +1.613.693.0684x3545

^ permalink raw reply

* Re: [PATCH V6 4/4] audit: avoid double copying the audit_exe path string
From: Richard Guy Briggs @ 2015-07-17 16:18 UTC (permalink / raw)
  To: Eric Paris; +Cc: Paul Moore, linux-audit, linux-kernel, sgrubb, pmoody
In-Reply-To: <1437102090.18955.93.camel@redhat.com>

On 15/07/16, Eric Paris wrote:
> I have to admit, I'm partial to not merging this (with the other
> patches).  Changing object lifetimes in what i seem to remember is long
> standing code (auditfilter, not auditexe) seems to me like something we
> really would want to be git bisectable, not mushed with an unrelated
> feature addition. But it ain't my tree   :)

So maybe even fixing this before applying the audit exe stuff has
merit...

> -Eric
> 
> On Thu, 2015-07-16 at 22:01 -0400, Richard Guy Briggs wrote:
> > On 15/07/16, Paul Moore wrote:
> > > On Tuesday, July 14, 2015 11:50:26 AM Richard Guy Briggs wrote:
> > > > Make this interface consistent with watch and filter key, 
> > > > avoiding the extra
> > > > string copy and simply consume the new string pointer.
> > > > 
> > > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > > ---
> > > >  kernel/audit_exe.c      |    8 ++++++--
> > > >  kernel/audit_fsnotify.c |    9 +--------
> > > >  kernel/auditfilter.c    |    2 +-
> > > >  3 files changed, 8 insertions(+), 11 deletions(-)
> > > 
> > > Merge this patch too, there is no reason why these needs to be its 
> > > own patch.
> > 
> > I wanted to keep this patch seperate until it is well understood and
> > accepted rather than mix it in.
> > 
> > I'm fine merging it if you prefer.
> > 
> > > > diff --git a/kernel/audit_exe.c b/kernel/audit_exe.c
> > > > index 75ad4f2..09e4eb4 100644
> > > > --- a/kernel/audit_exe.c
> > > > +++ b/kernel/audit_exe.c
> > > > @@ -27,11 +27,15 @@ int audit_dupe_exe(struct audit_krule *new, 
> > > > struct
> > > > audit_krule *old) struct audit_fsnotify_mark *audit_mark;
> > > >  	char *pathname;
> > > > 
> > > > -	pathname = audit_mark_path(old->exe);
> > > > +	pathname = kstrdup(audit_mark_path(old->exe), 
> > > > GFP_KERNEL);
> > > > +	if (!pathname)
> > > > +		return -ENOMEM;
> > > > 
> > > >  	audit_mark = audit_alloc_mark(new, pathname, 
> > > > strlen(pathname));
> > > > -	if (IS_ERR(audit_mark))
> > > > +	if (IS_ERR(audit_mark)) {
> > > > +		kfree(pathname);
> > > >  		return PTR_ERR(audit_mark);
> > > > +	}
> > > >  	new->exe = audit_mark;
> > > > 
> > > >  	return 0;
> > > > diff --git a/kernel/audit_fsnotify.c b/kernel/audit_fsnotify.c
> > > > index a4e7b16..e57e08a 100644
> > > > --- a/kernel/audit_fsnotify.c
> > > > +++ b/kernel/audit_fsnotify.c
> > > > @@ -94,7 +94,6 @@ struct audit_fsnotify_mark 
> > > > *audit_alloc_mark(struct
> > > > audit_krule *krule, char *pa struct dentry *dentry;
> > > >  	struct inode *inode;
> > > >  	unsigned long ino;
> > > > -	char *local_pathname;
> > > >  	dev_t dev;
> > > >  	int ret;
> > > > 
> > > > @@ -115,21 +114,15 @@ struct audit_fsnotify_mark 
> > > > *audit_alloc_mark(struct
> > > > audit_krule *krule, char *pa ino = dentry->d_inode->i_ino;
> > > >  	}
> > > > 
> > > > -	audit_mark = ERR_PTR(-ENOMEM);
> > > > -	local_pathname = kstrdup(pathname, GFP_KERNEL);
> > > > -	if (!local_pathname)
> > > > -		goto out;
> > > > -
> > > >  	audit_mark = kzalloc(sizeof(*audit_mark), GFP_KERNEL);
> > > >  	if (unlikely(!audit_mark)) {
> > > > -		kfree(local_pathname);
> > > >  		audit_mark = ERR_PTR(-ENOMEM);
> > > >  		goto out;
> > > >  	}
> > > > 
> > > >  	fsnotify_init_mark(&audit_mark->mark, 
> > > > audit_fsnotify_free_mark);
> > > >  	audit_mark->mark.mask = AUDIT_FS_EVENTS;
> > > > -	audit_mark->path = local_pathname;
> > > > +	audit_mark->path = pathname;
> > > >  	audit_mark->ino = ino;
> > > >  	audit_mark->dev = dev;
> > > >  	audit_mark->rule = krule;
> > > > diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
> > > > index f65c97f..f46ed69 100644
> > > > --- a/kernel/auditfilter.c
> > > > +++ b/kernel/auditfilter.c
> > > > @@ -559,8 +559,8 @@ static struct audit_entry 
> > > > *audit_data_to_entry(struct
> > > > audit_rule_data *data, entry->rule.buflen += f->val;
> > > > 
> > > >  			audit_mark = audit_alloc_mark(&entry
> > > > ->rule, str, f->val);
> > > > -			kfree(str);
> > > >  			if (IS_ERR(audit_mark)) {
> > > > +				kfree(str);
> > > >  				err = PTR_ERR(audit_mark);
> > > >  				goto exit_free;
> > > >  			}
> > > 

- RGB

--
Richard Guy Briggs <rbriggs@redhat.com>
Senior Software Engineer, Kernel Security, AMER ENG Base Operating Systems, Red Hat
Remote, Ottawa, Canada
Voice: +1.647.777.2635, Internal: (81) 32635, Alt: +1.613.693.0684x3545

^ permalink raw reply

* Re: [PATCH V6 1/4] audit: implement audit by executable
From: Richard Guy Briggs @ 2015-07-17 15:33 UTC (permalink / raw)
  To: Paul Moore; +Cc: linux-audit, linux-kernel, Eric Paris, sgrubb, pmoody
In-Reply-To: <1935273.GTuYxx5kcM@sifl>

On 15/07/16, Paul Moore wrote:
> On Tuesday, July 14, 2015 11:50:23 AM Richard Guy Briggs wrote:
> > From: Eric Paris <eparis@redhat.com>
> > 
> > This patch implements the ability to filter on the executable.  It is
> > clearly incomplete!  This patch adds the inode/dev of the executable at
> > the moment the rule is loaded.  It does not update if the executable is
> > updated/moved/whatever.  That should be added.  But at this moment, this
> > patch works.
> 
> This needs work.  Either this patch is incomplete as the description says, in 
> which case I'm not going to merge it, or the description is out of date and 
> needs to be updated.

It is pretty close to the original, so the description is valid, however
combining this patch with 3/4 and 4/4 triggers a rewrite.

> If later patches in the series fix deficiencies in this patch (I haven't 
> gotten past this description yet) then we should consider merging some of the 
> patches together so they are more useful.

Ok, no problem.  (More below...)

> > RGB: Explicitly declare prototypes as extern.
> > RGB: Rename audit_dup_exe() to audit_dupe_exe() consistent with rule, watch,
> > lsm_field.
> > 
> > Based-on-user-interface-by: Richard Guy Briggs <rgb@redhat.com>
> > Based-on-idea-by: Peter Moody <pmoody@google.com>
> 
> I'm not fully up on the different patch metadata the cool kids are using these 
> days, but I think it is okay to simply credit Peter in the patch description 
> and omit the two lines above.  Giving credit is important, but these metadata 
> tags are a bit silly in my opinion.

Fair enough.  If it doesn't need to be machine-readable, I'll merge it
into the patch description prose.

> > Cc: pmoody@google.com
> > Signed-off-by: Eric Paris <eparis@redhat.com>
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> 
> It has been a while since I've looked at Eric's original patch, but 
> considering considering some of the work involved, I think it is reasonable to 
> claim this patch as your own and credit Eric in the patch description.

I left it in his authorship since all I did was declare the prototypes
explicitly as external and renamed one funciton by one letter.  I didn't
think that meritted claiming authorhship, but if I merge it as you
recommend and makes sense to me, there's no reason not to assume
authorship.

> > diff --git a/kernel/audit.h b/kernel/audit.h
> > index d641f9b..3aca24f 100644
> > --- a/kernel/audit.h
> > +++ b/kernel/audit.h
> > @@ -278,6 +286,30 @@ extern int audit_watch_compare(struct audit_watch
> > *watch, unsigned long ino, dev #define audit_watch_path(w) ""
> >  #define audit_watch_compare(w, i, d) 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_dupe_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;
> > +}
> >  #endif /* CONFIG_AUDIT_WATCH */
> 
> Not a big fan of the BUG() calls in the stubs above, let's get rid of them.  

Ok, that way I can more easily convert them to #defines.

> Yes, I know some other audit stubs are defined as BUG(), or similar, those 
> aren't a good idea either, but they are already there ...

Ok, cleanup patch later...

> > diff --git a/kernel/audit_exe.c b/kernel/audit_exe.c
> > new file mode 100644
> > index 0000000..d4cc8b5
> > --- /dev/null
> > +++ b/kernel/audit_exe.c
> > @@ -0,0 +1,109 @@
> > +/* audit_exe.c -- filtering of audit events
> > + *
> > + * Copyright 2014-2015 Red Hat, Inc.
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License as published by
> > + * the Free Software Foundation; either version 2 of the License, or
> > + * (at your option) any later version.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> > +
> > +#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;
> 
> You don't need the dev and ino variables here, just move the kmalloc() to just 
> after the dentry->d_inode check ... or put it after the sanity checks, 
> although you'll have to be careful to free it on error.

I'll take a closer look.  As referenced elsewhere, I agree a helper
function may be useful.

> > +	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);
> > +}
> 
> Not your fault, and nothing to change here, but I really hate how audit dups 
> strings outside the rule creation functions, but frees the strings in the rule 
> free routines; it's almost asking to be misused.

Again, cleanup patch later maybe...

> > +char *audit_exe_path(struct audit_exe *exe)
> > +{
> > +	return exe->pathname;
> > +}
> > +
> > +int audit_dupe_exe(struct audit_krule *new, struct audit_krule *old)
> > +{
> > +	struct audit_exe *exe;
> > +
> > +	exe = kmalloc(sizeof(*exe), GFP_KERNEL);
> > +	if (!exe)
> > +		return -ENOMEM;
> > +
> > +	exe->pathname = kstrdup(old->exe->pathname, GFP_KERNEL);
> > +	if (!exe->pathname) {
> > +		kfree(exe);
> > +		return -ENOMEM;
> > +	}
> > +
> > +	exe->ino = old->exe->ino;
> > +	exe->dev = old->exe->dev;
> > +	new->exe = exe;
> > +
> > +	return 0;
> > +}
> > +
> > +int audit_exe_compare(struct task_struct *tsk, struct audit_exe *exe)
> > +{
> > +	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;
> > +}
> 
> I suspect Eric put the above functions in a separate file to ease development 
> (no need to work about messy porting as upstream moved on), but I see no 
> reason why these functions couldn't be folded into auditfilter.c.

I thought it made sense where Eric put it.  It somewhat parallelled the
watch and tree code.  It might be tempting to put it in
audit_fsnotify.c, but I don't really want to overload that, since the
fsnotify code may be used to simpify the watch code in the future.  When
we're done after 3/4, audit_exe.c is down to 50 lines...

Mind you, auditsc.c is a bit overloaded with stuff that doesn't
necessarily belong there...

> > diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> > index 9fb9d1c..bf745c7 100644
> > --- a/kernel/auditsc.c
> > +++ b/kernel/auditsc.c
> > @@ -48,6 +48,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>
> > @@ -71,6 +72,7 @@
> >  #include <linux/capability.h>
> >  #include <linux/fs_struct.h>
> >  #include <linux/compat.h>
> > +#include <linux/sched.h>
> >  #include <linux/ctype.h>
> >  #include <linux/string.h>
> >  #include <uapi/linux/limits.h>
> > @@ -466,6 +468,20 @@ static int audit_filter_rules(struct task_struct *tsk,
> >  				result = audit_comparator(ctx->ppid, f->op, f->val);
> >  			}
> >  			break;
> > +		case AUDIT_EXE:
> > +			result = audit_exe_compare(tsk, rule->exe);
> > +			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_exe_compare(ptsk, rule->exe)) {
> > +					++result;
> > +					break;
> > +				}
> > +			}
> > +		}
> > +			break;
> 
> I don't completely understand the point of AUDIT_EXE_CHILDREN filter, what 
> problem are we trying to solve?  It checks to see if there is an executable 
> match starting with the current process and walking up the process' parents in 
> the current pid namespace?

Say we want to monitor /usr/sbin/apache2 and all its spawned processes.
Set up a rule that uses AUDIT_EXE_CHILDREN with /usr/sbin/apache2, then
when it spawns a cgi running perl or php, those actions will be caught.

> Help me understand what this accomplishes, I'm a little tried right now and I 
> just don't get it.

This was Peter Moody's idea and it made sense, so we kept it.

> paul moore

- RGB

--
Richard Guy Briggs <rbriggs@redhat.com>
Senior Software Engineer, Kernel Security, AMER ENG Base Operating Systems, Red Hat
Remote, Ottawa, Canada
Voice: +1.647.777.2635, Internal: (81) 32635, Alt: +1.613.693.0684x3545

^ permalink raw reply

* Re: [PATCH V6 4/4] audit: avoid double copying the audit_exe path string
From: Paul Moore @ 2015-07-17  3:24 UTC (permalink / raw)
  To: Eric Paris; +Cc: Richard Guy Briggs, linux-audit, linux-kernel, sgrubb
In-Reply-To: <1437102090.18955.93.camel@redhat.com>

On Thursday, July 16, 2015 10:01:30 PM Eric Paris wrote:
> I have to admit, I'm partial to not merging this (with the other
> patches).  Changing object lifetimes in what i seem to remember is long
> standing code (auditfilter, not auditexe) seems to me like something we
> really would want to be git bisectable, not mushed with an unrelated
> feature addition. But it ain't my tree   :)

It's been a long day, and maybe I'm missing something here, but this patch 
only affects the new code, no?

> On Thu, 2015-07-16 at 22:01 -0400, Richard Guy Briggs wrote:
> > On 15/07/16, Paul Moore wrote:
> > > On Tuesday, July 14, 2015 11:50:26 AM Richard Guy Briggs wrote:
> > > > Make this interface consistent with watch and filter key,
> > > > avoiding the extra
> > > > string copy and simply consume the new string pointer.
> > > > 
> > > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > > ---
> > > > 
> > > >  kernel/audit_exe.c      |    8 ++++++--
> > > >  kernel/audit_fsnotify.c |    9 +--------
> > > >  kernel/auditfilter.c    |    2 +-
> > > >  3 files changed, 8 insertions(+), 11 deletions(-)
> > > 
> > > Merge this patch too, there is no reason why these needs to be its
> > > own patch.
> > 
> > I wanted to keep this patch seperate until it is well understood and
> > accepted rather than mix it in.
> > 
> > I'm fine merging it if you prefer.
> > 
> > > > diff --git a/kernel/audit_exe.c b/kernel/audit_exe.c
> > > > index 75ad4f2..09e4eb4 100644
> > > > --- a/kernel/audit_exe.c
> > > > +++ b/kernel/audit_exe.c
> > > > @@ -27,11 +27,15 @@ int audit_dupe_exe(struct audit_krule *new,
> > > > struct
> > > > audit_krule *old) struct audit_fsnotify_mark *audit_mark;
> > > > 
> > > >  	char *pathname;
> > > > 
> > > > -	pathname = audit_mark_path(old->exe);
> > > > +	pathname = kstrdup(audit_mark_path(old->exe),
> > > > GFP_KERNEL);
> > > > +	if (!pathname)
> > > > +		return -ENOMEM;
> > > > 
> > > >  	audit_mark = audit_alloc_mark(new, pathname,
> > > > 
> > > > strlen(pathname));
> > > > -	if (IS_ERR(audit_mark))
> > > > +	if (IS_ERR(audit_mark)) {
> > > > +		kfree(pathname);
> > > > 
> > > >  		return PTR_ERR(audit_mark);
> > > > 
> > > > +	}
> > > > 
> > > >  	new->exe = audit_mark;
> > > >  	
> > > >  	return 0;
> > > > 
> > > > diff --git a/kernel/audit_fsnotify.c b/kernel/audit_fsnotify.c
> > > > index a4e7b16..e57e08a 100644
> > > > --- a/kernel/audit_fsnotify.c
> > > > +++ b/kernel/audit_fsnotify.c
> > > > @@ -94,7 +94,6 @@ struct audit_fsnotify_mark
> > > > *audit_alloc_mark(struct
> > > > audit_krule *krule, char *pa struct dentry *dentry;
> > > > 
> > > >  	struct inode *inode;
> > > >  	unsigned long ino;
> > > > 
> > > > -	char *local_pathname;
> > > > 
> > > >  	dev_t dev;
> > > >  	int ret;
> > > > 
> > > > @@ -115,21 +114,15 @@ struct audit_fsnotify_mark
> > > > *audit_alloc_mark(struct
> > > > audit_krule *krule, char *pa ino = dentry->d_inode->i_ino;
> > > > 
> > > >  	}
> > > > 
> > > > -	audit_mark = ERR_PTR(-ENOMEM);
> > > > -	local_pathname = kstrdup(pathname, GFP_KERNEL);
> > > > -	if (!local_pathname)
> > > > -		goto out;
> > > > -
> > > > 
> > > >  	audit_mark = kzalloc(sizeof(*audit_mark), GFP_KERNEL);
> > > >  	if (unlikely(!audit_mark)) {
> > > > 
> > > > -		kfree(local_pathname);
> > > > 
> > > >  		audit_mark = ERR_PTR(-ENOMEM);
> > > >  		goto out;
> > > >  	
> > > >  	}
> > > >  	
> > > >  	fsnotify_init_mark(&audit_mark->mark,
> > > > 
> > > > audit_fsnotify_free_mark);
> > > > 
> > > >  	audit_mark->mark.mask = AUDIT_FS_EVENTS;
> > > > 
> > > > -	audit_mark->path = local_pathname;
> > > > +	audit_mark->path = pathname;
> > > > 
> > > >  	audit_mark->ino = ino;
> > > >  	audit_mark->dev = dev;
> > > >  	audit_mark->rule = krule;
> > > > 
> > > > diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
> > > > index f65c97f..f46ed69 100644
> > > > --- a/kernel/auditfilter.c
> > > > +++ b/kernel/auditfilter.c
> > > > @@ -559,8 +559,8 @@ static struct audit_entry
> > > > *audit_data_to_entry(struct
> > > > audit_rule_data *data, entry->rule.buflen += f->val;
> > > > 
> > > >  			audit_mark = audit_alloc_mark(&entry
> > > > 
> > > > ->rule, str, f->val);
> > > > -			kfree(str);
> > > > 
> > > >  			if (IS_ERR(audit_mark)) {
> > > > 
> > > > +				kfree(str);
> > > > 
> > > >  				err = PTR_ERR(audit_mark);
> > > >  				goto exit_free;
> > > >  			
> > > >  			}

-- 
paul moore
security @ redhat

^ permalink raw reply

* Re: [PATCH V6 4/4] audit: avoid double copying the audit_exe path string
From: Eric Paris @ 2015-07-17  3:01 UTC (permalink / raw)
  To: Richard Guy Briggs, Paul Moore; +Cc: linux-audit, linux-kernel, sgrubb, pmoody
In-Reply-To: <20150717020128.GF32473@madcap2.tricolour.ca>

I have to admit, I'm partial to not merging this (with the other
patches).  Changing object lifetimes in what i seem to remember is long
standing code (auditfilter, not auditexe) seems to me like something we
really would want to be git bisectable, not mushed with an unrelated
feature addition. But it ain't my tree   :)

-Eric

On Thu, 2015-07-16 at 22:01 -0400, Richard Guy Briggs wrote:
> On 15/07/16, Paul Moore wrote:
> > On Tuesday, July 14, 2015 11:50:26 AM Richard Guy Briggs wrote:
> > > Make this interface consistent with watch and filter key, 
> > > avoiding the extra
> > > string copy and simply consume the new string pointer.
> > > 
> > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > ---
> > >  kernel/audit_exe.c      |    8 ++++++--
> > >  kernel/audit_fsnotify.c |    9 +--------
> > >  kernel/auditfilter.c    |    2 +-
> > >  3 files changed, 8 insertions(+), 11 deletions(-)
> > 
> > Merge this patch too, there is no reason why these needs to be its 
> > own patch.
> 
> I wanted to keep this patch seperate until it is well understood and
> accepted rather than mix it in.
> 
> I'm fine merging it if you prefer.
> 
> > > diff --git a/kernel/audit_exe.c b/kernel/audit_exe.c
> > > index 75ad4f2..09e4eb4 100644
> > > --- a/kernel/audit_exe.c
> > > +++ b/kernel/audit_exe.c
> > > @@ -27,11 +27,15 @@ int audit_dupe_exe(struct audit_krule *new, 
> > > struct
> > > audit_krule *old) struct audit_fsnotify_mark *audit_mark;
> > >  	char *pathname;
> > > 
> > > -	pathname = audit_mark_path(old->exe);
> > > +	pathname = kstrdup(audit_mark_path(old->exe), 
> > > GFP_KERNEL);
> > > +	if (!pathname)
> > > +		return -ENOMEM;
> > > 
> > >  	audit_mark = audit_alloc_mark(new, pathname, 
> > > strlen(pathname));
> > > -	if (IS_ERR(audit_mark))
> > > +	if (IS_ERR(audit_mark)) {
> > > +		kfree(pathname);
> > >  		return PTR_ERR(audit_mark);
> > > +	}
> > >  	new->exe = audit_mark;
> > > 
> > >  	return 0;
> > > diff --git a/kernel/audit_fsnotify.c b/kernel/audit_fsnotify.c
> > > index a4e7b16..e57e08a 100644
> > > --- a/kernel/audit_fsnotify.c
> > > +++ b/kernel/audit_fsnotify.c
> > > @@ -94,7 +94,6 @@ struct audit_fsnotify_mark 
> > > *audit_alloc_mark(struct
> > > audit_krule *krule, char *pa struct dentry *dentry;
> > >  	struct inode *inode;
> > >  	unsigned long ino;
> > > -	char *local_pathname;
> > >  	dev_t dev;
> > >  	int ret;
> > > 
> > > @@ -115,21 +114,15 @@ struct audit_fsnotify_mark 
> > > *audit_alloc_mark(struct
> > > audit_krule *krule, char *pa ino = dentry->d_inode->i_ino;
> > >  	}
> > > 
> > > -	audit_mark = ERR_PTR(-ENOMEM);
> > > -	local_pathname = kstrdup(pathname, GFP_KERNEL);
> > > -	if (!local_pathname)
> > > -		goto out;
> > > -
> > >  	audit_mark = kzalloc(sizeof(*audit_mark), GFP_KERNEL);
> > >  	if (unlikely(!audit_mark)) {
> > > -		kfree(local_pathname);
> > >  		audit_mark = ERR_PTR(-ENOMEM);
> > >  		goto out;
> > >  	}
> > > 
> > >  	fsnotify_init_mark(&audit_mark->mark, 
> > > audit_fsnotify_free_mark);
> > >  	audit_mark->mark.mask = AUDIT_FS_EVENTS;
> > > -	audit_mark->path = local_pathname;
> > > +	audit_mark->path = pathname;
> > >  	audit_mark->ino = ino;
> > >  	audit_mark->dev = dev;
> > >  	audit_mark->rule = krule;
> > > diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
> > > index f65c97f..f46ed69 100644
> > > --- a/kernel/auditfilter.c
> > > +++ b/kernel/auditfilter.c
> > > @@ -559,8 +559,8 @@ static struct audit_entry 
> > > *audit_data_to_entry(struct
> > > audit_rule_data *data, entry->rule.buflen += f->val;
> > > 
> > >  			audit_mark = audit_alloc_mark(&entry
> > > ->rule, str, f->val);
> > > -			kfree(str);
> > >  			if (IS_ERR(audit_mark)) {
> > > +				kfree(str);
> > >  				err = PTR_ERR(audit_mark);
> > >  				goto exit_free;
> > >  			}
> > 

^ permalink raw reply

* Re: [PATCH V6 4/4] audit: avoid double copying the audit_exe path string
From: Paul Moore @ 2015-07-17  2:42 UTC (permalink / raw)
  To: Richard Guy Briggs; +Cc: linux-audit, linux-kernel, sgrubb, eparis
In-Reply-To: <20150717020128.GF32473@madcap2.tricolour.ca>

On Thursday, July 16, 2015 10:01:28 PM Richard Guy Briggs wrote:
> On 15/07/16, Paul Moore wrote:
> > On Tuesday, July 14, 2015 11:50:26 AM Richard Guy Briggs wrote:
> > > Make this interface consistent with watch and filter key, avoiding the
> > > extra string copy and simply consume the new string pointer.
> > > 
> > > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > > ---
> > > 
> > >  kernel/audit_exe.c      |    8 ++++++--
> > >  kernel/audit_fsnotify.c |    9 +--------
> > >  kernel/auditfilter.c    |    2 +-
> > >  3 files changed, 8 insertions(+), 11 deletions(-)
> > 
> > Merge this patch too, there is no reason why these needs to be its own
> > patch.
> I wanted to keep this patch seperate until it is well understood and
> accepted rather than mix it in.
> 
> I'm fine merging it if you prefer.

Like I mentioned in one of the patches, I'm not really a fan of how audit 
handles the alloc/free'ing of some things, but I think it is more important to 
be consistent within audit itself.

At some point we'll fix this, but it doesn't have to be now.  Go ahead and 
merge the patch with the others.

-- 
paul moore
security @ redhat

^ permalink raw reply

* Re: [PATCH V6 3/4] audit: convert audit_exe to audit_fsnotify
From: Richard Guy Briggs @ 2015-07-17  2:02 UTC (permalink / raw)
  To: Paul Moore; +Cc: linux-audit, linux-kernel, sgrubb, eparis
In-Reply-To: <3828355.kbLCDqrcbq@sifl>

On 15/07/16, Paul Moore wrote:
> On Tuesday, July 14, 2015 11:50:25 AM Richard Guy Briggs wrote:
> > 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 <eparis@redhat.com>
> > 
> > RGB: Clean up exe with similar interface as watch and tree.
> > RGB: Clean up audit exe mark just before audit_free_rule() rather than in it
> > to avoid mutex in software interrupt context.
> > 
> > Based-on-code-by: Eric Paris <eparis@redhat.com>
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> 
> Ah, good, the fix that patch 1/4 was hoping for is finally happening :)
> 
> Since we're not getting paid by the number of patches in a patch set, I think 
> I would prefer to see the fsnotify implementation as the first patch and the 
> original crappy exe filter patch merged with this fixup patch.

Ah, fair enough.  Yeah, I'll do that.

> No in depth comments on this particular patch, I skimmed it but frankly it 
> makes much more sense to review this patch once you've merged the two.
> 
> > diff --git a/include/linux/audit.h b/include/linux/audit.h
> > index 95463a2..aee456f 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 491bd4b..eeaf054 100644
> > --- a/kernel/audit.h
> > +++ b/kernel/audit.h
> > @@ -51,7 +51,6 @@ enum audit_state {
> >  /* Rule lists */
> >  struct audit_watch;
> >  struct audit_fsnotify_mark;
> > -struct audit_exe;
> >  struct audit_tree;
> >  struct audit_chunk;
> > 
> > @@ -279,11 +278,8 @@ extern void audit_remove_mark(struct
> > audit_fsnotify_mark *audit_mark); extern void audit_remove_mark_rule(struct
> > audit_krule *krule);
> >  extern int audit_mark_compare(struct audit_fsnotify_mark *mark, unsigned
> > long ino, dev_t dev);
> > 
> > -extern int audit_make_exe_rule(struct audit_krule *krule, char *pathname,
> > int len, u32 op); -extern void audit_remove_exe_rule(struct audit_krule
> > *krule);
> > -extern char *audit_exe_path(struct audit_exe *exe);
> >  extern int audit_dupe_exe(struct audit_krule *new, struct audit_krule
> > *old); -extern int audit_exe_compare(struct task_struct *tsk, struct
> > audit_exe *exe); +extern int audit_exe_compare(struct task_struct *tsk,
> > struct audit_fsnotify_mark *mark);
> > 
> >  #else
> >  #define audit_put_watch(w) {}
> > @@ -302,36 +298,19 @@ static inline char *audit_mark_path(struct
> > audit_fsnotify_mark *mark) }
> >  #define audit_remove_mark(m) BUG()
> >  #define audit_remove_mark_rule(k) BUG()
> > -static inline int audit_mark_compare(struct audit_fsnotify_mark *mark,
> > unsigned long ino, dev_t dev) -{
> > -	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)
> > +static inline int audit_exe_compare(struct task_struct *tsk, struct
> > audit_fsnotify_mark *mark) {
> >  	BUG();
> > -	return "";
> > +	return -EINVAL;
> >  }
> > +
> >  static inline int audit_dupe_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 d4cc8b5..75ad4f2 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_dupe_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_tree.c b/kernel/audit_tree.c
> > index b0f9877..94ecdab 100644
> > --- a/kernel/audit_tree.c
> > +++ b/kernel/audit_tree.c
> > @@ -479,6 +479,8 @@ static void kill_rules(struct audit_tree *tree)
> >  		if (rule->tree) {
> >  			/* not a half-baked one */
> >  			audit_tree_log_remove_rule(rule);
> > +			if (entry->rule.exe)
> > +				audit_remove_mark(entry->rule.exe);
> >  			rule->tree = NULL;
> >  			list_del_rcu(&entry->list);
> >  			list_del(&entry->rule.list);
> > diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
> > index 8f123d7..4aaa393 100644
> > --- a/kernel/audit_watch.c
> > +++ b/kernel/audit_watch.c
> > @@ -312,6 +312,8 @@ static void audit_update_watch(struct audit_parent
> > *parent, list_replace(&oentry->rule.list,
> >  					     &nentry->rule.list);
> >  			}
> > +			if (oentry->rule.exe)
> > +				audit_remove_mark(oentry->rule.exe);
> > 
> >  			audit_watch_log_rule_change(r, owatch, "updated_rules");
> > 
> > @@ -342,6 +344,8 @@ static void audit_remove_parent_watches(struct
> > audit_parent *parent) list_for_each_entry_safe(r, nextr, &w->rules, rlist)
> > {
> >  			e = container_of(r, struct audit_entry, rule);
> >  			audit_watch_log_rule_change(r, w, "remove_rule");
> > +			if (e->rule.exe)
> > +				audit_remove_mark(e->rule.exe);
> >  			list_del(&r->rlist);
> >  			list_del(&r->list);
> >  			list_del_rcu(&e->list);
> > diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
> > index bbb39ec..f65c97f 100644
> > --- a/kernel/auditfilter.c
> > +++ b/kernel/auditfilter.c
> > @@ -426,6 +426,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))
> > @@ -557,11 +558,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;
> >  		}
> >  	}
> > @@ -575,6 +578,8 @@ exit_nofree:
> >  exit_free:
> >  	if (entry->rule.tree)
> >  		audit_put_tree(entry->rule.tree); /* that's the temporary one */
> > +	if (entry->rule.exe)
> > +		audit_remove_mark(entry->rule.exe); /* that's the template one */
> >  	audit_free_rule(entry);
> >  	return ERR_PTR(err);
> >  }
> > @@ -642,7 +647,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;
> >  		case AUDIT_LOGINUID_SET:
> >  			if (krule->pflags & AUDIT_LOGINUID_LEGACY && !f->val) {
> > @@ -710,8 +715,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:
> > @@ -842,6 +847,8 @@ struct audit_entry *audit_dupe_rule(struct audit_krule
> > *old) break;
> >  		}
> >  		if (err) {
> > +			if (new->exe)
> > +				audit_remove_mark(new->exe);
> >  			audit_free_rule(entry);
> >  			return ERR_PTR(err);
> >  		}
> > @@ -1008,7 +1015,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_rule(&e->rule);
> > 
> >  	list_del_rcu(&e->list);
> >  	list_del(&e->rule.list);
> > @@ -1113,8 +1120,11 @@ int audit_rule_change(int type, __u32 portid, int
> > seq, void *data, WARN_ON(1);
> >  	}
> > 
> > -	if (err || type == AUDIT_DEL_RULE)
> > +	if (err || type == AUDIT_DEL_RULE) {
> > +		if (entry->rule.exe)
> > +			audit_remove_mark(entry->rule.exe);
> >  		audit_free_rule(entry);
> > +	}
> > 
> >  	return err;
> >  }
> > @@ -1406,6 +1416,8 @@ static int update_lsm_rule(struct audit_krule *r)
> >  		return 0;
> > 
> >  	nentry = audit_dupe_rule(r);
> > +	if (entry->rule.exe)
> > +		audit_remove_mark(entry->rule.exe);
> >  	if (IS_ERR(nentry)) {
> >  		/* save the first error encountered for the
> >  		 * return value */
> 
> -- 
> paul moore
> security @ redhat
> 

- RGB

--
Richard Guy Briggs <rbriggs@redhat.com>
Senior Software Engineer, Kernel Security, AMER ENG Base Operating Systems, Red Hat
Remote, Ottawa, Canada
Voice: +1.647.777.2635, Internal: (81) 32635, Alt: +1.613.693.0684x3545

^ permalink raw reply

* Re: [PATCH V6 4/4] audit: avoid double copying the audit_exe path string
From: Richard Guy Briggs @ 2015-07-17  2:01 UTC (permalink / raw)
  To: Paul Moore; +Cc: linux-audit, linux-kernel, sgrubb, eparis, pmoody
In-Reply-To: <9338092.i1kyKho6FJ@sifl>

On 15/07/16, Paul Moore wrote:
> On Tuesday, July 14, 2015 11:50:26 AM Richard Guy Briggs wrote:
> > Make this interface consistent with watch and filter key, avoiding the extra
> > string copy and simply consume the new string pointer.
> > 
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > ---
> >  kernel/audit_exe.c      |    8 ++++++--
> >  kernel/audit_fsnotify.c |    9 +--------
> >  kernel/auditfilter.c    |    2 +-
> >  3 files changed, 8 insertions(+), 11 deletions(-)
> 
> Merge this patch too, there is no reason why these needs to be its own patch.

I wanted to keep this patch seperate until it is well understood and
accepted rather than mix it in.

I'm fine merging it if you prefer.

> > diff --git a/kernel/audit_exe.c b/kernel/audit_exe.c
> > index 75ad4f2..09e4eb4 100644
> > --- a/kernel/audit_exe.c
> > +++ b/kernel/audit_exe.c
> > @@ -27,11 +27,15 @@ int audit_dupe_exe(struct audit_krule *new, struct
> > audit_krule *old) struct audit_fsnotify_mark *audit_mark;
> >  	char *pathname;
> > 
> > -	pathname = audit_mark_path(old->exe);
> > +	pathname = kstrdup(audit_mark_path(old->exe), GFP_KERNEL);
> > +	if (!pathname)
> > +		return -ENOMEM;
> > 
> >  	audit_mark = audit_alloc_mark(new, pathname, strlen(pathname));
> > -	if (IS_ERR(audit_mark))
> > +	if (IS_ERR(audit_mark)) {
> > +		kfree(pathname);
> >  		return PTR_ERR(audit_mark);
> > +	}
> >  	new->exe = audit_mark;
> > 
> >  	return 0;
> > diff --git a/kernel/audit_fsnotify.c b/kernel/audit_fsnotify.c
> > index a4e7b16..e57e08a 100644
> > --- a/kernel/audit_fsnotify.c
> > +++ b/kernel/audit_fsnotify.c
> > @@ -94,7 +94,6 @@ struct audit_fsnotify_mark *audit_alloc_mark(struct
> > audit_krule *krule, char *pa struct dentry *dentry;
> >  	struct inode *inode;
> >  	unsigned long ino;
> > -	char *local_pathname;
> >  	dev_t dev;
> >  	int ret;
> > 
> > @@ -115,21 +114,15 @@ struct audit_fsnotify_mark *audit_alloc_mark(struct
> > audit_krule *krule, char *pa ino = dentry->d_inode->i_ino;
> >  	}
> > 
> > -	audit_mark = ERR_PTR(-ENOMEM);
> > -	local_pathname = kstrdup(pathname, GFP_KERNEL);
> > -	if (!local_pathname)
> > -		goto out;
> > -
> >  	audit_mark = kzalloc(sizeof(*audit_mark), GFP_KERNEL);
> >  	if (unlikely(!audit_mark)) {
> > -		kfree(local_pathname);
> >  		audit_mark = ERR_PTR(-ENOMEM);
> >  		goto out;
> >  	}
> > 
> >  	fsnotify_init_mark(&audit_mark->mark, audit_fsnotify_free_mark);
> >  	audit_mark->mark.mask = AUDIT_FS_EVENTS;
> > -	audit_mark->path = local_pathname;
> > +	audit_mark->path = pathname;
> >  	audit_mark->ino = ino;
> >  	audit_mark->dev = dev;
> >  	audit_mark->rule = krule;
> > diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
> > index f65c97f..f46ed69 100644
> > --- a/kernel/auditfilter.c
> > +++ b/kernel/auditfilter.c
> > @@ -559,8 +559,8 @@ static struct audit_entry *audit_data_to_entry(struct
> > audit_rule_data *data, entry->rule.buflen += f->val;
> > 
> >  			audit_mark = audit_alloc_mark(&entry->rule, str, f->val);
> > -			kfree(str);
> >  			if (IS_ERR(audit_mark)) {
> > +				kfree(str);
> >  				err = PTR_ERR(audit_mark);
> >  				goto exit_free;
> >  			}
> 
> -- 
> paul moore
> security @ redhat
> 

- RGB

--
Richard Guy Briggs <rbriggs@redhat.com>
Senior Software Engineer, Kernel Security, AMER ENG Base Operating Systems, Red Hat
Remote, Ottawa, Canada
Voice: +1.647.777.2635, Internal: (81) 32635, Alt: +1.613.693.0684x3545

^ permalink raw reply

* Re: [PATCH V6 4/4] audit: avoid double copying the audit_exe path string
From: Paul Moore @ 2015-07-17  1:56 UTC (permalink / raw)
  To: Richard Guy Briggs; +Cc: linux-audit, linux-kernel, sgrubb, eparis, pmoody
In-Reply-To: <b8eeaf2d806f039266d2a2d40e8f87f73d9bf6f2.1436823321.git.rgb@redhat.com>

On Tuesday, July 14, 2015 11:50:26 AM Richard Guy Briggs wrote:
> Make this interface consistent with watch and filter key, avoiding the extra
> string copy and simply consume the new string pointer.
> 
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> ---
>  kernel/audit_exe.c      |    8 ++++++--
>  kernel/audit_fsnotify.c |    9 +--------
>  kernel/auditfilter.c    |    2 +-
>  3 files changed, 8 insertions(+), 11 deletions(-)

Merge this patch too, there is no reason why these needs to be its own patch.

> diff --git a/kernel/audit_exe.c b/kernel/audit_exe.c
> index 75ad4f2..09e4eb4 100644
> --- a/kernel/audit_exe.c
> +++ b/kernel/audit_exe.c
> @@ -27,11 +27,15 @@ int audit_dupe_exe(struct audit_krule *new, struct
> audit_krule *old) struct audit_fsnotify_mark *audit_mark;
>  	char *pathname;
> 
> -	pathname = audit_mark_path(old->exe);
> +	pathname = kstrdup(audit_mark_path(old->exe), GFP_KERNEL);
> +	if (!pathname)
> +		return -ENOMEM;
> 
>  	audit_mark = audit_alloc_mark(new, pathname, strlen(pathname));
> -	if (IS_ERR(audit_mark))
> +	if (IS_ERR(audit_mark)) {
> +		kfree(pathname);
>  		return PTR_ERR(audit_mark);
> +	}
>  	new->exe = audit_mark;
> 
>  	return 0;
> diff --git a/kernel/audit_fsnotify.c b/kernel/audit_fsnotify.c
> index a4e7b16..e57e08a 100644
> --- a/kernel/audit_fsnotify.c
> +++ b/kernel/audit_fsnotify.c
> @@ -94,7 +94,6 @@ struct audit_fsnotify_mark *audit_alloc_mark(struct
> audit_krule *krule, char *pa struct dentry *dentry;
>  	struct inode *inode;
>  	unsigned long ino;
> -	char *local_pathname;
>  	dev_t dev;
>  	int ret;
> 
> @@ -115,21 +114,15 @@ struct audit_fsnotify_mark *audit_alloc_mark(struct
> audit_krule *krule, char *pa ino = dentry->d_inode->i_ino;
>  	}
> 
> -	audit_mark = ERR_PTR(-ENOMEM);
> -	local_pathname = kstrdup(pathname, GFP_KERNEL);
> -	if (!local_pathname)
> -		goto out;
> -
>  	audit_mark = kzalloc(sizeof(*audit_mark), GFP_KERNEL);
>  	if (unlikely(!audit_mark)) {
> -		kfree(local_pathname);
>  		audit_mark = ERR_PTR(-ENOMEM);
>  		goto out;
>  	}
> 
>  	fsnotify_init_mark(&audit_mark->mark, audit_fsnotify_free_mark);
>  	audit_mark->mark.mask = AUDIT_FS_EVENTS;
> -	audit_mark->path = local_pathname;
> +	audit_mark->path = pathname;
>  	audit_mark->ino = ino;
>  	audit_mark->dev = dev;
>  	audit_mark->rule = krule;
> diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
> index f65c97f..f46ed69 100644
> --- a/kernel/auditfilter.c
> +++ b/kernel/auditfilter.c
> @@ -559,8 +559,8 @@ static struct audit_entry *audit_data_to_entry(struct
> audit_rule_data *data, entry->rule.buflen += f->val;
> 
>  			audit_mark = audit_alloc_mark(&entry->rule, str, f->val);
> -			kfree(str);
>  			if (IS_ERR(audit_mark)) {
> +				kfree(str);
>  				err = PTR_ERR(audit_mark);
>  				goto exit_free;
>  			}

-- 
paul moore
security @ redhat

^ permalink raw reply

* Re: [PATCH V6 3/4] audit: convert audit_exe to audit_fsnotify
From: Paul Moore @ 2015-07-17  1:54 UTC (permalink / raw)
  To: Richard Guy Briggs; +Cc: linux-audit, linux-kernel, sgrubb, eparis
In-Reply-To: <2b37c4f1602bd672ee5b241c0fda57559d4a576a.1436823321.git.rgb@redhat.com>

On Tuesday, July 14, 2015 11:50:25 AM Richard Guy Briggs wrote:
> 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 <eparis@redhat.com>
> 
> RGB: Clean up exe with similar interface as watch and tree.
> RGB: Clean up audit exe mark just before audit_free_rule() rather than in it
> to avoid mutex in software interrupt context.
> 
> Based-on-code-by: Eric Paris <eparis@redhat.com>
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>

Ah, good, the fix that patch 1/4 was hoping for is finally happening :)

Since we're not getting paid by the number of patches in a patch set, I think 
I would prefer to see the fsnotify implementation as the first patch and the 
original crappy exe filter patch merged with this fixup patch.

No in depth comments on this particular patch, I skimmed it but frankly it 
makes much more sense to review this patch once you've merged the two.

> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 95463a2..aee456f 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 491bd4b..eeaf054 100644
> --- a/kernel/audit.h
> +++ b/kernel/audit.h
> @@ -51,7 +51,6 @@ enum audit_state {
>  /* Rule lists */
>  struct audit_watch;
>  struct audit_fsnotify_mark;
> -struct audit_exe;
>  struct audit_tree;
>  struct audit_chunk;
> 
> @@ -279,11 +278,8 @@ extern void audit_remove_mark(struct
> audit_fsnotify_mark *audit_mark); extern void audit_remove_mark_rule(struct
> audit_krule *krule);
>  extern int audit_mark_compare(struct audit_fsnotify_mark *mark, unsigned
> long ino, dev_t dev);
> 
> -extern int audit_make_exe_rule(struct audit_krule *krule, char *pathname,
> int len, u32 op); -extern void audit_remove_exe_rule(struct audit_krule
> *krule);
> -extern char *audit_exe_path(struct audit_exe *exe);
>  extern int audit_dupe_exe(struct audit_krule *new, struct audit_krule
> *old); -extern int audit_exe_compare(struct task_struct *tsk, struct
> audit_exe *exe); +extern int audit_exe_compare(struct task_struct *tsk,
> struct audit_fsnotify_mark *mark);
> 
>  #else
>  #define audit_put_watch(w) {}
> @@ -302,36 +298,19 @@ static inline char *audit_mark_path(struct
> audit_fsnotify_mark *mark) }
>  #define audit_remove_mark(m) BUG()
>  #define audit_remove_mark_rule(k) BUG()
> -static inline int audit_mark_compare(struct audit_fsnotify_mark *mark,
> unsigned long ino, dev_t dev) -{
> -	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)
> +static inline int audit_exe_compare(struct task_struct *tsk, struct
> audit_fsnotify_mark *mark) {
>  	BUG();
> -	return "";
> +	return -EINVAL;
>  }
> +
>  static inline int audit_dupe_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 d4cc8b5..75ad4f2 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_dupe_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_tree.c b/kernel/audit_tree.c
> index b0f9877..94ecdab 100644
> --- a/kernel/audit_tree.c
> +++ b/kernel/audit_tree.c
> @@ -479,6 +479,8 @@ static void kill_rules(struct audit_tree *tree)
>  		if (rule->tree) {
>  			/* not a half-baked one */
>  			audit_tree_log_remove_rule(rule);
> +			if (entry->rule.exe)
> +				audit_remove_mark(entry->rule.exe);
>  			rule->tree = NULL;
>  			list_del_rcu(&entry->list);
>  			list_del(&entry->rule.list);
> diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
> index 8f123d7..4aaa393 100644
> --- a/kernel/audit_watch.c
> +++ b/kernel/audit_watch.c
> @@ -312,6 +312,8 @@ static void audit_update_watch(struct audit_parent
> *parent, list_replace(&oentry->rule.list,
>  					     &nentry->rule.list);
>  			}
> +			if (oentry->rule.exe)
> +				audit_remove_mark(oentry->rule.exe);
> 
>  			audit_watch_log_rule_change(r, owatch, "updated_rules");
> 
> @@ -342,6 +344,8 @@ static void audit_remove_parent_watches(struct
> audit_parent *parent) list_for_each_entry_safe(r, nextr, &w->rules, rlist)
> {
>  			e = container_of(r, struct audit_entry, rule);
>  			audit_watch_log_rule_change(r, w, "remove_rule");
> +			if (e->rule.exe)
> +				audit_remove_mark(e->rule.exe);
>  			list_del(&r->rlist);
>  			list_del(&r->list);
>  			list_del_rcu(&e->list);
> diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
> index bbb39ec..f65c97f 100644
> --- a/kernel/auditfilter.c
> +++ b/kernel/auditfilter.c
> @@ -426,6 +426,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))
> @@ -557,11 +558,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;
>  		}
>  	}
> @@ -575,6 +578,8 @@ exit_nofree:
>  exit_free:
>  	if (entry->rule.tree)
>  		audit_put_tree(entry->rule.tree); /* that's the temporary one */
> +	if (entry->rule.exe)
> +		audit_remove_mark(entry->rule.exe); /* that's the template one */
>  	audit_free_rule(entry);
>  	return ERR_PTR(err);
>  }
> @@ -642,7 +647,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;
>  		case AUDIT_LOGINUID_SET:
>  			if (krule->pflags & AUDIT_LOGINUID_LEGACY && !f->val) {
> @@ -710,8 +715,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:
> @@ -842,6 +847,8 @@ struct audit_entry *audit_dupe_rule(struct audit_krule
> *old) break;
>  		}
>  		if (err) {
> +			if (new->exe)
> +				audit_remove_mark(new->exe);
>  			audit_free_rule(entry);
>  			return ERR_PTR(err);
>  		}
> @@ -1008,7 +1015,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_rule(&e->rule);
> 
>  	list_del_rcu(&e->list);
>  	list_del(&e->rule.list);
> @@ -1113,8 +1120,11 @@ int audit_rule_change(int type, __u32 portid, int
> seq, void *data, WARN_ON(1);
>  	}
> 
> -	if (err || type == AUDIT_DEL_RULE)
> +	if (err || type == AUDIT_DEL_RULE) {
> +		if (entry->rule.exe)
> +			audit_remove_mark(entry->rule.exe);
>  		audit_free_rule(entry);
> +	}
> 
>  	return err;
>  }
> @@ -1406,6 +1416,8 @@ static int update_lsm_rule(struct audit_krule *r)
>  		return 0;
> 
>  	nentry = audit_dupe_rule(r);
> +	if (entry->rule.exe)
> +		audit_remove_mark(entry->rule.exe);
>  	if (IS_ERR(nentry)) {
>  		/* save the first error encountered for the
>  		 * return value */

-- 
paul moore
security @ redhat

^ permalink raw reply

* Re: [PATCH V6 2/4] audit: clean simple fsnotify implementation
From: Paul Moore @ 2015-07-17  1:45 UTC (permalink / raw)
  To: Richard Guy Briggs; +Cc: linux-audit, linux-kernel, sgrubb, eparis
In-Reply-To: <267c9708b85459c06f7f5252c51760267a18fa8b.1436823321.git.rgb@redhat.com>

On Tuesday, July 14, 2015 11:50:24 AM Richard Guy Briggs wrote:
> This is to be used to audit by executable rules, but audit watches
> should be able to share this code eventually.
> 
> At the moment the audit watch code is a lot more complex, that code only
> creates one fsnotify watch per parent directory.  That 'audit_parent' in
> turn has a list of 'audit_watches' which contain the name, ino, dev of
> the specific object we care about.  This just creates one fsnotify watch
> per object we care about.  So if you watch 100 inodes in /etc this code
> will create 100 fsnotify watches on /etc.  The audit_watch code will
> instead create 1 fsnotify watch on /etc (the audit_parent) and then 100
> individual watches chained from that fsnotify mark.
> 
> We should be able to convert the audit_watch code to do one fsnotify
> mark per watch and simplify things/remove a whole lot of code.  After
> that conversion we should be able to convert the audit_fsnotify code to
> support that hierarchy if the optimization is necessary.
> 
> Signed-off-by: Eric Paris <eparis@redhat.com>
> 
> RGB: Move the access to the entry for audit_match_signal() to the beginning
> of the function in case the entry found is the same one passed in.  This
> will enable it to be used by audit_autoremove_mark_rule().
> RGB: Rename several "watch" references to "mark".
> RGB: Rename audit_remove_rule() to audit_autoremove_mark_rule().
> RGB: Put audit_alloc_mark() arguments in same order as watch, tree and
> inode. RGB: Remove space from audit log value text in
> audit_autoremove_mark_rule(). RGB: Explicitly declare prototypes as extern.
> RGB: Rename audit_remove_mark_rule() called from audit_mark_handle_event()
> to audit_autoremove_mark_rule() to avoid confusion with
> audit_remove_{watch,tree}_rule() usage.
> RGB: Add audit_remove_mark_rule() to provide similar interface as
> audit_remove_{watch,tree}_rule().
> RGB: Simplify stubs to defines.
> RGB: Rename audit_free_fsnotify_mark() to audit_fsnotify_free_mark() in
> keeping with the naming convention of inotify_free_mark(),
> dnotify_free_mark(), fanotify_free_mark(), audit_watch_free_mark().
> RGB: Return -ENOMEM rather than null in case of memory allocation failure
> for audit_mark. RGB: Rename audit_free_mark() to audit_mark_free() to avoid
> association with {i,d,fa}notify_free_mark() and audit_watch_free_mark().

Definitely enough changes here to call this your own; credit Eric in the 
description and just stick with your sign off.

> Based-on-code-by: Eric Paris <eparis@redhat.com>
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>

Based on the patch description, should this be patch 1/4 instead of 2/4?

> diff --git a/kernel/Makefile b/kernel/Makefile
> index a7ea330..397109e 100644
> --- a/kernel/Makefile
> +++ b/kernel/Makefile
> @@ -64,7 +64,7 @@ obj-$(CONFIG_SMP) += stop_machine.o
>  obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o
>  obj-$(CONFIG_AUDIT) += audit.o auditfilter.o
>  obj-$(CONFIG_AUDITSYSCALL) += auditsc.o
> -obj-$(CONFIG_AUDIT_WATCH) += audit_watch.o audit_exe.o
> +obj-$(CONFIG_AUDIT_WATCH) += audit_watch.o audit_exe.o audit_fsnotify.o
>  obj-$(CONFIG_AUDIT_TREE) += audit_tree.o
>  obj-$(CONFIG_GCOV_KERNEL) += gcov/
>  obj-$(CONFIG_KPROBES) += kprobes.o
> diff --git a/kernel/audit.h b/kernel/audit.h
> index 3aca24f..491bd4b 100644
> --- a/kernel/audit.h
> +++ b/kernel/audit.h
> @@ -286,6 +294,20 @@ extern int audit_exe_compare(struct task_struct *tsk,
> struct audit_exe *exe); #define audit_watch_path(w) ""
>  #define audit_watch_compare(w, i, d) 0
> 
> +#define audit_alloc_mark(k, p, l) (ERR_PTR(-EINVAL))
> +static inline char *audit_mark_path(struct audit_fsnotify_mark *mark)
> +{
> +	BUG();
> +	return "";
> +}
> +#define audit_remove_mark(m) BUG()
> +#define audit_remove_mark_rule(k) BUG()
> +static inline int audit_mark_compare(struct audit_fsnotify_mark *mark,
> unsigned long ino, dev_t dev) +{
> +	BUG();
> +	return 0;
> +}

No BUG(), we've got enough of those things already.

> diff --git a/kernel/audit_fsnotify.c b/kernel/audit_fsnotify.c
> new file mode 100644
> index 0000000..a4e7b16
> --- /dev/null
> +++ b/kernel/audit_fsnotify.c
> @@ -0,0 +1,253 @@
> +/* audit_fsnotify.c -- tracking inodes
> + *
> + * Copyright 2003-2009,2014-2015 Red Hat, Inc.
> + * Copyright 2005 Hewlett-Packard Development Company, L.P.
> + * Copyright 2005 IBM Corporation
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */

...

> +static void audit_fsnotify_free_mark(struct fsnotify_mark *mark)
> +{
> +	struct audit_fsnotify_mark *audit_mark;
> +
> +	audit_mark = container_of(mark, struct audit_fsnotify_mark, mark);
> +	audit_mark_free(audit_mark);
> +}

It seems like audit_fsnotify_mark_free() might be more consistent with the 
rest of the naming, yes?

> +#if 0 /* not sure if we need these... */
> +static void audit_get_mark(struct audit_fsnotify_mark *audit_mark)
> +{
> +	if (likely(audit_mark))
> +		fsnotify_get_mark(&audit_mark->mark);
> +}
> +
> +static void audit_put_mark(struct audit_fsnotify_mark *audit_mark)
> +{
> +	if (likely(audit_mark))
> +		fsnotify_put_mark(&audit_mark->mark);
> +}
> +#endif

If this code is '#if 0' let's dump it.  We need it or we don't, keeping it 
around as dead weight is dangerous.

> +char *audit_mark_path(struct audit_fsnotify_mark *mark)
> +{
> +	return mark->path;
> +}
> +
> +int audit_mark_compare(struct audit_fsnotify_mark *mark, unsigned long ino,
> dev_t dev) +{
> +	if (mark->ino == (unsigned long)-1)
> +		return 0;
> +	return (mark->ino == ino) && (mark->dev == dev);
> +}

It seems like there should be a #define for -1 inodes, did you check?  I 
generally hate magic numbers like this because I'm pretty stupid and tend to 
forget their meaning over time ....

Also, at some point we should make (or find?) some generic inode comparison 
function/macro.  I'm amazed at home many times I see (i_foo == ino && i_dev == 
dev).

> +struct audit_fsnotify_mark *audit_alloc_mark(struct audit_krule *krule,
> char *pathname, int len) +{
> +	struct audit_fsnotify_mark *audit_mark;
> +	struct path path;
> +	struct dentry *dentry;
> +	struct inode *inode;
> +	unsigned long ino;
> +	char *local_pathname;
> +	dev_t dev;
> +	int ret;
> +
> +	if (pathname[0] != '/' || pathname[len-1] == '/')
> +		return ERR_PTR(-EINVAL);
> +
> +	dentry = kern_path_locked(pathname, &path);
> +	if (IS_ERR(dentry))
> +		return (void *)dentry; /* returning an error */
> +	inode = path.dentry->d_inode;
> +	mutex_unlock(&inode->i_mutex);
> +
> +	if (!dentry->d_inode) {
> +		ino = (unsigned long)-1;
> +		dev = (unsigned)-1;
> +	} else {
> +		dev = dentry->d_inode->i_sb->s_dev;
> +		ino = dentry->d_inode->i_ino;
> +	}

My comments on the ino and dev variables from the other patch apply here.

> +	audit_mark = ERR_PTR(-ENOMEM);
> +	local_pathname = kstrdup(pathname, GFP_KERNEL);
> +	if (!local_pathname)
> +		goto out;

Why not just kstrdup() into audit_mark->path directly?  I don't get the 
fascination with local variables.  Also, why bother with the strdup if the 
audit_mark malloc is going to fail?

> +	audit_mark = kzalloc(sizeof(*audit_mark), GFP_KERNEL);
> +	if (unlikely(!audit_mark)) {
> +		kfree(local_pathname);
> +		audit_mark = ERR_PTR(-ENOMEM);
> +		goto out;
> +	}
> +
> +	fsnotify_init_mark(&audit_mark->mark, audit_fsnotify_free_mark);
> +	audit_mark->mark.mask = AUDIT_FS_EVENTS;
> +	audit_mark->path = local_pathname;
> +	audit_mark->ino = ino;
> +	audit_mark->dev = dev;
> +	audit_mark->rule = krule;
> +
> +	ret = fsnotify_add_mark(&audit_mark->mark, audit_fsnotify_group, inode,
> NULL, true); +	if (ret < 0) {
> +		audit_mark_free(audit_mark);
> +		audit_mark = ERR_PTR(ret);
> +	}
> +out:
> +	dput(dentry);
> +	path_put(&path);
> +	return audit_mark;
> +}

...

> +static void audit_mark_log_rule_change(struct audit_fsnotify_mark
> *audit_mark, char *op)
> +{

That is a lot of letters ... who about audit_mark_log_change()?

> +/* Update mark data in audit rules based on fsnotify events. */
> +static int audit_mark_handle_event(struct fsnotify_group *group,
> +				    struct inode *to_tell,
> +				    struct fsnotify_mark *inode_mark,
> +				    struct fsnotify_mark *vfsmount_mark,
> +				    u32 mask, void *data, int data_type,
> +				    const unsigned char *dname, u32 cookie)
> +{
> +	struct audit_fsnotify_mark *audit_mark;
> +	struct inode *inode = NULL;
> +
> +	audit_mark = container_of(inode_mark, struct audit_fsnotify_mark, mark);
> +
> +	BUG_ON(group != audit_fsnotify_group);

What happens when BUG_ON() is compiled out?  Let's back this up with some 
normal error checking if you think this is a real concern.  If it isn't a real 
concern, why do we have a BUG_ON()?  This doesn't strike me as something that 
is going to be a real problem.

> +	switch (data_type) {
> +	case (FSNOTIFY_EVENT_PATH):
> +		inode = ((struct path *)data)->dentry->d_inode;
> +		break;
> +	case (FSNOTIFY_EVENT_INODE):
> +		inode = (struct inode *)data;
> +		break;
> +	default:
> +		BUG();
> +		return 0;
> +	};

We can do better than BUG() in the default catch-all above.  Maybe a 
prink(KERN_ERR ...)?

> diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
> index 09041b2..bbb39ec 100644
> --- a/kernel/auditfilter.c
> +++ b/kernel/auditfilter.c
> @@ -977,7 +977,7 @@ error:
>  }
> 
>  /* Remove an existing rule from filterlist. */
> -static inline int audit_del_rule(struct audit_entry *entry)
> +int audit_del_rule(struct audit_entry *entry)
>  {
>  	struct audit_entry  *e;
>  	struct audit_tree *tree = entry->rule.tree;
> @@ -985,6 +985,7 @@ static inline int audit_del_rule(struct audit_entry
> *entry) int ret = 0;
>  #ifdef CONFIG_AUDITSYSCALL
>  	int dont_count = 0;
> +	int match = audit_match_signal(entry);
> 
>  	/* If either of these, don't count towards total */
>  	if (entry->rule.listnr == AUDIT_FILTER_USER ||
> @@ -1017,7 +1018,7 @@ static inline int audit_del_rule(struct audit_entry
> *entry) if (!dont_count)
>  		audit_n_rules--;
> 
> -	if (!audit_match_signal(entry))
> +	if (!match)
>  		audit_signals--;
>  #endif
>  	mutex_unlock(&audit_filter_mutex);

Is the bit above worthy of it's own bugfix patch independent of this fsnotify 
implementation, or is it only an issue with this new fsnotify code?

-- 
paul moore
security @ redhat

^ permalink raw reply

* Re: [PATCH V6 2/2] audit: eliminate unnecessary extra layer of watch parent references
From: Richard Guy Briggs @ 2015-07-17  1:45 UTC (permalink / raw)
  To: Paul Moore; +Cc: linux-audit, linux-kernel, sgrubb
In-Reply-To: <1782280.KrZWA343Ju@sifl>

On 15/07/16, Paul Moore wrote:
> On Tuesday, July 14, 2015 11:40:42 AM Richard Guy Briggs wrote:
> > The audit watch parent count was imbalanced, adding an unnecessary layer of
> > watch parent references.  Decrement the additional parent reference when a
> > watch is reused, already having a reference to the parent.
> > 
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > ---
> >  kernel/audit_watch.c |    6 ++----
> >  1 files changed, 2 insertions(+), 4 deletions(-)
> > 
> > diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
> > index f33f54c..8f123d7 100644
> > --- a/kernel/audit_watch.c
> > +++ b/kernel/audit_watch.c
> > @@ -391,11 +391,12 @@ static void audit_add_to_parent(struct audit_krule
> > *krule,
> > 
> >  		audit_get_watch(w);
> >  		krule->watch = watch = w;
> > +
> > +		audit_put_parent(parent);
> >  		break;
> >  	}
> > 
> >  	if (!watch_found) {
> > -		audit_get_parent(parent);
> >  		watch->parent = parent;
> 
> I understand removing the get() here and the put() in audit_add_watch, but I 
> don't understand adding the put() above, can you help me understand?

audit_find_parent() gets a reference to the parent, if the parent is
already known.  This additional parental reference is not needed if the
watch is subsequently found by audit_add_to_parent(), and consumed if
the watch does not already exist, so we need to put the parent if the
watch is found, and do nothing if this new watch is added to the parent.

If the parent wasn't already known, it is created with a refcount of 1
and added to the audit_watch_group, then incremented by one to be
subsequently consumed by the newly created watch in
audit_add_to_parent().

The graph below may help to visualize it.

The rule points to the watch, not to the parent, so the rule's refcount
gets bumped, not the parent's.

> >  		audit_get_watch(watch);
> > @@ -436,9 +437,6 @@ int audit_add_watch(struct audit_krule *krule, struct
> > list_head **list)
> > 
> >  	audit_add_to_parent(krule, parent);
> > 
> > -	/* match get in audit_find_parent or audit_init_parent */
> > -	audit_put_parent(parent);
> > -
> >  	h = audit_hash_ino((u32)watch->ino);
> >  	*list = &audit_inode_hash[h];
> >  error:

	audit_add_watch(entry->rule)
		parent = audit_find_parent()
			fsnotify_find_inode_mark(audit_watch_group)
				fsnotify_find_mark(audit_watch_group)
					fsnotify_get_mark() parent->mark->refcnt ++
		OR parent = audit_init_parent()
			fsnotify_init_mark() parent->mark->refcnt = 1
			fsnotify_add_mark(parent->mark, audit_watch_group)
				fsnotify_add_mark_locked(parent->mark, audit_watch_group)
				|	fsnotify_get_group(audit_watch_group) audit_watch_group->refcnt ++ (mark->group)
				 |	audit_watch_group->num_marks ++ (mark->g_list)
				  |	fsnotify_get_mark(parent->mark) parent->mark->refcnt ++ (i_list/m_list?)
				|	on err, fsnotify_put_group(audit_watch_group) audit_watch_group->refcnt -- test
				 |	on err, audit_watch_group->num_marks --
				  |	on err, destroy_list fsnotify_put_mark(parent->mark) parent->mark->refcnt -- test
						fsnotify_put_group(parent->mark->group) audit_watch_group->refcnt -- test
							fsnotify_final_destroy_group(audit_watch_group) group->ops->free_group_priv(group)
			on err, audit_free_parent(parent)
		on err, return err
		audit_add_to_parent(entry->rule, parent)
			if found, call audit_put_watch(entry->rule->watch) entry->rule->watch->count -- and test?
			if found, call audit_get_watch(parent->watches->watch) parent->watches->watch->count ++
+p			if found, call audit_put_parent(parent) parent->mark->refcnt --
-p			if not found, call audit_get_parent(parent) parent->mark->refcnt ++
-p		audit_put_parent(parent)
			fsnotify_put_mark(parent->mark) parent->mark->refcnt -- test
				fsnotify_put_group(parent->mark->group) audit_watch_group->refcnt -- test
					fsnotify_final_destroy_group(audit_watch_group) group->ops->free_group_priv(group)

> paul moore

- RGB

--
Richard Guy Briggs <rbriggs@redhat.com>
Senior Software Engineer, Kernel Security, AMER ENG Base Operating Systems, Red Hat
Remote, Ottawa, Canada
Voice: +1.647.777.2635, Internal: (81) 32635, Alt: +1.613.693.0684x3545

^ permalink raw reply

* Re: [PATCH V6 1/4] audit: implement audit by executable
From: Paul Moore @ 2015-07-17  1:18 UTC (permalink / raw)
  To: Richard Guy Briggs; +Cc: linux-audit, linux-kernel, Eric Paris, sgrubb, pmoody
In-Reply-To: <ae52b2f53138ae344cb9c0eacfbf3899c2540d13.1436823321.git.rgb@redhat.com>

On Tuesday, July 14, 2015 11:50:23 AM Richard Guy Briggs wrote:
> From: Eric Paris <eparis@redhat.com>
> 
> This patch implements the ability to filter on the executable.  It is
> clearly incomplete!  This patch adds the inode/dev of the executable at
> the moment the rule is loaded.  It does not update if the executable is
> updated/moved/whatever.  That should be added.  But at this moment, this
> patch works.

This needs work.  Either this patch is incomplete as the description says, in 
which case I'm not going to merge it, or the description is out of date and 
needs to be updated.

If later patches in the series fix deficiencies in this patch (I haven't 
gotten past this description yet) then we should consider merging some of the 
patches together so they are more useful.

> RGB: Explicitly declare prototypes as extern.
> RGB: Rename audit_dup_exe() to audit_dupe_exe() consistent with rule, watch,
> lsm_field.
> 
> Based-on-user-interface-by: Richard Guy Briggs <rgb@redhat.com>
> Based-on-idea-by: Peter Moody <pmoody@google.com>

I'm not fully up on the different patch metadata the cool kids are using these 
days, but I think it is okay to simply credit Peter in the patch description 
and omit the two lines above.  Giving credit is important, but these metadata 
tags are a bit silly in my opinion.

> Cc: pmoody@google.com
> Signed-off-by: Eric Paris <eparis@redhat.com>
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>

It has been a while since I've looked at Eric's original patch, but 
considering considering some of the work involved, I think it is reasonable to 
claim this patch as your own and credit Eric in the patch description.
 
> diff --git a/kernel/audit.h b/kernel/audit.h
> index d641f9b..3aca24f 100644
> --- a/kernel/audit.h
> +++ b/kernel/audit.h
> @@ -278,6 +286,30 @@ extern int audit_watch_compare(struct audit_watch
> *watch, unsigned long ino, dev #define audit_watch_path(w) ""
>  #define audit_watch_compare(w, i, d) 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_dupe_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;
> +}
>  #endif /* CONFIG_AUDIT_WATCH */

Not a big fan of the BUG() calls in the stubs above, let's get rid of them.  
Yes, I know some other audit stubs are defined as BUG(), or similar, those 
aren't a good idea either, but they are already there ...
 
> diff --git a/kernel/audit_exe.c b/kernel/audit_exe.c
> new file mode 100644
> index 0000000..d4cc8b5
> --- /dev/null
> +++ b/kernel/audit_exe.c
> @@ -0,0 +1,109 @@
> +/* audit_exe.c -- filtering of audit events
> + *
> + * Copyright 2014-2015 Red Hat, Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License, or
> + * (at your option) any later version.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + */
> +
> +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
> +
> +#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;

You don't need the dev and ino variables here, just move the kmalloc() to just 
after the dentry->d_inode check ... or put it after the sanity checks, 
although you'll have to be careful to free it on error.

> +	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);
> +}

Not your fault, and nothing to change here, but I really hate how audit dups 
strings outside the rule creation functions, but frees the strings in the rule 
free routines; it's almost asking to be misused.

> +char *audit_exe_path(struct audit_exe *exe)
> +{
> +	return exe->pathname;
> +}
> +
> +int audit_dupe_exe(struct audit_krule *new, struct audit_krule *old)
> +{
> +	struct audit_exe *exe;
> +
> +	exe = kmalloc(sizeof(*exe), GFP_KERNEL);
> +	if (!exe)
> +		return -ENOMEM;
> +
> +	exe->pathname = kstrdup(old->exe->pathname, GFP_KERNEL);
> +	if (!exe->pathname) {
> +		kfree(exe);
> +		return -ENOMEM;
> +	}
> +
> +	exe->ino = old->exe->ino;
> +	exe->dev = old->exe->dev;
> +	new->exe = exe;
> +
> +	return 0;
> +}
> +
> +int audit_exe_compare(struct task_struct *tsk, struct audit_exe *exe)
> +{
> +	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;
> +}

I suspect Eric put the above functions in a separate file to ease development 
(no need to work about messy porting as upstream moved on), but I see no 
reason why these functions couldn't be folded into auditfilter.c.

> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index 9fb9d1c..bf745c7 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -48,6 +48,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>
> @@ -71,6 +72,7 @@
>  #include <linux/capability.h>
>  #include <linux/fs_struct.h>
>  #include <linux/compat.h>
> +#include <linux/sched.h>
>  #include <linux/ctype.h>
>  #include <linux/string.h>
>  #include <uapi/linux/limits.h>
> @@ -466,6 +468,20 @@ static int audit_filter_rules(struct task_struct *tsk,
>  				result = audit_comparator(ctx->ppid, f->op, f->val);
>  			}
>  			break;
> +		case AUDIT_EXE:
> +			result = audit_exe_compare(tsk, rule->exe);
> +			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_exe_compare(ptsk, rule->exe)) {
> +					++result;
> +					break;
> +				}
> +			}
> +		}
> +			break;

I don't completely understand the point of AUDIT_EXE_CHILDREN filter, what 
problem are we trying to solve?  It checks to see if there is an executable 
match starting with the current process and walking up the process' parents in 
the current pid namespace?

Help me understand what this accomplishes, I'm a little tried right now and I 
just don't get it.

-- 
paul moore
security @ redhat

^ permalink raw reply

* Re: [PATCH V6 1/2] audit: eliminate unnecessary extra layer of watch references
From: Richard Guy Briggs @ 2015-07-17  0:32 UTC (permalink / raw)
  To: Paul Moore; +Cc: linux-audit, linux-kernel, sgrubb
In-Reply-To: <2780197.VSVkCiSN5s@sifl>

On 15/07/16, Paul Moore wrote:
> On Tuesday, July 14, 2015 11:40:41 AM Richard Guy Briggs wrote:
> > The audit watch count was imbalanced, adding an unnecessary layer of watch
> > references.  Only add the second reference when it is added to a parent.
> > 
> > Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> > ---
> >  kernel/audit_watch.c |    5 ++---
> >  kernel/auditfilter.c |    9 ---------
> >  2 files changed, 2 insertions(+), 12 deletions(-)
> 
> Nice catch, we never needed that extra refcnt bump in audit_to_watch().  One 
> minor comment below...
> 
> > diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
> > index 72e1660..74cc077 100644
> > --- a/kernel/auditfilter.c
> > +++ b/kernel/auditfilter.c
> > @@ -549,8 +549,6 @@ exit_nofree:
> >  	return entry;
> > 
> >  exit_free:
> > -	if (entry->rule.watch)
> > -		audit_put_watch(entry->rule.watch); /* matches initial get */
> >  	if (entry->rule.tree)
> >  		audit_put_tree(entry->rule.tree); /* that's the temporary one */
> >  	audit_free_rule(entry);
> > @@ -933,11 +931,7 @@ static inline int audit_add_rule(struct audit_entry
> > *entry) #endif
> >  	mutex_unlock(&audit_filter_mutex);
> > 
> > - 	return 0;
> > -
> >  error:
> > -	if (watch)
> > -		audit_put_watch(watch); /* tmp watch, matches initial get */
> >  	return err;
> >  }
> 
> Since the error label is now just a "return err;", how about removing the 
> label entirely and replacing the gotos with returns?

Yup, sounds reasonable.

> paul moore

- RGB

--
Richard Guy Briggs <rbriggs@redhat.com>
Senior Software Engineer, Kernel Security, AMER ENG Base Operating Systems, Red Hat
Remote, Ottawa, Canada
Voice: +1.647.777.2635, Internal: (81) 32635, Alt: +1.613.693.0684x3545

^ permalink raw reply

* audit 2.4.3 released
From: Steve Grubb @ 2015-07-16 23:14 UTC (permalink / raw)
  To: linux-audit

Hello,

I've just released a new version of the audit daemon. It can be downloaded 
from http://people.redhat.com/sgrubb/audit. It will also be in rawhide
soon. The ChangeLog is:

- Add python3 support for libaudit
- Cleanup automake warnings
- Add AuParser_search_add_timestamp_item_ex to python bindings
- Add AuParser_get_type_name to python bindings
- Correct processing of obj_gid in auditctl (Aleksander Zdyb)
- Make plugin config file parsing more robust for long lines (#1235457)
- Make auditctl status print lost field as unsigned number
- Add interpretation mode for auditctl -s
- Add python3 support to auparse library
- Make --enable-zos-remote a build time configuration option (Clayton Shotwell)
- Updates for cross compiling (Clayton Shotwell)
- Add MAC_CHECK audit event type
- Add libauparse pkgconfig file (Aleksander Zdyb)

The main focus of this release is in adding Python3 support. There were also 
various bug fixes and improvements for cross compile support.

Note to Package Maintainers
-------------------------------------
To add python 3 support, you will need to add --with-python3=yes to the 
./configure line. This is independent of python2 support so that one day 
python2 can be retired is so desired.

One other change to be aware of is that zos plugin support is dropped by 
default. This means that to keep the same zos binary in the distribution, you 
will need to add --enable-zos-remote to the configure line.

There is also a new auparse.pc file that you may want to package up in the 
devel package.

Please let me know if you run across any problems with this release.

-Steve

^ permalink raw reply

* Re: [PATCH] Enable cross compiling
From: Steve Grubb @ 2015-07-16 21:03 UTC (permalink / raw)
  To: linux-audit
In-Reply-To: <1437078716-15626-1-git-send-email-clayton.shotwell@rockwellcollins.com>

On Thursday, July 16, 2015 03:31:56 PM Clayton Shotwell wrote:
> This is revision 2 of this patch and is a complete rework of the
> original patch. I have tested that it builds on an x86_64 ubuntu
> platform and tested it running on an ARM cross compile platform.

Thanks! Applied. Starting release for audit-2.4.3.

-Steve

^ permalink raw reply

* Re: [PATCH V6 2/2] audit: eliminate unnecessary extra layer of watch parent references
From: Paul Moore @ 2015-07-16 20:32 UTC (permalink / raw)
  To: Richard Guy Briggs; +Cc: linux-audit, linux-kernel, sgrubb
In-Reply-To: <606b8964c3147668af4d6b1a2d770ccf694d26f9.1435723005.git.rgb@redhat.com>

On Tuesday, July 14, 2015 11:40:42 AM Richard Guy Briggs wrote:
> The audit watch parent count was imbalanced, adding an unnecessary layer of
> watch parent references.  Decrement the additional parent reference when a
> watch is reused, already having a reference to the parent.
> 
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> ---
>  kernel/audit_watch.c |    6 ++----
>  1 files changed, 2 insertions(+), 4 deletions(-)
> 
> diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
> index f33f54c..8f123d7 100644
> --- a/kernel/audit_watch.c
> +++ b/kernel/audit_watch.c
> @@ -391,11 +391,12 @@ static void audit_add_to_parent(struct audit_krule
> *krule,
> 
>  		audit_get_watch(w);
>  		krule->watch = watch = w;
> +
> +		audit_put_parent(parent);
>  		break;
>  	}
> 
>  	if (!watch_found) {
> -		audit_get_parent(parent);
>  		watch->parent = parent;

I understand removing the get() here and the put() in audit_add_watch, but I 
don't understand adding the put() above, can you help me understand?

>  		audit_get_watch(watch);
> @@ -436,9 +437,6 @@ int audit_add_watch(struct audit_krule *krule, struct
> list_head **list)
> 
>  	audit_add_to_parent(krule, parent);
> 
> -	/* match get in audit_find_parent or audit_init_parent */
> -	audit_put_parent(parent);
> -
>  	h = audit_hash_ino((u32)watch->ino);
>  	*list = &audit_inode_hash[h];
>  error:

-- 
paul moore
security @ redhat

^ permalink raw reply

* [PATCH] Enable cross compiling
From: Clayton Shotwell @ 2015-07-16 20:31 UTC (permalink / raw)
  To: linux-audit

During the audit build, several lookup tables are generated as header
files that are then linked in with the executables. This process is done
by a C application that needs to be able to be run on the host. The
current Makfile structure tries to build these executables for the
target instead of the host where they cannot be executed. This patch
reworks the Makefile structure to build for the correct platform.

This is revision 2 of this patch and is a complete rework of the
original patch. I have tested that it builds on an x86_64 ubuntu
platform and tested it running on an ARM cross compile platform.

The ax_prog_cc_for_build.m4 file was obtained from GNU at the link
below.
http://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html

Signed-off-by: Clayton Shotwell <clayton.shotwell@rockwellcollins.com>
---
 auparse/Makefile.am        | 185 ++++++++++++++++++++++++++++++++++++---------
 configure.ac               |   1 +
 lib/Makefile.am            |  85 ++++++++++++++++-----
 m4/ax_prog_cc_for_build.m4 | 125 ++++++++++++++++++++++++++++++
 4 files changed, 342 insertions(+), 54 deletions(-)
 create mode 100644 m4/ax_prog_cc_for_build.m4

diff --git a/auparse/Makefile.am b/auparse/Makefile.am
index 89b2d21..f9709de 100644
--- a/auparse/Makefile.am
+++ b/auparse/Makefile.am
@@ -74,191 +74,302 @@ noinst_PROGRAMS = gen_accesstabs_h gen_captabs_h gen_clock_h \
 	gen_umounttabs_h
 
 gen_accesstabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h accesstab.h
-gen_accesstabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="accesstab.h"'
+gen_accesstabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="accesstab.h"'
+$(gen_accesstabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_accesstabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_accesstabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 accesstabs.h: gen_accesstabs_h Makefile
 	./gen_accesstabs_h --i2s-transtab access > $@
 
 gen_captabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h captab.h
-gen_captabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="captab.h"'
+gen_captabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="captab.h"'
+$(gen_captabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_captabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_captabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 captabs.h: gen_captabs_h Makefile
 	./gen_captabs_h --i2s cap > $@
 
 gen_clock_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h clocktab.h
-gen_clock_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="clocktab.h"'
+gen_clock_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="clocktab.h"'
+$(gen_clock_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_clock_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_clock_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 clocktabs.h: gen_clock_h Makefile
 	./gen_clock_h --i2s clock > $@
 
 gen_clone_flagtabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h \
 	clone-flagtab.h
-gen_clone_flagtabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="clone-flagtab.h"'
+gen_clone_flagtabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="clone-flagtab.h"'
+$(gen_clone_flagtabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_clone_flagtabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_clone-flagtabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 clone-flagtabs.h: gen_clone-flagtabs_h Makefile
 	./gen_clone-flagtabs_h --i2s-transtab clone_flag > $@
 
 gen_epoll_ctls_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h epoll_ctl.h
-gen_epoll_ctls_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="epoll_ctl.h"'
+gen_epoll_ctls_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="epoll_ctl.h"'
+$(gen_epoll_ctls_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_epoll_ctls_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_epoll_ctls_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 epoll_ctls.h: gen_epoll_ctls_h Makefile
 	./gen_epoll_ctls_h --i2s epoll_ctl > $@
 
 gen_famtabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h famtab.h
-gen_famtabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="famtab.h"'
+gen_famtabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="famtab.h"'
+$(gen_famtabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_famtabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_famtabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 famtabs.h: gen_famtabs_h Makefile
 	./gen_famtabs_h --i2s fam > $@
 
 gen_flagtabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h flagtab.h
 # ../auparse/ is used to avoid using ../lib/flagtab.h
-gen_flagtabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="../auparse/flagtab.h"'
+gen_flagtabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="../auparse/flagtab.h"'
+$(gen_flagtabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_flagtabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_flagtabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 flagtabs.h: gen_flagtabs_h Makefile
 	./gen_flagtabs_h --i2s-transtab flag > $@
 
 gen_fcntl_cmdtabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h \
 	fcntl-cmdtab.h
-gen_fcntl_cmdtabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="fcntl-cmdtab.h"'
+gen_fcntl_cmdtabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="fcntl-cmdtab.h"'
+$(gen_fcntl_cmdtabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_fcntl_cmdtabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_fcntl-cmdtabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 fcntl-cmdtabs.h: gen_fcntl-cmdtabs_h Makefile
 	./gen_fcntl-cmdtabs_h --i2s fcntl > $@
 
 gen_icmptypetabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h icmptypetab.h
-gen_icmptypetabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="icmptypetab.h"'
+gen_icmptypetabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="icmptypetab.h"'
+$(gen_icmptypetabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_icmptypetabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_icmptypetabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 icmptypetabs.h: gen_icmptypetabs_h Makefile
 	./gen_icmptypetabs_h --i2s icmptype > $@
 
 gen_ioctlreqtabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h ioctlreqtab.h
-gen_ioctlreqtabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="ioctlreqtab.h"'
+gen_ioctlreqtabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="ioctlreqtab.h"'
+$(gen_ioctlreqtabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_ioctlreqtabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_ioctlreqtabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 ioctlreqtabs.h: gen_ioctlreqtabs_h Makefile
 	./gen_ioctlreqtabs_h --i2s ioctlreq > $@
 
 gen_ipctabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h ipctab.h
-gen_ipctabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="ipctab.h"'
+gen_ipctabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="ipctab.h"'
+$(gen_ipctabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_ipctabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_ipctabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 ipctabs.h: gen_ipctabs_h Makefile
 	./gen_ipctabs_h --i2s ipc > $@
 
 gen_ipccmdtabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h ipccmdtab.h
-gen_ipccmdtabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="ipccmdtab.h"'
+gen_ipccmdtabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="ipccmdtab.h"'
+$(gen_ipccmdtabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_ipccmdtabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_ipccmdtabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 ipccmdtabs.h: gen_ipccmdtabs_h Makefile
 	./gen_ipccmdtabs_h --i2s-transtab ipccmd > $@
 
 gen_ipoptnametabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h ipoptnametab.h
-gen_ipoptnametabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="ipoptnametab.h"'
+gen_ipoptnametabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="ipoptnametab.h"'
+$(gen_ipoptnametabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_ipoptnametabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_ipoptnametabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 ipoptnametabs.h: gen_ipoptnametabs_h Makefile
 	./gen_ipoptnametabs_h --i2s ipoptname > $@
 
 gen_ip6optnametabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h ip6optnametab.h
-gen_ip6optnametabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="ip6optnametab.h"'
+gen_ip6optnametabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="ip6optnametab.h"'
+$(gen_ip6optnametabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_ip6optnametabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_ip6optnametabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 ip6optnametabs.h: gen_ip6optnametabs_h Makefile
 	./gen_ip6optnametabs_h --i2s ip6optname > $@
 
 gen_mmaptabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h mmaptab.h
-gen_mmaptabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="mmaptab.h"'
+gen_mmaptabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="mmaptab.h"'
+$(gen_mmaptabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_mmaptabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_mmaptabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 mmaptabs.h: gen_mmaptabs_h Makefile
 	./gen_mmaptabs_h --i2s-transtab mmap > $@
 
 gen_mounttabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h mounttab.h
-gen_mounttabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="mounttab.h"'
+gen_mounttabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="mounttab.h"'
+$(gen_mounttabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_mounttabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_mounttabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 mounttabs.h: gen_mounttabs_h Makefile
 	./gen_mounttabs_h --i2s-transtab mount > $@
 
 gen_nfprototabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h nfprototab.h
-gen_nfprototabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="nfprototab.h"'
+gen_nfprototabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="nfprototab.h"'
+$(gen_nfprototabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_nfprototabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_nfprototabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 nfprototabs.h: gen_nfprototabs_h Makefile
 	./gen_nfprototabs_h --i2s nfproto > $@
 
 gen_open_flagtabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h \
 	open-flagtab.h
-gen_open_flagtabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="open-flagtab.h"'
+gen_open_flagtabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="open-flagtab.h"'
+$(gen_open_flagtabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_open_flagtabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_open-flagtabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 open-flagtabs.h: gen_open-flagtabs_h Makefile
 	./gen_open-flagtabs_h --i2s-transtab open_flag > $@
 
 gen_persontabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h persontab.h
-gen_persontabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="persontab.h"'
+gen_persontabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="persontab.h"'
+$(gen_persontabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_persontabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_persontabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 persontabs.h: gen_persontabs_h Makefile
 	./gen_persontabs_h --i2s person > $@
 
 gen_ptracetabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h ptracetab.h
-gen_ptracetabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="ptracetab.h"'
+gen_ptracetabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="ptracetab.h"'
+$(gen_ptracetabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_ptracetabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_ptracetabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 ptracetabs.h: gen_ptracetabs_h Makefile
 	./gen_ptracetabs_h --i2s ptrace > $@
 
 gen_prctl_opttabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h prctl-opt-tab.h
-gen_prctl_opttabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="prctl-opt-tab.h"'
+gen_prctl_opttabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="prctl-opt-tab.h"'
+$(gen_prctl_opttabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_prctl_opttabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_prctl_opttabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 prctl_opttabs.h: gen_prctl_opttabs_h Makefile
 	./gen_prctl_opttabs_h --i2s prctl_opt > $@
 
 gen_pktoptnametabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h pktoptnametab.h
-gen_pktoptnametabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="pktoptnametab.h"'
+gen_pktoptnametabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="pktoptnametab.h"'
+$(gen_pktoptnametabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_pktoptnametabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_pktoptnametabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 pktoptnametabs.h: gen_pktoptnametabs_h Makefile
 	./gen_pktoptnametabs_h --i2s pktoptname > $@
 
 gen_prottabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h prottab.h
-gen_prottabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="prottab.h"'
+gen_prottabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="prottab.h"'
+$(gen_prottabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_prottabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_prottabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 prottabs.h: gen_prottabs_h Makefile
 	./gen_prottabs_h --i2s-transtab prot > $@
 
 gen_recvtabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h recvtab.h
-gen_recvtabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="recvtab.h"'
+gen_recvtabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="recvtab.h"'
+$(gen_recvtabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_recvtabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_recvtabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 recvtabs.h: gen_recvtabs_h Makefile
 	./gen_recvtabs_h --i2s-transtab recv > $@
 
 gen_rlimit_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h rlimittab.h
-gen_rlimit_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="rlimittab.h"'
+gen_rlimit_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="rlimittab.h"'
+$(gen_rlimit_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_rlimit_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_rlimit_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 rlimittabs.h: gen_rlimit_h Makefile
 	./gen_rlimit_h --i2s rlimit > $@
 
 gen_schedtabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h schedtab.h
-gen_schedtabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="schedtab.h"'
+gen_schedtabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="schedtab.h"'
+$(gen_schedtabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_schedtabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_schedtabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 schedtabs.h: gen_schedtabs_h Makefile
 	./gen_schedtabs_h --i2s sched > $@
 
 gen_seccomptabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h seccomptab.h
-gen_seccomptabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="seccomptab.h"'
+gen_seccomptabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="seccomptab.h"'
+$(gen_seccomptabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_seccomptabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_seccomptabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 seccomptabs.h: gen_seccomptabs_h Makefile
 	./gen_seccomptabs_h --i2s seccomp > $@
 
 gen_seektabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h seektab.h
-gen_seektabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="seektab.h"'
+gen_seektabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="seektab.h"'
+$(gen_seektabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_seektabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_seektabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 seektabs.h: gen_seektabs_h Makefile
 	./gen_seektabs_h --i2s seek > $@
 
 gen_shm_modetabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h shm_modetab.h
-gen_shm_modetabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="shm_modetab.h"'
+gen_shm_modetabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="shm_modetab.h"'
+$(gen_shm_modetabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_shm_modetabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_shm_modetabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 shm_modetabs.h: gen_shm_modetabs_h Makefile
 	./gen_shm_modetabs_h --i2s-transtab shm_mode > $@
 
 gen_signals_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h signaltab.h
-gen_signals_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="signaltab.h"'
+gen_signals_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="signaltab.h"'
+$(gen_signals_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_signals_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_signals_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 signaltabs.h: gen_signals_h Makefile
 	./gen_signals_h --i2s signal > $@
 
 gen_sockleveltabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h sockleveltab.h
-gen_sockleveltabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="sockleveltab.h"'
+gen_sockleveltabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="sockleveltab.h"'
+$(gen_sockleveltabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_sockleveltabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_sockleveltabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 sockleveltabs.h: gen_sockleveltabs_h Makefile
 	./gen_sockleveltabs_h --i2s socklevel > $@
 
 gen_sockoptnametabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h sockoptnametab.h
-gen_sockoptnametabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="sockoptnametab.h"'
+gen_sockoptnametabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="sockoptnametab.h"'
+$(gen_sockoptnametabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_sockoptnametabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_sockoptnametabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 sockoptnametabs.h: gen_sockoptnametabs_h Makefile
 	./gen_sockoptnametabs_h --i2s sockoptname > $@
 
 gen_socktabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h socktab.h
-gen_socktabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="socktab.h"'
+gen_socktabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="socktab.h"'
+$(gen_socktabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_socktabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_socktabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 socktabs.h: gen_socktabs_h Makefile
 	./gen_socktabs_h --i2s sock > $@
 
 gen_socktypetabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h socktypetab.h
-gen_socktypetabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="socktypetab.h"'
+gen_socktypetabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="socktypetab.h"'
+$(gen_socktypetabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_socktypetabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_socktypetabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 socktypetabs.h: gen_socktypetabs_h Makefile
 	./gen_socktypetabs_h --i2s sock_type > $@
 
 gen_tcpoptnametabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h tcpoptnametab.h
-gen_tcpoptnametabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="tcpoptnametab.h"'
+gen_tcpoptnametabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="tcpoptnametab.h"'
+$(gen_tcpoptnametabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_tcpoptnametabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_tcpoptnametabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 tcpoptnametabs.h: gen_tcpoptnametabs_h Makefile
 	./gen_tcpoptnametabs_h --i2s tcpoptname > $@
 
 gen_typetabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h typetab.h
-gen_typetabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="typetab.h"'
+gen_typetabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="typetab.h"'
+$(gen_typetabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_typetabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_typetabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 typetabs.h: gen_typetabs_h Makefile
 	./gen_typetabs_h --s2i type > $@
 
 gen_umounttabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h umounttab.h
-gen_umounttabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="umounttab.h"'
+gen_umounttabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="umounttab.h"'
+$(gen_umounttabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_umounttabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_umounttabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 umounttabs.h: gen_umounttabs_h Makefile
 	./gen_umounttabs_h --i2s-transtab umount > $@
 
diff --git a/configure.ac b/configure.ac
index ad9084b..f29fa41 100644
--- a/configure.ac
+++ b/configure.ac
@@ -51,6 +51,7 @@ echo Checking for programs
 AC_PROG_CC
 AC_PROG_INSTALL
 AC_PROG_AWK
+AX_PROG_CC_FOR_BUILD
 
 echo .
 echo Checking for header files
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 3560a88..97825bb 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -70,94 +70,145 @@ if USE_AARCH64
 noinst_PROGRAMS += gen_aarch64_tables_h
 endif
 gen_actiontabs_h_SOURCES = gen_tables.c gen_tables.h actiontab.h
-gen_actiontabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="actiontab.h"'
+gen_actiontabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="actiontab.h"'
+$(gen_actiontabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_actiontabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_actiontabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 actiontabs.h: gen_actiontabs_h Makefile
 	./gen_actiontabs_h --lowercase --i2s --s2i action > $@
 
 if USE_ALPHA
 gen_alpha_tables_h_SOURCES = gen_tables.c gen_tables.h alpha_table.h
-gen_alpha_tables_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="alpha_table.h"'
+gen_alpha_tables_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="alpha_table.h"'
+$(gen_alpha_tables_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_alpha_tables_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_alpha_tables_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 alpha_tables.h: gen_alpha_tables_h Makefile
 	./gen_alpha_tables_h --lowercase --i2s --s2i alpha_syscall > $@
 endif
 
 if USE_ARM
 gen_arm_tables_h_SOURCES = gen_tables.c gen_tables.h arm_table.h
-gen_arm_tables_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="arm_table.h"'
+gen_arm_tables_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="arm_table.h"'
+$(gen_arm_tables_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_arm_tables_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_arm_tables_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 arm_tables.h: gen_arm_tables_h Makefile
 	./gen_arm_tables_h --lowercase --i2s --s2i arm_syscall > $@
 endif
 
 if USE_AARCH64
 gen_aarch64_tables_h_SOURCES = gen_tables.c gen_tables.h aarch64_table.h
-gen_aarch64_tables_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="aarch64_table.h"'
+gen_aarch64_tables_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="aarch64_table.h"'
+$(gen_aarch64_tables_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_aarch64_tables_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_aarch64_tables_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 aarch64_tables.h: gen_aarch64_tables_h Makefile
 	./gen_aarch64_tables_h --lowercase --i2s --s2i aarch64_syscall > $@
 endif
 
 gen_errtabs_h_SOURCES = gen_tables.c gen_tables.h errtab.h
-gen_errtabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="errtab.h"'
+gen_errtabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="errtab.h"'
+$(gen_errtabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_errtabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_errtabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 errtabs.h: gen_errtabs_h Makefile
 	./gen_errtabs_h --duplicate-ints --uppercase --i2s --s2i err > $@
 
 gen_fieldtabs_h_SOURCES = gen_tables.c gen_tables.h fieldtab.h
-gen_fieldtabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="fieldtab.h"'
+gen_fieldtabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="fieldtab.h"'
+$(gen_fieldtabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_fieldtabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_fieldtabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 fieldtabs.h: gen_fieldtabs_h Makefile
 	./gen_fieldtabs_h --duplicate-ints --lowercase --i2s --s2i field > $@
 
 gen_flagtabs_h_SOURCES = gen_tables.c gen_tables.h flagtab.h
-gen_flagtabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="flagtab.h"'
+gen_flagtabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="flagtab.h"'
+$(gen_flagtabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_flagtabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_flagtabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 flagtabs.h: gen_flagtabs_h Makefile
 	./gen_flagtabs_h --lowercase --i2s --s2i flag > $@
 
 gen_ftypetabs_h_SOURCES = gen_tables.c gen_tables.h ftypetab.h
-gen_ftypetabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="ftypetab.h"'
+gen_ftypetabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="ftypetab.h"'
+$(gen_ftypetabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_ftypetabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_ftypetabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 ftypetabs.h: gen_ftypetabs_h Makefile
 	./gen_ftypetabs_h --lowercase --i2s --s2i ftype > $@
 
 gen_i386_tables_h_SOURCES = gen_tables.c gen_tables.h i386_table.h
-gen_i386_tables_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="i386_table.h"'
+gen_i386_tables_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="i386_table.h"'
+$(gen_i386_tables_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_i386_tables_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_i386_tables_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 i386_tables.h: gen_i386_tables_h Makefile
 	./gen_i386_tables_h --duplicate-ints --lowercase --i2s --s2i \
 		i386_syscall > $@
 
 gen_ia64_tables_h_SOURCES = gen_tables.c gen_tables.h ia64_table.h
-gen_ia64_tables_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="ia64_table.h"'
+gen_ia64_tables_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="ia64_table.h"'
+$(gen_ia64_tables_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_ia64_tables_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_ia64_tables_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 ia64_tables.h: gen_ia64_tables_h Makefile
 	./gen_ia64_tables_h --lowercase --i2s --s2i ia64_syscall > $@
 
 gen_machinetabs_h_SOURCES = gen_tables.c gen_tables.h machinetab.h
-gen_machinetabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="machinetab.h"'
+gen_machinetabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="machinetab.h"'
+$(gen_machinetabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_machinetabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_machinetabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 machinetabs.h: gen_machinetabs_h Makefile
 	./gen_machinetabs_h --duplicate-ints --lowercase --i2s --s2i machine \
 		> $@
 
 gen_msg_typetabs_h_SOURCES = gen_tables.c gen_tables.h msg_typetab.h
-gen_msg_typetabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="msg_typetab.h"'
+gen_msg_typetabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="msg_typetab.h"'
+$(gen_msg_typetabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_msg_typetabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_msg_typetabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 msg_typetabs.h: gen_msg_typetabs_h Makefile
 	./gen_msg_typetabs_h --uppercase --i2s --s2i msg_type > $@
 
 gen_optabs_h_SOURCES = gen_tables.c gen_tables.h optab.h
-gen_optabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="optab.h"'
+gen_optabs_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="optab.h"'
+$(gen_optabs_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_optabs_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_optabs_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 optabs.h: gen_optabs_h Makefile
 	./gen_optabs_h --i2s op > $@
 
 gen_ppc_tables_h_SOURCES = gen_tables.c gen_tables.h ppc_table.h
-gen_ppc_tables_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="ppc_table.h"'
+gen_ppc_tables_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="ppc_table.h"'
+$(gen_ppc_tables_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_ppc_tables_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_ppc_tables_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 ppc_tables.h: gen_ppc_tables_h Makefile
 	./gen_ppc_tables_h --lowercase --i2s --s2i ppc_syscall > $@
 
 gen_s390_tables_h_SOURCES = gen_tables.c gen_tables.h s390_table.h
-gen_s390_tables_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="s390_table.h"'
+gen_s390_tables_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="s390_table.h"'
+$(gen_s390_tables_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_s390_tables_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_s390_tables_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 s390_tables.h: gen_s390_tables_h Makefile
 	./gen_s390_tables_h --lowercase --i2s --s2i s390_syscall > $@
 
 gen_s390x_tables_h_SOURCES = gen_tables.c gen_tables.h s390x_table.h
-gen_s390x_tables_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="s390x_table.h"'
+gen_s390x_tables_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="s390x_table.h"'
+$(gen_s390x_tables_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_s390x_tables_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_s390x_tables_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 s390x_tables.h: gen_s390x_tables_h Makefile
 	./gen_s390x_tables_h --lowercase --i2s --s2i s390x_syscall > $@
 
 gen_x86_64_tables_h_SOURCES = gen_tables.c gen_tables.h x86_64_table.h
-gen_x86_64_tables_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="x86_64_table.h"'
+gen_x86_64_tables_h_CFLAGS = $(CFLAGS_FOR_BUILD) '-DTABLE_H="x86_64_table.h"'
+$(gen_x86_64_tables_h_OBJECTS): CC=$(CC_FOR_BUILD)
+$(gen_x86_64_tables_h_OBJECTS): CPPFLAGS=$(CPPFLAGS_FOR_BUILD)
+gen_x86_64_tables_h$(BUILD_EXEEXT): CC=$(CC_FOR_BUILD)
 x86_64_tables.h: gen_x86_64_tables_h Makefile
 	./gen_x86_64_tables_h --lowercase --i2s --s2i x86_64_syscall > $@
diff --git a/m4/ax_prog_cc_for_build.m4 b/m4/ax_prog_cc_for_build.m4
new file mode 100644
index 0000000..77fd346
--- /dev/null
+++ b/m4/ax_prog_cc_for_build.m4
@@ -0,0 +1,125 @@
+# ===========================================================================
+#   http://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html
+# ===========================================================================
+#
+# SYNOPSIS
+#
+#   AX_PROG_CC_FOR_BUILD
+#
+# DESCRIPTION
+#
+#   This macro searches for a C compiler that generates native executables,
+#   that is a C compiler that surely is not a cross-compiler. This can be
+#   useful if you have to generate source code at compile-time like for
+#   example GCC does.
+#
+#   The macro sets the CC_FOR_BUILD and CPP_FOR_BUILD macros to anything
+#   needed to compile or link (CC_FOR_BUILD) and preprocess (CPP_FOR_BUILD).
+#   The value of these variables can be overridden by the user by specifying
+#   a compiler with an environment variable (like you do for standard CC).
+#
+#   It also sets BUILD_EXEEXT and BUILD_OBJEXT to the executable and object
+#   file extensions for the build platform, and GCC_FOR_BUILD to `yes' if
+#   the compiler we found is GCC. All these variables but GCC_FOR_BUILD are
+#   substituted in the Makefile.
+#
+# LICENSE
+#
+#   Copyright (c) 2008 Paolo Bonzini <bonzini@gnu.org>
+#
+#   Copying and distribution of this file, with or without modification, are
+#   permitted in any medium without royalty provided the copyright notice
+#   and this notice are preserved. This file is offered as-is, without any
+#   warranty.
+
+#serial 8
+
+AU_ALIAS([AC_PROG_CC_FOR_BUILD], [AX_PROG_CC_FOR_BUILD])
+AC_DEFUN([AX_PROG_CC_FOR_BUILD], [dnl
+AC_REQUIRE([AC_PROG_CC])dnl
+AC_REQUIRE([AC_PROG_CPP])dnl
+AC_REQUIRE([AC_EXEEXT])dnl
+AC_REQUIRE([AC_CANONICAL_HOST])dnl
+
+dnl Use the standard macros, but make them use other variable names
+dnl
+pushdef([ac_cv_prog_CPP], ac_cv_build_prog_CPP)dnl
+pushdef([ac_cv_prog_gcc], ac_cv_build_prog_gcc)dnl
+pushdef([ac_cv_prog_cc_works], ac_cv_build_prog_cc_works)dnl
+pushdef([ac_cv_prog_cc_cross], ac_cv_build_prog_cc_cross)dnl
+pushdef([ac_cv_prog_cc_g], ac_cv_build_prog_cc_g)dnl
+pushdef([ac_cv_exeext], ac_cv_build_exeext)dnl
+pushdef([ac_cv_objext], ac_cv_build_objext)dnl
+pushdef([ac_exeext], ac_build_exeext)dnl
+pushdef([ac_objext], ac_build_objext)dnl
+pushdef([CC], CC_FOR_BUILD)dnl
+pushdef([CPP], CPP_FOR_BUILD)dnl
+pushdef([CFLAGS], CFLAGS_FOR_BUILD)dnl
+pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl
+pushdef([LDFLAGS], LDFLAGS_FOR_BUILD)dnl
+pushdef([host], build)dnl
+pushdef([host_alias], build_alias)dnl
+pushdef([host_cpu], build_cpu)dnl
+pushdef([host_vendor], build_vendor)dnl
+pushdef([host_os], build_os)dnl
+pushdef([ac_cv_host], ac_cv_build)dnl
+pushdef([ac_cv_host_alias], ac_cv_build_alias)dnl
+pushdef([ac_cv_host_cpu], ac_cv_build_cpu)dnl
+pushdef([ac_cv_host_vendor], ac_cv_build_vendor)dnl
+pushdef([ac_cv_host_os], ac_cv_build_os)dnl
+pushdef([ac_cpp], ac_build_cpp)dnl
+pushdef([ac_compile], ac_build_compile)dnl
+pushdef([ac_link], ac_build_link)dnl
+
+save_cross_compiling=$cross_compiling
+save_ac_tool_prefix=$ac_tool_prefix
+cross_compiling=no
+ac_tool_prefix=
+
+AC_PROG_CC
+AC_PROG_CPP
+AC_EXEEXT
+
+ac_tool_prefix=$save_ac_tool_prefix
+cross_compiling=$save_cross_compiling
+
+dnl Restore the old definitions
+dnl
+popdef([ac_link])dnl
+popdef([ac_compile])dnl
+popdef([ac_cpp])dnl
+popdef([ac_cv_host_os])dnl
+popdef([ac_cv_host_vendor])dnl
+popdef([ac_cv_host_cpu])dnl
+popdef([ac_cv_host_alias])dnl
+popdef([ac_cv_host])dnl
+popdef([host_os])dnl
+popdef([host_vendor])dnl
+popdef([host_cpu])dnl
+popdef([host_alias])dnl
+popdef([host])dnl
+popdef([LDFLAGS])dnl
+popdef([CPPFLAGS])dnl
+popdef([CFLAGS])dnl
+popdef([CPP])dnl
+popdef([CC])dnl
+popdef([ac_objext])dnl
+popdef([ac_exeext])dnl
+popdef([ac_cv_objext])dnl
+popdef([ac_cv_exeext])dnl
+popdef([ac_cv_prog_cc_g])dnl
+popdef([ac_cv_prog_cc_cross])dnl
+popdef([ac_cv_prog_cc_works])dnl
+popdef([ac_cv_prog_gcc])dnl
+popdef([ac_cv_prog_CPP])dnl
+
+dnl Finally, set Makefile variables
+dnl
+BUILD_EXEEXT=$ac_build_exeext
+BUILD_OBJEXT=$ac_build_objext
+AC_SUBST(BUILD_EXEEXT)dnl
+AC_SUBST(BUILD_OBJEXT)dnl
+AC_SUBST([CFLAGS_FOR_BUILD])dnl
+AC_SUBST([CPPFLAGS_FOR_BUILD])dnl
+AC_SUBST([LDFLAGS_FOR_BUILD])dnl
+])
-- 
1.9.1

^ permalink raw reply related

* Re: [PATCH V6 1/2] audit: eliminate unnecessary extra layer of watch references
From: Paul Moore @ 2015-07-16 20:13 UTC (permalink / raw)
  To: Richard Guy Briggs; +Cc: linux-audit, linux-kernel, sgrubb
In-Reply-To: <83de0ec5dd6ba510a66bd4a3aa2988b7617cd621.1435723005.git.rgb@redhat.com>

On Tuesday, July 14, 2015 11:40:41 AM Richard Guy Briggs wrote:
> The audit watch count was imbalanced, adding an unnecessary layer of watch
> references.  Only add the second reference when it is added to a parent.
> 
> Signed-off-by: Richard Guy Briggs <rgb@redhat.com>
> ---
>  kernel/audit_watch.c |    5 ++---
>  kernel/auditfilter.c |    9 ---------
>  2 files changed, 2 insertions(+), 12 deletions(-)

Nice catch, we never needed that extra refcnt bump in audit_to_watch().  One 
minor comment below...

> diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
> index 72e1660..74cc077 100644
> --- a/kernel/auditfilter.c
> +++ b/kernel/auditfilter.c
> @@ -549,8 +549,6 @@ exit_nofree:
>  	return entry;
> 
>  exit_free:
> -	if (entry->rule.watch)
> -		audit_put_watch(entry->rule.watch); /* matches initial get */
>  	if (entry->rule.tree)
>  		audit_put_tree(entry->rule.tree); /* that's the temporary one */
>  	audit_free_rule(entry);
> @@ -933,11 +931,7 @@ static inline int audit_add_rule(struct audit_entry
> *entry) #endif
>  	mutex_unlock(&audit_filter_mutex);
> 
> - 	return 0;
> -
>  error:
> -	if (watch)
> -		audit_put_watch(watch); /* tmp watch, matches initial get */
>  	return err;
>  }

Since the error label is now just a "return err;", how about removing the 
label entirely and replacing the gotos with returns?

-- 
paul moore
security @ redhat

^ permalink raw reply

* Re: Audit class/lab
From: Steve Grubb @ 2015-07-16 18:12 UTC (permalink / raw)
  To: Smith, Gary R; +Cc: linux-audit@redhat.com
In-Reply-To: <DEE39E62895A1A4B870B6E879DADFA081A4F2BFC@EX10MBOX03.pnnl.gov>

On Thursday, July 16, 2015 05:03:26 PM Smith, Gary R wrote:
> Any chance that your presentation would get recorded for later viewing
> by those of us who have no budget for travel at the end of the fiscal year?

This presentation will not be recorded. Slides will be available. I might do 
something separately from this conference so that there's something people can 
watch. But I expect the lab to be interactive where people can say, "We have 
these requirements, what would be the best way to do it?"  And sometimes, 
there isn't a best way and I take notes to look into it more deeply.

-Steve


> On 07/15/2015 03:22 PM, Steve Grubb wrote:
> > Hello,
> > 
> > I normally don't put the word out about speeches I give, or things like
> > that. But I am going to be teaching a hands-on audit class to demonstrate
> > how to configure, setup rules, and do searching and reporting using the
> > native linux audit tools.
> > 
> > The lab will be part of the Defence in Depth conference in Washington
> > (Tyson's Cormers, VA) on Sept 1. Its free, you just have to register.
> > More info:
> > 
> > http://www.redhat.com/en/about/events/2015-defense-depth
> > 
> > I will be going over new features that aids insider threat detection and
> > signs of intrusion in addition to basics. Bring your questions and
> > problems, let's talk.
> > 
> > -Steve
> > 
> > --
> > Linux-audit mailing list
> > Linux-audit@redhat.com
> > https://www.redhat.com/mailman/listinfo/linux-audit

^ permalink raw reply

* Re: Audit class/lab
From: Smith, Gary R @ 2015-07-16 17:03 UTC (permalink / raw)
  To: Steve Grubb, linux-audit@redhat.com
In-Reply-To: <1604626.3lxFnqoXVB@x2>

Hi Steve,

Any chance that your presentation would get recorded for later viewing
by those of us who have no budget for travel at the end of the fiscal year?

Best regards,

Gary Smith

On 07/15/2015 03:22 PM, Steve Grubb wrote:
> Hello,
>
> I normally don't put the word out about speeches I give, or things like that. 
> But I am going to be teaching a hands-on audit class to demonstrate how to 
> configure, setup rules, and do searching and reporting using the native linux 
> audit tools.
>
> The lab will be part of the Defence in Depth conference in Washington (Tyson's 
> Cormers, VA) on Sept 1. Its free, you just have to register. More info:
>
> http://www.redhat.com/en/about/events/2015-defense-depth
>
> I will be going over new features that aids insider threat detection and signs 
> of intrusion in addition to basics. Bring your questions and problems, let's 
> talk.
>
> -Steve
>
> --
> Linux-audit mailing list
> Linux-audit@redhat.com
> https://www.redhat.com/mailman/listinfo/linux-audit
>

^ permalink raw reply

* Re: [PATCH 1/5] Enable cross compiling
From: Clayton Shotwell @ 2015-07-16 13:12 UTC (permalink / raw)
  To: Steve Grubb; +Cc: linux-audit
In-Reply-To: <1810330.TXo9gmCVWY@x2>

Steve,

Thanks for taking a look at my patch.

On Wed, Jul 15, 2015 at 3:38 PM, Steve Grubb <sgrubb@redhat.com> wrote:
> On Thursday, May 28, 2015 08:04:05 AM Clayton Shotwell wrote:
>> During the audit build, several lookup tables are generated as header
>> files that are then linked in with the executables. This process is done
>> by a C application that needs to be able to be run on the host. The
>> current Makfile structure tries to build these executables for the
>> target instead of the host where they cannot be executed. This patch
>> reworks the Makefile structure to build for the correct platform.
>>
>> This patch is a rework of a patch posted to the audit mailing list at
>> the link below.
>> https://www.redhat.com/archives/linux-audit/2012-November/msg00000.html
>>
>> The ax_prog_cc_for_build.m4 file was obtained from GNU at the link
>> below.
>> http://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html
>>
>> Signed-off-by: Clayton Shotwell <clayton.shotwell@rockwellcollins.com>
>
> This patch causes a problem during a normal build:
>
> Making all in lib
> make[2]: Entering directory '/home/sgrubb/working/BUILD/audit-2.4.3/lib'
> make[2]: *** No rule to make target 'gen_tables.c', needed by
> 'gen_actiontabs_h'.  Stop.

That's odd. I'll see if I can reproduce it here and get the patch reworked.

Thanks,
Clayton

Clayton Shotwell
Senior Software Engineer, Rockwell Collins
clayton.shotwell@rockwellcollins.com

^ permalink raw reply

* Re: Auditd framework slowdowns (sometimes freezes) the entire system.
From: Steve Grubb @ 2015-07-16 12:56 UTC (permalink / raw)
  To: linux-audit
In-Reply-To: <09D2CD6A-EA4F-4925-BAB5-44086B86424B@gmail.com>

On Thursday, July 16, 2015 08:38:22 AM Kangkook Jee wrote:
> I'm writing a custom user-land auditd client subscribing to kauditd to
> monitor a number of system calls that we are interested. My auditd client
> seems to work fine in overall but I found unexpected behavior of auditd
> framework which slows down (or sometimes freezes) the entire system as the
> consuming rate of audit client couldn't catch up the speed of audit message
> generation.

This is by design. Auditing is so important that we cannot let even 1 event 
escape the audit trail. To people that count on auditing, they would normally 
rather have access denied than lose the ability to track who's accessing 
something.

This leads to a couple issues. One is have you done anything about priority? 
Did you give your daemon a healthy boost over the other processes so it gets 
more runtime than normal processes? How about cgroups? Have you checked disk 
synchronization techniques (some yield worse performance but guarantee its 
written)? What about gprof traces to see where the "hotspots" are in your 
daemon?

> Here's the simple code snippet used to reproduce the problem.
> 
> //
> // To build.
> // g++ -o simple_audit -std=c++11 -L/usr/lib/x86_64-linux-gnu/  main.cpp
> -laudit //
> #include <libaudit.h>
> #include <sys/types.h>
> #include <unistd.h>
> 
> #include <cassert>
> #include <iostream>
> 
> static int32_t fd = -1;
> static bool au_listen_flag = true;
> 
> int main(int argc, char* argv[]) {
>     struct audit_reply rep;
>     uint64_t cnt = 0;
> 
>     if (argc != 2) {
>         fprintf(stderr, "Invalid usage: %s <sleep_interval>\n", argv[0]);
>         exit(1);
>     }
> 
>     uint32_t sleep_time = atoi(argv[1]);
> 
>     fd = audit_open();
>     if (fd < 0) {
>         // error handling.
>         std::cerr << "Invalid fd returned: " + std::to_string(fd) <<
> std::endl; exit(-1);
>     }
>     int32_t ret = audit_set_pid(fd, getpid(), WAIT_YES);
>     if (ret < 0) {
>         std::cerr << "audit_set_pid failed: " + std::to_string(fd) <<
> std::endl; exit(-1);
>     }
> 
>     while (au_listen_flag) {
>         int32_t rc = audit_get_reply(fd, &rep, GET_REPLY_BLOCKING, 0);
>         if (rc > 0) {
>             cnt++;
>         }
> 
>         usleep(sleep_time);

Why would you do this? You ought to be using epoll or something like that to 
wait on next event.

>         if (cnt % 10000 == 0) {
>             printf ("messages %lu\n", cnt);
>         }
>     }
>     close(fd);
> }
> 
> 
> The problem becomes more apparent as we increase the amount of sleep time
> that is provided as a first command line argument (say a thousand
> Milli-seconds) and simultaneously run some heavy-load tasks (i.e., kernel
> build).
> 
> sudo ./simple_audit 1000
> 
> Here's the command line that we used to add system calls to be monitored and
> enable.
> 
> # Adding events.
> /sbin/auditctl -a exit,always -F arch=b64 -S clone -S close -S creat -S dup
> -S dup2 -S dup3 -S execve -S exit -S exit_group -S fork -S open -S openat
> -S unlink -S unlinkat -S vfork -S 288 -S accept -S bind -S connect -S
> listen -S socket -S socketpair

Next question...why would you want all those syscalls? Do you want them for 
daemons and users? Normally daemons are considered normal system function and 
are not of interest. What is of interest is what users do. So, to weed out 
damons, you don't want anything with auid=-1. Because the kernel uses unsigned 
numbers, you would add

-F auid>=1000 -F auid!=-1

to the rule. That might make a big difference.

> # Enabling events.
> /sbin/auditctl -e1 -b 102400
> 
> At the very moment, "auditctl -s" indicating that kernel buffer is filled up
> but it does not throw away audit messages ('lost' is not increasing ).
> 
> # auditctl -s
> AUDIT_STATUS: enabled=1 flag=1 pid=29887 rate_limit=0 backlog_limit=102400
> lost=270878600 backlog=102402 # auditctl -s
> AUDIT_STATUS: enabled=1 flag=1 pid=29887 rate_limit=0 backlog_limit=102400
> lost=270878600 backlog=102402
> 
> Could anyone guide me how to configure kauditd's buffer setting so that it
> can dump audit messages when the buffer is filled up and user-land consumer
> can't catch up the speed of audit message produce?

If you don't mind losing events, you can also listen on the netlink socket 
without setting the pid the same way that journald does it. That is a best 
effort connection and not guaranteed to be lossless.

-Steve

^ permalink raw reply

* Auditd framework slowdowns (sometimes freezes) the entire system.
From: Kangkook Jee @ 2015-07-16 12:38 UTC (permalink / raw)
  To: linux-audit

Hi all,

I'm writing a custom user-land auditd client subscribing to kauditd to monitor a
number of system calls that we are interested. My auditd client seems to work
fine in overall but I found unexpected behavior of auditd framework which slows
down (or sometimes freezes) the entire system as the consuming rate of audit
client couldn't catch up the speed of audit message generation.

Here's the simple code snippet used to reproduce the problem.

//
// To build.
// g++ -o simple_audit -std=c++11 -L/usr/lib/x86_64-linux-gnu/  main.cpp -laudit
//
#include <libaudit.h>
#include <sys/types.h>
#include <unistd.h>

#include <cassert>
#include <iostream>

static int32_t fd = -1;
static bool au_listen_flag = true;

int main(int argc, char* argv[]) {
    struct audit_reply rep;
    uint64_t cnt = 0;

    if (argc != 2) {
        fprintf(stderr, "Invalid usage: %s <sleep_interval>\n", argv[0]);
        exit(1);
    }

    uint32_t sleep_time = atoi(argv[1]);

    fd = audit_open();
    if (fd < 0) {
        // error handling.
        std::cerr << "Invalid fd returned: " + std::to_string(fd) << std::endl;
        exit(-1);
    }
    int32_t ret = audit_set_pid(fd, getpid(), WAIT_YES);
    if (ret < 0) {
        std::cerr << "audit_set_pid failed: " + std::to_string(fd) << std::endl;
        exit(-1);
    }

    while (au_listen_flag) {
        int32_t rc = audit_get_reply(fd, &rep, GET_REPLY_BLOCKING, 0);
        if (rc > 0) {
            cnt++;
        }

        usleep(sleep_time);

        if (cnt % 10000 == 0) {
            printf ("messages %lu\n", cnt);
        }
    }
    close(fd);
}


The problem becomes more apparent as we increase the amount of sleep time that
is provided as a first command line argument (say a thousand Milli-seconds) and
simultaneously run some heavy-load tasks (i.e., kernel build). 

sudo ./simple_audit 1000

Here's the command line that we used to add system calls to be monitored and
enable.

# Adding events.
/sbin/auditctl -a exit,always -F arch=b64 -S clone -S close -S creat -S dup -S dup2 -S dup3 -S execve -S exit -S exit_group -S fork -S open -S openat -S unlink -S unlinkat -S vfork -S 288 -S accept -S bind -S connect -S listen -S socket -S socketpair

# Enabling events.
/sbin/auditctl -e1 -b 102400

At the very moment, "auditctl -s" indicating that kernel buffer is filled up but
it does not throw away audit messages ('lost' is not increasing ). 

# auditctl -s
AUDIT_STATUS: enabled=1 flag=1 pid=29887 rate_limit=0 backlog_limit=102400 lost=270878600 backlog=102402
# auditctl -s
AUDIT_STATUS: enabled=1 flag=1 pid=29887 rate_limit=0 backlog_limit=102400 lost=270878600 backlog=102402

Could anyone guide me how to configure kauditd's buffer setting so that it can
dump audit messages when the buffer is filled up and user-land consumer can't
catch up the speed of audit message produce?

Thanks a lot for your help in advance!

Regards, Kangkook

^ permalink raw reply

* Audit class/lab
From: Steve Grubb @ 2015-07-15 22:19 UTC (permalink / raw)
  To: linux-audit

Hello,

I normally don't put the word out about speeches I give, or things like that. 
But I am going to be teaching a hands-on audit class to demonstrate how to 
configure, setup rules, and do searching and reporting using the native linux 
audit tools.

The lab will be part of the Defence in Depth conference in Washington (Tyson's 
Cormers, VA) on Sept 1. Its free, you just have to register. More info:

http://www.redhat.com/en/about/events/2015-defense-depth

I will be going over new features that aids insider threat detection and signs 
of intrusion in addition to basics. Bring your questions and problems, let's 
talk.

-Steve

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox