Re: Refactoring src/ausearch-report.c:output_interpreted_node()

2014-10-02 Thread Burn Alting
Thanks Steve,

Patch to follow this weekend.

Rgds

On Wed, 2014-10-01 at 18:28 -0400, Steve Grubb wrote:
 On Thursday, October 02, 2014 07:52:47 AM Burn Alting wrote:
  On Wed, 2014-10-01 at 17:19 -0400, Steve Grubb wrote:
   On Thursday, October 02, 2014 07:08:13 AM Burn Alting wrote:
On Wed, 2014-10-01 at 14:54 -0400, Steve Grubb wrote:
  I am uncertain what effect of accepting this additional format would
  have when adding rules to the running audit system - i.e.
  audit_name_to_msg_type() is called by autrace/auditctl when parsing
  rules (ie the msgtype field name).
 
 I think ausearch-report.c might be the place that needs updating.

So, could we modify output_interpreted_node() to no longer re-parse the

   [node=node] type=type msg=audit(epochsecs.msecs:serial)

header and pass both the lnode and llist-e which has this data already
as the code

  if (num == -1) {
  
  // see if we are older and wiser now.
  bptr = strchr(str, '[');
  if (bptr  bptr  ptr) {
  
  char *eptr;
  bptr++;
  eptr = strchr(bptr, ']');
  if (eptr) {
  
   *eptr = 0;
   errno = 0;
   num = strtoul(bptr, NULL, 10);
   *eptr = ']';
   if (errno)
   
   num = -1;
  
  }
   
   }
 
 }

which parses for

type=.*[n].*

is no longer needed as we don't have that format any more?
   
   That is a very loose check for UNKNOWN[]. If you see a performance
   improvement by refactoring this function, please send a patch. The output
   needs to be identical to the old way.
   
   Thanks,
   -Steve
  
  I can provide a patch to refactor this part of the code, but I want to
  confirm there is no longer a need to parse for
  
type=some_text '[' integer_type ']' some_other_text
 
 While this may have been implied by the code, the fact is that [ ] would only 
 be in type fields when its unknown[].
 
 
  given my refactoring will rely upon the parsing already done by
  lib/lookup_table.c:audit_name_to_msg_type(). Remember this routine only
  parses for
  Given
  type=type_value
  then
  type_value
  is parsed for
  - a known string
  - a long integer number, n, found in the specific string
  UNKNOWN[n]
  - a long integer number, n, found in the specific string
  n
 
 These 3 formats are all that it can ever be. So, I think you have a correct 
 understanding.
 
 -Steve


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


Re: Audit format utility

2014-10-02 Thread Steve Grubb
On Thursday, October 02, 2014 07:44:32 AM Burn Alting wrote:
 On Wed, 2014-10-01 at 14:44 -0400, Steve Grubb wrote:
   Further, it has a couple of immediate issues given it's using
   libauparse.
   
   -  it is lossy in that it wont parse poorly formed audit events (see
   the op key value pair below)
   
   [burn@swtf auformat]$ cat add_user.txt
   node=swtf.swtf.dyndns.org type=ADD_USER
   msg=audit(1411871714.393:47872): user pid=13455 uid=0 auid=500
   ses=11
   subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
   msg='op=adding home directory id=502 exe=/usr/sbin/useradd
   hostname=? addr=? terminal=pts/2 res=success'
   [burn@swtf auformat]$ ./auformat %node %date %time %milli %
   serial: type=%TYPE msg=%msg op=%op auid=%auid pid=%pid  path=%
   path exe=%exe subj=%subj hostname=%hostname terminal=%terminal
   res=%res\n add_user.txt
   swtf.swtf.dyndns.org 09/28/2014 12:35:14 393 47872:
   type=ADD_USER msg= op=adding auid=500 pid=13455  path=
   exe=/usr/sbin/useradd
   subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
   hostname=? terminal=pts/2 res=success
   [burn@swtf auformat]$
   
   We loose the strings
   
   - 'user' before the pid key
  
  Which is meaningless in this case.
  
   - op='adding home directory' becomes op'adding'
   
   This is particularly important for incorrectly formatted application
   level audit sent via auditd.
  
  This is a problem in the shadow-utils package. It is the one that I'm
  currently having to re-do for this reason and many more. Upstream seems to
  have taken a stab at re-doming the audit events and pretty much used it
  like syslog.
 
 I suppose my concern is that until we have fixed all the incorrectly
 formatted key values, auparse is going to loose information.

OK. I see. I really think we should get some tool created that can help 
identify these. It could be as simple as pushing into auparse, iterating 
across fields to to recreate the record, then diff the original and the 
recreated.

From that, we can get fixes in place. I think shadow-utils is the package most 
affected.

 
   - 'rewinding' the event's cursor for each possible key, the call to
   auparse_first_record() in print_item(), is probably not what one would
   want - but then again, auformat is just a mock up at the moment.
  
  Well, if you want your fields in a specific order and its not the order in
  the event, then we have no choice. Note that the event is alrady parsed
  at this point so we are just literally changing the position in a linked
  list. The cost is a series of strcmp calls.
  
   - one looses the parsing 'fix-up' that ausearch does in
   src/ausearch-report.c:output_interpreted_node()
  
  Not sure what fix-up we are talking about. The intention is that auparse
  completely mimicks ausearch's interpretation ability (which ausearch was
  switched over to use auparse a few releases back).
 
 By 'fix-up' I meant the code like
 // Some user messages have msg='uid=500   in this case
 // skip the msg= piece since the real stuff is the uid=
 ...
// Value side  has commas and another field exists
// Known: LABEL_LEVEL_CHANGE banners=none,none
// Known: ROLL_ASSIGN new-role=r,r
// Known: any MAC LABEL can potentially have commas
 etc

Auparse should handle these.


   - to build a complete event, having addressed the 'rewinding' issue,
   would make the format look very messy - you would need to include every
   possible key to print all key/values.
  
  If you wanted that, yeah. But I am thinking of cases where one may not
  want
  every field. For example, you might do something like this to check file
  access:
  
  
  # ausearch --start today -m path --raw |
  
  auformat 'auid=%AUID res=%SUCCESS name=%NAME\n'
  
   - one should add event separation so that further tools could process
   the data more easily.
  
  I am thinking of 1 event per line. This is kind of a requirement of Map
  Reduce.
 
 So you expect the complete event of my tailing audit.log
 node=swtf.swtf.dyndns.org type=SYSCALL
 msg=audit(1412198543.190:141570): arch=c03e syscall=59
 success=yes exit=0 a0=1a2d530 a1=1a2d350 a2=1a06f10 a3=20
 items=2 ppid=19529 pid=32647 auid=500 uid=0 gid=0 euid=0 suid=0
 fsuid=0 egid=0 sgid=0 fsgid=0 tty=pts0 ses=1 comm=tail
 exe=/usr/bin/tail
 subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023
 key=cmds
 node=swtf.swtf.dyndns.org type=EXECVE
 msg=audit(1412198543.190:141570): argc=3 a0=tail a1=-f
 a2=/var/log/audit/audit.log
 node=swtf.swtf.dyndns.org type=CWD
 msg=audit(1412198543.190:141570):  cwd=/home/burn
 node=swtf.swtf.dyndns.org type=PATH
 

[PATCH 0/7] audit fsnotify cleanups for watches and trees

2014-10-02 Thread Richard Guy Briggs
This is a collection of patches to clean up some issues discovered while
implementing audit by exe path.

They compile and have been lightly tested.

I'd be interested in feedback about approaches or details or grossly
misunderstanding some fundamental concepts.

Thanks!

Richard Guy Briggs (7):
  audit: put rule existence check in canonical order
  audit: cull redundancy in audit_rule_change
  audit: eliminate string copy for new tree rules
  audit: optimize add to parent skipping needless search and consuming
parent ref
  audit: remove redundant watch refcount
  audit: remove extra audit_get_parent()
  audit: rename audit_log_remove_rule to disambiguate for trees

 kernel/audit_tree.c  |   13 +++--
 kernel/audit_watch.c |   29 -
 kernel/auditfilter.c |   34 +++---
 3 files changed, 34 insertions(+), 42 deletions(-)

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


[PATCH 4/7] audit: optimize add to parent skipping needless search and consuming parent ref

2014-10-02 Thread Richard Guy Briggs
When parent has just been created there is no need to search for the parent in
the list.  Add a parameter to skip the search and consume the parent reference
no matter what happens.

Signed-off-by: Richard Guy Briggs r...@redhat.com
---
 kernel/audit_watch.c |   23 +++
 1 files changed, 15 insertions(+), 8 deletions(-)

diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index ad9c168..f209448 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -372,15 +372,20 @@ static int audit_get_nd(struct audit_watch *watch, struct 
path *parent)
 }
 
 /* Associate the given rule with an existing parent.
- * Caller must hold audit_filter_mutex. */
+ * Caller must hold audit_filter_mutex.
+ * Consumes parent reference. */
 static void audit_add_to_parent(struct audit_krule *krule,
-   struct audit_parent *parent)
+   struct audit_parent *parent,
+   int new)
 {
struct audit_watch *w, *watch = krule-watch;
int watch_found = 0;
 
BUG_ON(!mutex_is_locked(audit_filter_mutex));
 
+   if (new)
+   goto not_found;
+
list_for_each_entry(w, parent-watches, wlist) {
if (strcmp(watch-path, w-path))
continue;
@@ -396,12 +401,15 @@ static void audit_add_to_parent(struct audit_krule *krule,
break;
}
 
+not_found:
if (!watch_found) {
-   audit_get_parent(parent);
watch-parent = parent;
 
list_add(watch-wlist, parent-watches);
-   }
+   } else
+   /* match get in audit_find_parent or audit_init_parent */
+   audit_put_parent(parent);
+
list_add(krule-rlist, watch-rules);
 }
 
@@ -413,6 +421,7 @@ int audit_add_watch(struct audit_krule *krule, struct 
list_head **list)
struct audit_parent *parent;
struct path parent_path;
int h, ret = 0;
+   int new = 0;
 
mutex_unlock(audit_filter_mutex);
 
@@ -433,12 +442,10 @@ int audit_add_watch(struct audit_krule *krule, struct 
list_head **list)
ret = PTR_ERR(parent);
goto error;
}
+   new = 1;
}
 
-   audit_add_to_parent(krule, parent);
-
-   /* match get in audit_find_parent or audit_init_parent */
-   audit_put_parent(parent);
+   audit_add_to_parent(krule, parent, new);
 
h = audit_hash_ino((u32)watch-ino);
*list = audit_inode_hash[h];
-- 
1.7.1

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


[PATCH 5/7] audit: remove redundant watch refcount

2014-10-02 Thread Richard Guy Briggs
Remove extra layer of audit_{get,put}_watch() calls.

Signed-off-by: Richard Guy Briggs r...@redhat.com
---
 kernel/audit_watch.c |5 +
 kernel/auditfilter.c |7 ---
 2 files changed, 1 insertions(+), 11 deletions(-)

diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index f209448..c707afb 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -203,7 +203,6 @@ int audit_to_watch(struct audit_krule *krule, char *path, 
int len, u32 op)
if (IS_ERR(watch))
return PTR_ERR(watch);
 
-   audit_get_watch(watch);
krule-watch = watch;
 
return 0;
@@ -306,7 +305,6 @@ static void audit_update_watch(struct audit_parent *parent,
 * new watch.
 */
audit_put_watch(nentry-rule.watch);
-   audit_get_watch(nwatch);
nentry-rule.watch = nwatch;
list_add(nentry-rule.rlist, nwatch-rules);
list_add_rcu(nentry-list, 
audit_inode_hash[h]);
@@ -392,8 +390,7 @@ static void audit_add_to_parent(struct audit_krule *krule,
 
watch_found = 1;
 
-   /* put krule's and initial refs to temporary watch */
-   audit_put_watch(watch);
+   /* put krule's ref to temporary watch */
audit_put_watch(watch);
 
audit_get_watch(w);
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index facd704..5675916 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -563,8 +563,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);
@@ -942,8 +940,6 @@ static inline int audit_add_rule(struct audit_entry *entry)
return 0;
 
 error:
-   if (watch)
-   audit_put_watch(watch); /* tmp watch, matches initial get */
return err;
 }
 
@@ -951,7 +947,6 @@ error:
 static inline int audit_del_rule(struct audit_entry *entry)
 {
struct audit_entry  *e;
-   struct audit_watch *watch = entry-rule.watch;
struct audit_tree *tree = entry-rule.tree;
struct list_head *list;
int ret = 0;
@@ -992,8 +987,6 @@ static inline int audit_del_rule(struct audit_entry *entry)
mutex_unlock(audit_filter_mutex);
 
 out:
-   if (watch)
-   audit_put_watch(watch); /* match initial get */
if (tree)
audit_put_tree(tree);   /* that's the temporary one */
 
-- 
1.7.1

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


[PATCH 7/7] audit: rename audit_log_remove_rule to disambiguate for trees

2014-10-02 Thread Richard Guy Briggs
Rename audit_log_remove_rule() to audit_tree_log_remove_rule() to avoid
confusion with watch and mark rule removal/changes.

Signed-off-by: Richard Guy Briggs r...@redhat.com
---
 kernel/audit_tree.c |4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index ace72ed..866d403 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -450,7 +450,7 @@ static int tag_chunk(struct inode *inode, struct audit_tree 
*tree)
return 0;
 }
 
-static void audit_log_remove_rule(struct audit_krule *rule)
+static void audit_tree_log_remove_rule(struct audit_krule *rule)
 {
struct audit_buffer *ab;
 
@@ -477,7 +477,7 @@ static void kill_rules(struct audit_tree *tree)
list_del_init(rule-rlist);
if (rule-tree) {
/* not a half-baked one */
-   audit_log_remove_rule(rule);
+   audit_tree_log_remove_rule(rule);
rule-tree = NULL;
list_del_rcu(entry-list);
list_del(entry-rule.list);
-- 
1.7.1

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


[PATCH 6/7] audit: remove extra audit_get_parent()

2014-10-02 Thread Richard Guy Briggs
There appears to be an extra parent reference taken.  Remove it.

Signed-off-by: Richard Guy Briggs r...@redhat.com
---
 kernel/audit_watch.c |1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index c707afb..eb53bc7 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -462,7 +462,6 @@ void audit_remove_watch_rule(struct audit_krule *krule)
audit_remove_watch(watch);
 
if (list_empty(parent-watches)) {
-   audit_get_parent(parent);
fsnotify_destroy_mark(parent-mark, audit_watch_group);
audit_put_parent(parent);
}
-- 
1.7.1

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


[PATCH 2/7] audit: cull redundancy in audit_rule_change

2014-10-02 Thread Richard Guy Briggs
Re-factor audit_rule_change() to reduce the amount of code redundancy and
simplify the logic.

Signed-off-by: Richard Guy Briggs r...@redhat.com
---
 kernel/auditfilter.c |   20 +++-
 1 files changed, 7 insertions(+), 13 deletions(-)

diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 4a11697..e3378a4 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -1064,30 +1064,24 @@ int audit_rule_change(int type, __u32 portid, int seq, 
void *data,
int err = 0;
struct audit_entry *entry;
 
+   entry = audit_data_to_entry(data, datasz);
+   if (IS_ERR(entry))
+   return PTR_ERR(entry);
+
switch (type) {
case AUDIT_ADD_RULE:
-   entry = audit_data_to_entry(data, datasz);
-   if (IS_ERR(entry))
-   return PTR_ERR(entry);
-
err = audit_add_rule(entry);
audit_log_rule_change(add_rule, entry-rule, !err);
-   if (err)
-   audit_free_rule(entry);
break;
case AUDIT_DEL_RULE:
-   entry = audit_data_to_entry(data, datasz);
-   if (IS_ERR(entry))
-   return PTR_ERR(entry);
-
err = audit_del_rule(entry);
audit_log_rule_change(remove_rule, entry-rule, !err);
-   audit_free_rule(entry);
break;
-   default:
-   return -EINVAL;
}
 
+   if (err || type == AUDIT_DEL_RULE)
+   audit_free_rule(entry);
+
return err;
 }
 
-- 
1.7.1

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


[PATCH 1/7] audit: put rule existence check in canonical order

2014-10-02 Thread Richard Guy Briggs
Use same rule existence check order as audit_make_tree(), audit_to_watch(),
update_lsm_rule() for legibility.

Signed-off-by: Richard Guy Briggs r...@redhat.com
---
 kernel/auditfilter.c |2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 40ed981..4a11697 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -163,7 +163,7 @@ static inline int audit_to_inode(struct audit_krule *krule,
 struct audit_field *f)
 {
if (krule-listnr != AUDIT_FILTER_EXIT ||
-   krule-watch || krule-inode_f || krule-tree ||
+   krule-inode_f || krule-watch || krule-tree ||
(f-op != Audit_equal  f-op != Audit_not_equal))
return -EINVAL;
 
-- 
1.7.1

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


[PATCH 3/7] audit: eliminate string copy for new tree rules

2014-10-02 Thread Richard Guy Briggs
New tree rules copy the path twice and discard the intermediary copy.

This saves one pointer at the expense of one path string copy.

Signed-off-by: Richard Guy Briggs r...@redhat.com
---
 kernel/audit_tree.c  |9 +
 kernel/auditfilter.c |5 +++--
 2 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index bd418c4..ace72ed 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -17,7 +17,7 @@ struct audit_tree {
struct list_head list;
struct list_head same_root;
struct rcu_head head;
-   char pathname[];
+   char *pathname;
 };
 
 struct audit_chunk {
@@ -70,11 +70,11 @@ static LIST_HEAD(prune_list);
 
 static struct fsnotify_group *audit_tree_group;
 
-static struct audit_tree *alloc_tree(const char *s)
+static struct audit_tree *alloc_tree(char *s)
 {
struct audit_tree *tree;
 
-   tree = kmalloc(sizeof(struct audit_tree) + strlen(s) + 1, GFP_KERNEL);
+   tree = kmalloc(sizeof(struct audit_tree), GFP_KERNEL);
if (tree) {
atomic_set(tree-count, 1);
tree-goner = 0;
@@ -83,7 +83,7 @@ static struct audit_tree *alloc_tree(const char *s)
INIT_LIST_HEAD(tree-list);
INIT_LIST_HEAD(tree-same_root);
tree-root = NULL;
-   strcpy(tree-pathname, s);
+   tree-pathname = s;
}
return tree;
 }
@@ -96,6 +96,7 @@ static inline void get_tree(struct audit_tree *tree)
 static inline void put_tree(struct audit_tree *tree)
 {
if (atomic_dec_and_test(tree-count))
+   kfree(tree-pathname);
kfree_rcu(tree, head);
 }
 
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index e3378a4..facd704 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -534,9 +534,10 @@ static struct audit_entry *audit_data_to_entry(struct 
audit_rule_data *data,
entry-rule.buflen += f-val;
 
err = audit_make_tree(entry-rule, str, f-op);
-   kfree(str);
-   if (err)
+   if (err) {
+   kfree(str);
goto exit_free;
+   }
break;
case AUDIT_INODE:
err = audit_to_inode(entry-rule, f);
-- 
1.7.1

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


[PATCH V5 1/5] audit: implement audit by executable

2014-10-02 Thread Richard Guy Briggs
From: Eric Paris epa...@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.

Based-on-user-interface-by: Richard Guy Briggs r...@redhat.com
Cc: r...@redhat.com
Based-on-idea-by: Peter Moody pmo...@google.com
Cc: pmo...@google.com
Signed-off-by: Eric Paris epa...@redhat.com
Signed-off-by: Richard Guy Briggs r...@redhat.com
---
 include/linux/audit.h  |1 +
 include/uapi/linux/audit.h |2 +
 kernel/Makefile|2 +-
 kernel/audit.h |   32 +
 kernel/audit_exe.c |  109 
 kernel/auditfilter.c   |   44 ++
 kernel/auditsc.c   |   16 ++
 7 files changed, 205 insertions(+), 1 deletions(-)
 create mode 100644 kernel/audit_exe.c

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 36dffec..ce51204 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -59,6 +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 list_headrlist;  /* entry in audit_{watch,tree}.rules 
list */
struct list_headlist;   /* for AUDIT_LIST* purposes only */
u64 prio;
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 4d100c8..101d344 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -266,6 +266,8 @@
 #define AUDIT_OBJ_UID  109
 #define AUDIT_OBJ_GID  110
 #define AUDIT_FIELD_COMPARE111
+#define AUDIT_EXE  112
+#define AUDIT_EXE_CHILDREN 113
 
 #define AUDIT_ARG0  200
 #define AUDIT_ARG1  (AUDIT_ARG0+1)
diff --git a/kernel/Makefile b/kernel/Makefile
index f2a8b62..60def04 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -63,7 +63,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
+obj-$(CONFIG_AUDIT_WATCH) += audit_watch.o audit_exe.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 3cdffad..7825c7e 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -56,6 +56,7 @@ enum audit_state {
 
 /* Rule lists */
 struct audit_watch;
+struct audit_exe;
 struct audit_tree;
 struct audit_chunk;
 
@@ -279,6 +280,13 @@ extern int audit_add_watch(struct audit_krule *krule, 
struct list_head **list);
 extern void audit_remove_watch_rule(struct audit_krule *krule);
 extern char *audit_watch_path(struct audit_watch *watch);
 extern int audit_watch_compare(struct audit_watch *watch, unsigned long ino, 
dev_t dev);
+
+int audit_make_exe_rule(struct audit_krule *krule, char *pathname, int len, 
u32 op);
+void audit_remove_exe_rule(struct audit_krule *krule);
+char *audit_exe_path(struct audit_exe *exe);
+int audit_dup_exe(struct audit_krule *new, struct audit_krule *old);
+int audit_exe_compare(struct task_struct *tsk, struct audit_exe *exe);
+
 #else
 #define audit_put_watch(w) {}
 #define audit_get_watch(w) {}
@@ -288,6 +296,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_dup_exe(struct audit_krule *new, struct audit_krule 
*old)
+{
+   BUG();
+   return -EINVAL
+}
+static inline int audit_exe_compare(struct task_struct *tsk, struct audit_exe 
*exe)
+{
+   BUG();
+   return 0;
+}
 #endif /* CONFIG_AUDIT_WATCH */
 
 #ifdef CONFIG_AUDIT_TREE
diff --git a/kernel/audit_exe.c b/kernel/audit_exe.c
new file mode 100644
index 000..ec3231b
--- /dev/null
+++ b/kernel/audit_exe.c
@@ -0,0 +1,109 @@
+/* audit_exe.c -- filtering of audit events
+ *
+ * Copyright 2014 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; 

[PATCH V5 3/5] audit: convert audit_exe to audit_fsnotify

2014-10-02 Thread Richard Guy Briggs
From: Eric Paris epa...@redhat.com

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

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

diff --git a/include/linux/audit.h b/include/linux/audit.h
index ce51204..0ffa268 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_headrlist;  /* entry in audit_{watch,tree}.rules 
list */
struct list_headlist;   /* for AUDIT_LIST* purposes only */
u64 prio;
diff --git a/kernel/audit.h b/kernel/audit.h
index b8ecc06..9821732 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -57,7 +57,6 @@ enum audit_state {
 /* Rule lists */
 struct audit_watch;
 struct audit_fsnotify_mark;
-struct audit_exe;
 struct audit_tree;
 struct audit_chunk;
 
@@ -288,11 +287,8 @@ char *audit_mark_path(struct audit_fsnotify_mark *mark);
 void audit_remove_mark(struct audit_fsnotify_mark *audit_mark);
 int audit_mark_compare(struct audit_fsnotify_mark *mark, unsigned long ino, 
dev_t dev);
 
-int audit_make_exe_rule(struct audit_krule *krule, char *pathname, int len, 
u32 op);
-void audit_remove_exe_rule(struct audit_krule *krule);
-char *audit_exe_path(struct audit_exe *exe);
 int audit_dup_exe(struct audit_krule *new, struct audit_krule *old);
-int audit_exe_compare(struct task_struct *tsk, struct audit_exe *exe);
+int audit_exe_compare(struct task_struct *tsk, struct audit_fsnotify_mark 
*mark);
 
 #else
 #define audit_put_watch(w) {}
@@ -319,36 +315,18 @@ static inline void audit_remove_mark(struct 
audit_fsnotify_mark *audit_mark)
BUG();
 }
 
-static inline int audit_mark_compare(struct audit_fsnotify_mark *mark, 
unsigned long ino, dev_t dev)
+static inline int audit_exe_compare(struct task_struct *tsk, struct 
audit_fsnotify_mark *mark)
 {
BUG();
-   return 0;
-}
-
-static inline int audit_make_exe_rule(struct audit_krule *krule, char 
*pathname, int len, u32 op)
-{
return -EINVAL;
 }
-static inline void audit_remove_exe_rule(struct audit_krule *krule)
-{
-   BUG();
-   return 0;
-}
-static inline char *audit_exe_path(struct audit_exe *exe)
-{
-   BUG();
-   return ;
-}
+
 static inline int audit_dup_exe(struct audit_krule *new, struct audit_krule 
*old)
 {
BUG();
-   return -EINVAL
-}
-static inline int audit_exe_compare(struct task_struct *tsk, struct audit_exe 
*exe)
-{
-   BUG();
-   return 0;
+   return -EINVAL;
 }
+
 #endif /* CONFIG_AUDIT_WATCH */
 
 #ifdef CONFIG_AUDIT_TREE
diff --git a/kernel/audit_exe.c b/kernel/audit_exe.c
index ec3231b..0c7ee8d 100644
--- a/kernel/audit_exe.c
+++ b/kernel/audit_exe.c
@@ -17,93 +17,30 @@
 
 #include linux/kernel.h
 #include linux/audit.h
-#include linux/mutex.h
 #include linux/fs.h
 #include linux/namei.h
 #include linux/slab.h
 #include audit.h
 
-struct audit_exe {
-   char *pathname;
-   unsigned long ino;
-   dev_t dev;
-};
-
-/* Translate a watch string to kernel respresentation. */
-int audit_make_exe_rule(struct audit_krule *krule, char *pathname, int len, 
u32 op)
-{
-   struct audit_exe *exe;
-   struct path path;
-   struct dentry *dentry;
-   unsigned long ino;
-   dev_t dev;
-
-   if (pathname[0] != '/' || pathname[len-1] == '/')
-   return -EINVAL;
-
-   dentry = kern_path_locked(pathname, path);
-   if (IS_ERR(dentry))
-   return PTR_ERR(dentry);
-   mutex_unlock(path.dentry-d_inode-i_mutex);
-
-   if (!dentry-d_inode)
-   return -ENOENT;
-   dev = dentry-d_inode-i_sb-s_dev;
-   ino = dentry-d_inode-i_ino;
-   dput(dentry);
-
-   exe = kmalloc(sizeof(*exe), GFP_KERNEL);
-   if (!exe)
-   return -ENOMEM;
-   exe-ino = ino;
-   exe-dev = dev;
-   exe-pathname = pathname;
-   krule-exe = exe;
-
-   return 0;
-}
-
-void audit_remove_exe_rule(struct audit_krule *krule)
-{
-   struct audit_exe *exe;
-
-   exe = krule-exe;
-   krule-exe = NULL;
-   kfree(exe-pathname);
-   kfree(exe);
-}
-
-char *audit_exe_path(struct audit_exe *exe)
-{
-   return exe-pathname;
-}
-
 

[PATCH V5 0/5] audit by executable name

2014-10-02 Thread Richard Guy Briggs
This is a part of Peter Moody, my and Eric Paris' work to implement
audit by executable name.

Please see the accompanying userspace patch:
https://www.redhat.com/archives/linux-audit/2014-May/msg00019.html
The userspace interface is not expected to change appreciably unless something
important has been overlooked.  Setting and deleting rules works as expected.

If the path does not exist at rule creation time, it will be re-evaluated every
time there is a change to the parent directory at which point the change in
device and inode will be noted.


Here's a sample run:

# /usr/local/sbin/auditctl -a always,exit -F dir=/tmp -F exe=/bin/touch -F 
key=touch_tmp
# /usr/local/sbin/ausearch --start recent -k touch_tmp
time-Mon Jun 30 14:15:06 2014
type=CONFIG_CHANGE msg=audit(1404152106.683:149): auid=0 ses=1 
subj=unconfined_u :unconfined_r:auditctl_t:s0-s0:c0.c1023 op=add_rule 
key=touch_tmp list=4 res =1

# /usr/local/sbin/auditctl -l
-a always,exit -S all -F dir=/tmp -F exe=/bin/touch -F key=touch_tmp

# touch /tmp/test

# /usr/local/sbin/ausearch --start recent -k touch_tmp
time-Wed Jul  2 12:18:47 2014
type=UNKNOWN[1327] msg=audit(1404317927.319:132): 
proctitle=746F756368002F746D702F74657374
type=PATH msg=audit(1404317927.319:132): item=1 name=/tmp/test inode=25997 
dev=00:20 mode=0100644 ouid=0 ogid=0 rdev=00:00 
obj=unconfined_u:object_r:user_tmp_t:s0 nametype=CREATE
type=PATH msg=audit(1404317927.319:132): item=0 name=/tmp/ inode=11144 
dev=00:20 mode=041777 ouid=0 ogid=0 rdev=00:00 obj=system_u:object_r:tmp_t:s0 
nametype=PARENT
type=CWD msg=audit(1404317927.319:132):  cwd=/root
type=SYSCALL msg=audit(1404317927.319:132): arch=c03e syscall=2 success=yes 
exit=3 a0=7a403dd5 a1=941 a2=1b6 a3=34b65b2c6c items=2 ppid=4321 pid=6436 
auid=0 uid=0 gid=0 euid=0 suid=0 fsuid=0 egid=0 sgid=0 fsgid=0 tty=ttyS0 ses=1 
comm=touch exe=/usr/bin/touch 
subj=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 key=touch_tmp


Revision history:
v5: Revert patch Let audit_free_rule() take care of calling
audit_remove_mark(). since it caused a group mark deadlock.

v4: Re-order and squash down fixups
Fix audit_dup_exe() to copy pathname string before calling 
audit_alloc_mark().

v3: Rationalize and rename some function names and clean up get/put and free 
code.
Rename several watch references to mark.
Rename audit_remove_rule() to audit_remove_mark_rule().
Let audit_free_rule() take care of calling audit_remove_mark().
Put audit_alloc_mark() arguments in same order as watch, tree and inode.
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_remove_mark_rule().
https://www.redhat.com/archives/linux-audit/2014-July/msg0.html

v2: Misguided attempt to add in audit_exe similar to watches
https://www.redhat.com/archives/linux-audit/2014-June/msg00066.html

v1.5: eparis' switch to fsnotify
https://www.redhat.com/archives/linux-audit/2014-May/msg00046.html
https://www.redhat.com/archives/linux-audit/2014-May/msg00066.html

v1: Change to path interface instead of inode
https://www.redhat.com/archives/linux-audit/2014-May/msg00017.html

v0: Peter Moodie's original patches
https://www.redhat.com/archives/linux-audit/2012-August/msg00033.html


Next step:
Get full-path notify working.


Eric Paris (3):
  audit: implement audit by executable
  audit: clean simple fsnotify implementation
  audit: convert audit_exe to audit_fsnotify

Richard Guy Briggs (2):
  audit: avoid double copying the audit_exe path string
  Revert fixup! audit: clean simple fsnotify implementation

 include/linux/audit.h  |1 +
 include/uapi/linux/audit.h |2 +
 kernel/Makefile|2 +-
 kernel/audit.h |   39 +++
 kernel/audit_exe.c |   49 +
 kernel/audit_fsnotify.c|  237 
 kernel/auditfilter.c   |   52 +-
 kernel/auditsc.c   |   16 +++
 8 files changed, 395 insertions(+), 3 deletions(-)
 create mode 100644 kernel/audit_exe.c
 create mode 100644 kernel/audit_fsnotify.c

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


[PATCH V5 4/5] audit: avoid double copying the audit_exe path string

2014-10-02 Thread Richard Guy Briggs
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 r...@redhat.com
---
 kernel/audit_exe.c  |5 -
 kernel/audit_fsnotify.c |   12 ++--
 kernel/auditfilter.c|2 +-
 3 files changed, 7 insertions(+), 12 deletions(-)

diff --git a/kernel/audit_exe.c b/kernel/audit_exe.c
index 0c7ee8d..ff6e3d6 100644
--- a/kernel/audit_exe.c
+++ b/kernel/audit_exe.c
@@ -27,10 +27,13 @@ int audit_dup_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))
+   kfree(pathname);
return PTR_ERR(audit_mark);
new-exe = audit_mark;
 
diff --git a/kernel/audit_fsnotify.c b/kernel/audit_fsnotify.c
index f4b3e66..6daf5c3 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,20 +114,13 @@ 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);
+   if (unlikely(!audit_mark))
goto out;
-   }
 
fsnotify_init_mark(audit_mark-mark, audit_free_fsnotify_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 fff92cf..570e79a 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -575,8 +575,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;
}
-- 
1.7.1

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