public inbox for linux-audit@redhat.com
 help / color / mirror / Atom feed
* [PATCH 1/7] audit: convert audit watches to use fsnotify instead of inotify
@ 2009-06-12 20:31 Eric Paris
  2009-06-12 20:32 ` [PATCH 2/7] audit: redo audit watch locking and refcnt in light of fsnotify Eric Paris
                   ` (6 more replies)
  0 siblings, 7 replies; 11+ messages in thread
From: Eric Paris @ 2009-06-12 20:31 UTC (permalink / raw)
  To: linux-audit; +Cc: viro

Audit currently uses inotify to pin inodes in core and to detect when
watched inodes are deleted or unmounted.  This patch uses fsnotify instead
of inotify.
    
Signed-off-by: Eric Paris <eparis@redhat.com>
---

 include/linux/fsnotify_backend.h |    5 +
 kernel/audit_watch.c             |  209 +++++++++++++++++++++++++++-----------
 2 files changed, 153 insertions(+), 61 deletions(-)

diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 44848aa..90e32cc 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -58,9 +58,12 @@
 				   FS_MOVED_FROM | FS_MOVED_TO | FS_CREATE |\
 				   FS_DELETE)
 
+#define FS_MOVE			(FS_MOVED_FROM | FS_MOVED_TO)
+
 /* listeners that hard code group numbers near the top */
 #define DNOTIFY_GROUP_NUM	UINT_MAX
-#define INOTIFY_GROUP_NUM	(DNOTIFY_GROUP_NUM-1)
+#define AUDIT_WATCH_GROUP_NUM  (DNOTIFY_GROUP_NUM-1)
+#define INOTIFY_GROUP_NUM      (AUDIT_WATCH_GROUP_NUM-1)
 
 struct fsnotify_group;
 struct fsnotify_event;
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index 0c179fb..8d7f264 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -24,17 +24,17 @@
 #include <linux/kthread.h>
 #include <linux/mutex.h>
 #include <linux/fs.h>
+#include <linux/fsnotify_backend.h>
 #include <linux/namei.h>
 #include <linux/netlink.h>
 #include <linux/sched.h>
-#include <linux/inotify.h>
 #include <linux/security.h>
 #include "audit.h"
 
 /*
  * Reference counting:
  *
- * audit_parent: lifetime is from audit_init_parent() to receipt of an IN_IGNORED
+ * audit_parent: lifetime is from audit_init_parent() to receipt of an FS_IGNORED
  * 	event.  Each audit_watch holds a reference to its associated parent.
  *
  * audit_watch: if added to lists, lifetime is from audit_init_watch() to
@@ -56,29 +56,30 @@ struct audit_watch {
 struct audit_parent {
 	struct list_head	ilist;	/* tmp list used to free parents */
 	struct list_head	watches; /* anchor for audit_watch->wlist */
-	struct inotify_watch	wdata;	/* inotify watch data */
+	struct fsnotify_mark_entry mark; /* fsnotify mark on the inode */
 	unsigned		flags;	/* status flags */
 };
 
 static struct kmem_cache *audit_watch_cache __read_mostly;
 static struct kmem_cache *audit_parent_cache __read_mostly;
 
-/* Inotify handle. */
-struct inotify_handle *audit_ih;
+/* fsnotify handle. */
+struct fsnotify_group *audit_watch_group;
 
 /*
  * audit_parent status flags:
  *
  * AUDIT_PARENT_INVALID - set anytime rules/watches are auto-removed due to
  * a filesystem event to ensure we're adding audit watches to a valid parent.
- * Technically not needed for IN_DELETE_SELF or IN_UNMOUNT events, as we cannot
- * receive them while we have nameidata, but must be used for IN_MOVE_SELF which
+ * Technically not needed for FS_DELETE_SELF or FS_UNMOUNT events, as we cannot
+ * receive them while we have nameidata, but must be used for FS_MOVE_SELF which
  * we can receive while holding nameidata.
  */
 #define AUDIT_PARENT_INVALID	0x001
 
-/* Inotify events we care about. */
-#define AUDIT_IN_WATCH IN_MOVE|IN_CREATE|IN_DELETE|IN_DELETE_SELF|IN_MOVE_SELF
+/* fsnotify events we care about. */
+#define AUDIT_FS_WATCH (FS_MOVE | FS_CREATE | FS_DELETE | FS_DELETE_SELF |\
+			FS_MOVE_SELF | FS_EVENT_ON_CHILD)
 
 static void audit_free_parent(struct audit_parent *parent)
 {
@@ -86,14 +87,45 @@ static void audit_free_parent(struct audit_parent *parent)
 	kmem_cache_free(audit_parent_cache, parent);
 }
 
-static void audit_destroy_watch(struct inotify_watch *i_watch)
+static void audit_watch_free_mark(struct fsnotify_mark_entry *entry)
 {
 	struct audit_parent *parent;
 
-	parent = container_of(i_watch, struct audit_parent, wdata);
+	parent = container_of(entry, struct audit_parent, mark);
 	audit_free_parent(parent);
 }
 
+static void audit_get_parent(struct audit_parent *parent)
+{
+	if (likely(parent))
+		fsnotify_get_mark(&parent->mark);
+}
+
+static void audit_put_parent(struct audit_parent *parent)
+{
+	if (likely(parent))
+		fsnotify_put_mark(&parent->mark);
+}
+
+/*
+ * Find and return the audit_parent on the given inode.  If found a reference
+ * is taken on this parent.
+ */
+static inline struct audit_parent *audit_find_parent(struct inode *inode)
+{
+	struct audit_parent *parent = NULL;
+	struct fsnotify_mark_entry *entry;
+
+	spin_lock(&inode->i_lock);
+	entry = fsnotify_find_mark_entry(audit_watch_group, inode);
+	spin_unlock(&inode->i_lock);
+
+	if (entry)
+		parent = container_of(entry, struct audit_parent, mark);
+
+	return parent;
+}
+
 void audit_get_watch(struct audit_watch *watch)
 {
 	atomic_inc(&watch->count);
@@ -112,7 +144,7 @@ void audit_put_watch(struct audit_watch *watch)
 void audit_remove_watch(struct audit_watch *watch)
 {
 	list_del(&watch->wlist);
-	put_inotify_watch(&watch->parent->wdata);
+	audit_put_parent(watch->parent);
 	watch->parent = NULL;
 	audit_put_watch(watch); /* match initial get */
 }
@@ -132,8 +164,9 @@ int audit_watch_compare(struct audit_watch *watch, unsigned long ino, dev_t dev)
 /* Initialize a parent watch entry. */
 static struct audit_parent *audit_init_parent(struct path *parent_path)
 {
+	struct inode *inode = parent_path->dentry->d_inode;
 	struct audit_parent *parent;
-	s32 wd;
+	int ret;
 
 	parent = kmem_cache_zalloc(audit_parent_cache, GFP_KERNEL);
 	if (unlikely(!parent))
@@ -142,14 +175,14 @@ static struct audit_parent *audit_init_parent(struct path *parent_path)
 	INIT_LIST_HEAD(&parent->watches);
 	parent->flags = 0;
 
-	inotify_init_watch(&parent->wdata);
-	/* grab a ref so inotify watch hangs around until we take audit_filter_mutex */
-	get_inotify_watch(&parent->wdata);
-	wd = inotify_add_watch(audit_ih, &parent->wdata,
-			       parent_path->dentry->d_inode, AUDIT_IN_WATCH);
-	if (wd < 0) {
+	fsnotify_init_mark(&parent->mark, audit_watch_free_mark);
+	parent->mark.mask = AUDIT_FS_WATCH;
+	/* grab a ref so fsnotify mark hangs around until we take audit_filter_mutex */
+	audit_get_parent(parent);
+	ret = fsnotify_add_mark(&parent->mark, audit_watch_group, inode);
+	if (ret < 0) {
 		audit_free_parent(parent);
-		return ERR_PTR(wd);
+		return ERR_PTR(ret);
 	}
 
 	return parent;
@@ -178,7 +211,7 @@ int audit_to_watch(struct audit_krule *krule, char *path, int len, u32 op)
 {
 	struct audit_watch *watch;
 
-	if (!audit_ih)
+	if (!audit_watch_group)
 		return -EOPNOTSUPP;
 
 	if (path[0] != '/' || path[len-1] == '/' ||
@@ -216,7 +249,7 @@ static struct audit_watch *audit_dupe_watch(struct audit_watch *old)
 
 	new->dev = old->dev;
 	new->ino = old->ino;
-	get_inotify_watch(&old->parent->wdata);
+	audit_get_parent(old->parent);
 	new->parent = old->parent;
 
 out:
@@ -337,19 +370,21 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
 		audit_remove_watch(w);
 	}
 	mutex_unlock(&audit_filter_mutex);
+
+	fsnotify_destroy_mark_by_entry(&parent->mark);
 }
 
 /* Unregister inotify watches for parents on in_list.
- * Generates an IN_IGNORED event. */
+ * Generates an FS_IGNORED event. */
 void audit_watch_inotify_unregister(struct list_head *in_list)
 {
 	struct audit_parent *p, *n;
 
 	list_for_each_entry_safe(p, n, in_list, ilist) {
 		list_del(&p->ilist);
-		inotify_rm_watch(audit_ih, &p->wdata);
-		/* the unpin matching the pin in audit_remove_watch_rule() */
-		unpin_inotify_watch(&p->wdata);
+		fsnotify_destroy_mark_by_entry(&p->mark);
+		/* matches the get in audit_remove_watch_rule() */
+		audit_put_parent(p);
 	}
 }
 
@@ -383,7 +418,7 @@ static void audit_put_path(struct path *parent_path, struct path *watch_path)
 		path_put(watch_path);
 }
 
-/* Associate the given rule with an existing parent inotify_watch.
+/* Associate the given rule with an existing parent.
  * Caller must hold audit_filter_mutex. */
 static void audit_add_to_parent(struct audit_krule *krule,
 				struct audit_parent *parent)
@@ -391,6 +426,8 @@ static void audit_add_to_parent(struct audit_krule *krule,
 	struct audit_watch *w, *watch = krule->watch;
 	int watch_found = 0;
 
+	BUG_ON(!mutex_is_locked(&audit_filter_mutex));
+
 	list_for_each_entry(w, &parent->watches, wlist) {
 		if (strcmp(watch->path, w->path))
 			continue;
@@ -407,7 +444,7 @@ static void audit_add_to_parent(struct audit_krule *krule,
 	}
 
 	if (!watch_found) {
-		get_inotify_watch(&parent->wdata);
+		audit_get_parent(parent);
 		watch->parent = parent;
 
 		list_add(&watch->wlist, &parent->watches);
@@ -420,7 +457,6 @@ static void audit_add_to_parent(struct audit_krule *krule,
 int audit_add_watch(struct audit_krule *krule, struct list_head **list)
 {
 	struct audit_watch *watch = krule->watch;
-	struct inotify_watch *i_watch;
 	struct audit_parent *parent;
 	struct path parent_path, watch_path;
 	int h, ret = 0;
@@ -446,8 +482,8 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list)
 	 * inotify watch is found, inotify_find_watch() grabs a reference before
 	 * returning.
 	 */
-	if (inotify_find_watch(audit_ih, parent_path.dentry->d_inode,
-			       &i_watch) < 0) {
+	parent = audit_find_parent(parent_path.dentry->d_inode);
+	if (!parent) {
 		parent = audit_init_parent(&parent_path);
 		if (IS_ERR(parent)) {
 			/* caller expects mutex locked */
@@ -455,8 +491,7 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list)
 			ret = PTR_ERR(parent);
 			goto error;
 		}
-	} else
-		parent = container_of(i_watch, struct audit_parent, wdata);
+	}
 
 	mutex_lock(&audit_filter_mutex);
 
@@ -466,8 +501,8 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list)
 	else
 		audit_add_to_parent(krule, parent);
 
-	/* match get in audit_init_parent or inotify_find_watch */
-	put_inotify_watch(&parent->wdata);
+	/* 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];
@@ -488,54 +523,108 @@ void audit_remove_watch_rule(struct audit_krule *krule, struct list_head *list)
 		audit_remove_watch(watch);
 
 		if (list_empty(&parent->watches)) {
-			/* Put parent on the inotify un-registration
-			 * list.  Grab a reference before releasing
+			/* Put parent on the un-registration list.
+			 * Grab a reference before releasing
 			 * audit_filter_mutex, to be released in
-			 * audit_inotify_unregister().
+			 * audit_watch_inotify_unregister().
 			 * If filesystem is going away, just leave
 			 * the sucker alone, eviction will take
 			 * care of it. */
-			if (pin_inotify_watch(&parent->wdata))
-				list_add(&parent->ilist, list);
+			audit_get_parent(parent);
+			list_add(&parent->ilist, list);
 		}
 	}
 }
 
-/* Update watch data in audit rules based on inotify events. */
-static void audit_handle_ievent(struct inotify_watch *i_watch, u32 wd, u32 mask,
-			 u32 cookie, const char *dname, struct inode *inode)
+static bool audit_watch_should_send_event(struct fsnotify_group *group, struct inode *inode, __u32 mask)
+{
+	struct fsnotify_mark_entry *entry;
+	bool send;
+
+	spin_lock(&inode->i_lock);
+	entry = fsnotify_find_mark_entry(group, inode);
+	spin_unlock(&inode->i_lock);
+	if (!entry)
+		return false;
+
+	mask = (mask & ~FS_EVENT_ON_CHILD);
+	send = (entry->mask & mask);
+
+	/* find took a reference */
+	fsnotify_put_mark(entry);
+
+	return send;
+}
+
+/* Update watch data in audit rules based on fsnotify events. */
+static int audit_watch_handle_event(struct fsnotify_group *group, struct fsnotify_event *event)
 {
+	struct inode *inode;
+	__u32 mask = event->mask;
+	const char *dname = event->file_name;
 	struct audit_parent *parent;
 
-	parent = container_of(i_watch, struct audit_parent, wdata);
+	BUG_ON(group != audit_watch_group);
+
+	parent = audit_find_parent(event->to_tell);
+	if (unlikely(!parent))
+		return 0;
 
-	if (mask & (IN_CREATE|IN_MOVED_TO) && inode)
+	switch (event->data_type) {
+	case (FSNOTIFY_EVENT_PATH):
+		inode = event->path.dentry->d_inode;
+		break;
+	case (FSNOTIFY_EVENT_INODE):
+		inode = event->inode;
+		break;
+	default:
+		BUG();
+		inode = NULL;
+		break;
+	};
+
+	if (mask & (FS_CREATE|FS_MOVED_TO) && inode)
 		audit_update_watch(parent, dname, inode->i_sb->s_dev, inode->i_ino, 0);
-	else if (mask & (IN_DELETE|IN_MOVED_FROM))
+	else if (mask & (FS_DELETE|FS_MOVED_FROM))
 		audit_update_watch(parent, dname, (dev_t)-1, (unsigned long)-1, 1);
-	/* inotify automatically removes the watch and sends IN_IGNORED */
-	else if (mask & (IN_DELETE_SELF|IN_UNMOUNT))
-		audit_remove_parent_watches(parent);
-	/* inotify does not remove the watch, so remove it manually */
-	else if(mask & IN_MOVE_SELF) {
+	else if (mask & (FS_DELETE_SELF|FS_UNMOUNT|FS_MOVE_SELF))
 		audit_remove_parent_watches(parent);
-		inotify_remove_watch_locked(audit_ih, i_watch);
-	} else if (mask & IN_IGNORED)
-		put_inotify_watch(i_watch);
+	/* moved put_inotify_watch to freeing mark */
+
+	/* matched the ref taken by audit_find_parent */
+	audit_put_parent(parent);
+
+	return 0;
+}
+
+static void audit_watch_freeing_mark(struct fsnotify_mark_entry *entry, struct fsnotify_group *group)
+{
+	struct audit_parent *parent;
+
+	parent = container_of(entry, struct audit_parent, mark);
+	/* taken from audit_handle_ievent & FS_IGNORED please figure out what I match... */
+	audit_put_parent(parent);
 }
 
-static const struct inotify_operations audit_inotify_ops = {
-	.handle_event   = audit_handle_ievent,
-	.destroy_watch  = audit_destroy_watch,
+static const struct fsnotify_ops audit_watch_fsnotify_ops = {
+	.should_send_event = 	audit_watch_should_send_event,
+	.handle_event = 	audit_watch_handle_event,
+	.free_group_priv = 	NULL,
+	.freeing_mark = 	audit_watch_freeing_mark,
+	.free_event_priv = 	NULL,
 };
 
 static int __init audit_watch_init(void)
 {
 	audit_watch_cache = KMEM_CACHE(audit_watch, SLAB_PANIC);
 	audit_parent_cache = KMEM_CACHE(audit_parent, SLAB_PANIC);
-	audit_ih = inotify_init(&audit_inotify_ops);
-	if (IS_ERR(audit_ih))
-		audit_panic("cannot initialize inotify handle");
+
+	audit_watch_group = fsnotify_obtain_group(AUDIT_WATCH_GROUP_NUM, AUDIT_FS_WATCH,
+						  &audit_watch_fsnotify_ops);
+	if (IS_ERR(audit_watch_group)) {
+		audit_watch_group = NULL;
+		audit_panic("cannot create audit fsnotify group");
+	}
 	return 0;
 }
 subsys_initcall(audit_watch_init);

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 2/7] audit: redo audit watch locking and refcnt in light of fsnotify
  2009-06-12 20:31 [PATCH 1/7] audit: convert audit watches to use fsnotify instead of inotify Eric Paris
@ 2009-06-12 20:32 ` Eric Paris
  2009-06-12 20:32 ` [PATCH 3/7] audit: do not get and put just to free a watch Eric Paris
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: Eric Paris @ 2009-06-12 20:32 UTC (permalink / raw)
  To: linux-audit; +Cc: viro

fsnotify can handle mutexes to be held across all fsnotify operations since
it deals strickly in spinlocks.  This can simplify and reduce some of the
audit_filter_mutex taking and dropping.

Signed-off-by: Eric Paris <eparis@redhat.com>
---

 kernel/audit_watch.c |   45 +++++----------------------------------------
 1 files changed, 5 insertions(+), 40 deletions(-)

diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index 8d7f264..bd8df58 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -57,7 +57,6 @@ struct audit_parent {
 	struct list_head	ilist;	/* tmp list used to free parents */
 	struct list_head	watches; /* anchor for audit_watch->wlist */
 	struct fsnotify_mark_entry mark; /* fsnotify mark on the inode */
-	unsigned		flags;	/* status flags */
 };
 
 static struct kmem_cache *audit_watch_cache __read_mostly;
@@ -66,17 +65,6 @@ static struct kmem_cache *audit_parent_cache __read_mostly;
 /* fsnotify handle. */
 struct fsnotify_group *audit_watch_group;
 
-/*
- * audit_parent status flags:
- *
- * AUDIT_PARENT_INVALID - set anytime rules/watches are auto-removed due to
- * a filesystem event to ensure we're adding audit watches to a valid parent.
- * Technically not needed for FS_DELETE_SELF or FS_UNMOUNT events, as we cannot
- * receive them while we have nameidata, but must be used for FS_MOVE_SELF which
- * we can receive while holding nameidata.
- */
-#define AUDIT_PARENT_INVALID	0x001
-
 /* fsnotify events we care about. */
 #define AUDIT_FS_WATCH (FS_MOVE | FS_CREATE | FS_DELETE | FS_DELETE_SELF |\
 			FS_MOVE_SELF | FS_EVENT_ON_CHILD)
@@ -173,12 +161,9 @@ static struct audit_parent *audit_init_parent(struct path *parent_path)
 		return ERR_PTR(-ENOMEM);
 
 	INIT_LIST_HEAD(&parent->watches);
-	parent->flags = 0;
 
 	fsnotify_init_mark(&parent->mark, audit_watch_free_mark);
 	parent->mark.mask = AUDIT_FS_WATCH;
-	/* grab a ref so fsnotify mark hangs around until we take audit_filter_mutex */
-	audit_get_parent(parent);
 	ret = fsnotify_add_mark(&parent->mark, audit_watch_group, inode);
 	if (ret < 0) {
 		audit_free_parent(parent);
@@ -357,7 +342,6 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
 	struct audit_entry *e;
 
 	mutex_lock(&audit_filter_mutex);
-	parent->flags |= AUDIT_PARENT_INVALID;
 	list_for_each_entry_safe(w, nextw, &parent->watches, wlist) {
 		list_for_each_entry_safe(r, nextr, &w->rules, rlist) {
 			e = container_of(r, struct audit_entry, rule);
@@ -471,35 +455,25 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list)
 		goto error;
 	}
 
+	mutex_lock(&audit_filter_mutex);
+
 	/* update watch filter fields */
 	if (watch_path.dentry) {
 		watch->dev = watch_path.dentry->d_inode->i_sb->s_dev;
 		watch->ino = watch_path.dentry->d_inode->i_ino;
 	}
 
-	/* The audit_filter_mutex must not be held during inotify calls because
-	 * we hold it during inotify event callback processing.  If an existing
-	 * inotify watch is found, inotify_find_watch() grabs a reference before
-	 * returning.
-	 */
+	/* either find an old parent or attach a new one */
 	parent = audit_find_parent(parent_path.dentry->d_inode);
 	if (!parent) {
 		parent = audit_init_parent(&parent_path);
 		if (IS_ERR(parent)) {
-			/* caller expects mutex locked */
-			mutex_lock(&audit_filter_mutex);
 			ret = PTR_ERR(parent);
 			goto error;
 		}
 	}
 
-	mutex_lock(&audit_filter_mutex);
-
-	/* parent was moved before we took audit_filter_mutex */
-	if (parent->flags & AUDIT_PARENT_INVALID)
-		ret = -ENOENT;
-	else
-		audit_add_to_parent(krule, parent);
+	audit_add_to_parent(krule, parent);
 
 	/* match get in audit_find_parent or audit_init_parent */
 	audit_put_parent(parent);
@@ -597,20 +571,11 @@ static int audit_watch_handle_event(struct fsnotify_group *group, struct fsnotif
 	return 0;
 }
 
-static void audit_watch_freeing_mark(struct fsnotify_mark_entry *entry, struct fsnotify_group *group)
-{
-	struct audit_parent *parent;
-
-	parent = container_of(entry, struct audit_parent, mark);
-	/* taken from audit_handle_ievent & FS_IGNORED please figure out what I match... */
-	audit_put_parent(parent);
-}
-
 static const struct fsnotify_ops audit_watch_fsnotify_ops = {
 	.should_send_event = 	audit_watch_should_send_event,
 	.handle_event = 	audit_watch_handle_event,
 	.free_group_priv = 	NULL,
-	.freeing_mark = 	audit_watch_freeing_mark,
+	.freeing_mark = 	NULL,
 	.free_event_priv = 	NULL,
 };
 

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 3/7] audit: do not get and put just to free a watch
  2009-06-12 20:31 [PATCH 1/7] audit: convert audit watches to use fsnotify instead of inotify Eric Paris
  2009-06-12 20:32 ` [PATCH 2/7] audit: redo audit watch locking and refcnt in light of fsnotify Eric Paris
@ 2009-06-12 20:32 ` Eric Paris
  2009-06-12 20:32 ` [PATCH 4/7] fsnotify: duplicate fsnotify_mark_entry data between 2 marks Eric Paris
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: Eric Paris @ 2009-06-12 20:32 UTC (permalink / raw)
  To: linux-audit; +Cc: viro

deleting audit watch rules is not currently done under audit_filter_mutex.
It was done this way because we could not hold the mutex during inotify
manipulation.  Since we are using fsnotify we don't need to do the extra
get/put pair nor do we need the private list on which to store the parents
while they are about to be freed.

Signed-off-by: Eric Paris <eparis@redhat.com>
---

 kernel/audit.h       |    3 +--
 kernel/audit_watch.c |   27 +++------------------------
 kernel/auditfilter.c |    6 +-----
 3 files changed, 5 insertions(+), 31 deletions(-)

diff --git a/kernel/audit.h b/kernel/audit.h
index bf7118d..77a7e51 100644
--- a/kernel/audit.h
+++ b/kernel/audit.h
@@ -108,8 +108,7 @@ extern void audit_put_watch(struct audit_watch *watch);
 extern void audit_get_watch(struct audit_watch *watch);
 extern int audit_to_watch(struct audit_krule *krule, char *path, int len, u32 op);
 extern int audit_add_watch(struct audit_krule *krule, struct list_head **list);
-extern void audit_remove_watch_rule(struct audit_krule *krule, struct list_head *list);
-extern void audit_watch_inotify_unregister(struct list_head *in_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);
 extern struct audit_entry *audit_dupe_rule(struct audit_krule *old);
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index bd8df58..231f2a6 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -54,7 +54,6 @@ struct audit_watch {
 };
 
 struct audit_parent {
-	struct list_head	ilist;	/* tmp list used to free parents */
 	struct list_head	watches; /* anchor for audit_watch->wlist */
 	struct fsnotify_mark_entry mark; /* fsnotify mark on the inode */
 };
@@ -358,20 +357,6 @@ static void audit_remove_parent_watches(struct audit_parent *parent)
 	fsnotify_destroy_mark_by_entry(&parent->mark);
 }
 
-/* Unregister inotify watches for parents on in_list.
- * Generates an FS_IGNORED event. */
-void audit_watch_inotify_unregister(struct list_head *in_list)
-{
-	struct audit_parent *p, *n;
-
-	list_for_each_entry_safe(p, n, in_list, ilist) {
-		list_del(&p->ilist);
-		fsnotify_destroy_mark_by_entry(&p->mark);
-		/* matches the get in audit_remove_watch_rule() */
-		audit_put_parent(p);
-	}
-}
-
 /* Get path information necessary for adding watches. */
 static int audit_get_path(const char *path, struct path *parent_path,
 			  struct path *watch_path)
@@ -486,7 +471,7 @@ error:
 
 }
 
-void audit_remove_watch_rule(struct audit_krule *krule, struct list_head *list)
+void audit_remove_watch_rule(struct audit_krule *krule)
 {
 	struct audit_watch *watch = krule->watch;
 	struct audit_parent *parent = watch->parent;
@@ -497,15 +482,9 @@ void audit_remove_watch_rule(struct audit_krule *krule, struct list_head *list)
 		audit_remove_watch(watch);
 
 		if (list_empty(&parent->watches)) {
-			/* Put parent on the un-registration list.
-			 * Grab a reference before releasing
-			 * audit_filter_mutex, to be released in
-			 * audit_watch_inotify_unregister().
-			 * If filesystem is going away, just leave
-			 * the sucker alone, eviction will take
-			 * care of it. */
 			audit_get_parent(parent);
-			list_add(&parent->ilist, list);
+			fsnotify_destroy_mark_by_entry(&parent->mark);
+			audit_put_parent(parent);
 		}
 	}
 }
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index f4dd2fc..f5e4cae 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -944,7 +944,6 @@ static inline int audit_del_rule(struct audit_entry *entry)
 	struct audit_watch *watch = entry->rule.watch;
 	struct audit_tree *tree = entry->rule.tree;
 	struct list_head *list;
-	LIST_HEAD(inotify_unregister_list);
 	int ret = 0;
 #ifdef CONFIG_AUDITSYSCALL
 	int dont_count = 0;
@@ -964,7 +963,7 @@ static inline int audit_del_rule(struct audit_entry *entry)
 	}
 
 	if (e->rule.watch)
-		audit_remove_watch_rule(&e->rule, &inotify_unregister_list);
+		audit_remove_watch_rule(&e->rule);
 
 	if (e->rule.tree)
 		audit_remove_tree_rule(&e->rule);
@@ -982,9 +981,6 @@ static inline int audit_del_rule(struct audit_entry *entry)
 #endif
 	mutex_unlock(&audit_filter_mutex);
 
-	if (!list_empty(&inotify_unregister_list))
-		audit_watch_inotify_unregister(&inotify_unregister_list);
-
 out:
 	if (watch)
 		audit_put_watch(watch); /* match initial get */

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 4/7] fsnotify: duplicate fsnotify_mark_entry data between 2 marks
  2009-06-12 20:31 [PATCH 1/7] audit: convert audit watches to use fsnotify instead of inotify Eric Paris
  2009-06-12 20:32 ` [PATCH 2/7] audit: redo audit watch locking and refcnt in light of fsnotify Eric Paris
  2009-06-12 20:32 ` [PATCH 3/7] audit: do not get and put just to free a watch Eric Paris
@ 2009-06-12 20:32 ` Eric Paris
  2009-06-12 20:32 ` [PATCH 5/7] fsnotify: allow addition of duplicate fsnotify marks Eric Paris
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: Eric Paris @ 2009-06-12 20:32 UTC (permalink / raw)
  To: linux-audit; +Cc: viro

Simple copy fsnotify information from one mark to another in preparation
for the second mark to replace the first.

Signed-off-by: Eric Paris <eparis@redhat.com>
---

 fs/notify/inode_mark.c           |   10 +++++++++-
 include/linux/fsnotify_backend.h |    2 ++
 2 files changed, 11 insertions(+), 1 deletions(-)

diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c
index c8a07c6..f560ad5 100644
--- a/fs/notify/inode_mark.c
+++ b/fs/notify/inode_mark.c
@@ -283,12 +283,20 @@ struct fsnotify_mark_entry *fsnotify_find_mark_entry(struct fsnotify_group *grou
 	return NULL;
 }
 
+void fsnotify_duplicate_mark(struct fsnotify_mark_entry *new, struct fsnotify_mark_entry *old)
+{
+	assert_spin_locked(&old->lock);
+	new->inode = old->inode;
+	new->group = old->group;
+	new->mask = old->mask;
+	new->free_mark = old->free_mark;
+}
+
 /*
  * Nothing fancy, just initialize lists and locks and counters.
  */
 void fsnotify_init_mark(struct fsnotify_mark_entry *entry,
 			void (*free_mark)(struct fsnotify_mark_entry *entry))
-
 {
 	spin_lock_init(&entry->lock);
 	atomic_set(&entry->refcnt, 1);
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 90e32cc..4c187c6 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -342,6 +342,8 @@ extern void fsnotify_recalc_inode_mask(struct inode *inode);
 extern void fsnotify_init_mark(struct fsnotify_mark_entry *entry, void (*free_mark)(struct fsnotify_mark_entry *entry));
 /* find (and take a reference) to a mark associated with group and inode */
 extern struct fsnotify_mark_entry *fsnotify_find_mark_entry(struct fsnotify_group *group, struct inode *inode);
+/* copy the values from old into new */
+extern void fsnotify_duplicate_mark(struct fsnotify_mark_entry *new, struct fsnotify_mark_entry *old);
 /* attach the mark to both the group and the inode */
 extern int fsnotify_add_mark(struct fsnotify_mark_entry *entry, struct fsnotify_group *group, struct inode *inode);
 /* given a mark, flag it to be freed when all references are dropped */

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 5/7] fsnotify: allow addition of duplicate fsnotify marks
  2009-06-12 20:31 [PATCH 1/7] audit: convert audit watches to use fsnotify instead of inotify Eric Paris
                   ` (2 preceding siblings ...)
  2009-06-12 20:32 ` [PATCH 4/7] fsnotify: duplicate fsnotify_mark_entry data between 2 marks Eric Paris
@ 2009-06-12 20:32 ` Eric Paris
  2009-06-12 20:32 ` [PATCH 6/7] audit: reimplement audit_trees using fsnotify rather than inotify Eric Paris
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 11+ messages in thread
From: Eric Paris @ 2009-06-12 20:32 UTC (permalink / raw)
  To: linux-audit; +Cc: viro

This patch allows a task to add a second fsnotify mark to an inode for the
same group.  This mark will be added to the end of the inode's list and
this will never be found by the stand fsnotify_find_mark() function.   This
is useful if a user wants to add a new mark before removing the old one.

Signed-off-by: Eric Paris <eparis@redhat.com>
---

 fs/notify/dnotify/dnotify.c      |    2 +-
 fs/notify/inode_mark.c           |    8 +++++---
 fs/notify/inotify/inotify_user.c |    2 +-
 include/linux/fsnotify_backend.h |    2 +-
 kernel/audit_watch.c             |    2 +-
 5 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/fs/notify/dnotify/dnotify.c b/fs/notify/dnotify/dnotify.c
index 828a889..6b71be9 100644
--- a/fs/notify/dnotify/dnotify.c
+++ b/fs/notify/dnotify/dnotify.c
@@ -361,7 +361,7 @@ int fcntl_dirnotify(int fd, struct file *filp, unsigned long arg)
 		dnentry = container_of(entry, struct dnotify_mark_entry, fsn_entry);
 		spin_lock(&entry->lock);
 	} else {
-		fsnotify_add_mark(new_entry, dnotify_group, inode);
+		fsnotify_add_mark(new_entry, dnotify_group, inode, 0);
 		spin_lock(&new_entry->lock);
 		entry = new_entry;
 		dnentry = new_dnentry;
diff --git a/fs/notify/inode_mark.c b/fs/notify/inode_mark.c
index f560ad5..3f3261b 100644
--- a/fs/notify/inode_mark.c
+++ b/fs/notify/inode_mark.c
@@ -313,9 +313,10 @@ void fsnotify_init_mark(struct fsnotify_mark_entry *entry,
  * event types should be delivered to which group and for which inodes.
  */
 int fsnotify_add_mark(struct fsnotify_mark_entry *entry,
-		      struct fsnotify_group *group, struct inode *inode)
+		      struct fsnotify_group *group, struct inode *inode,
+		      int allow_dups)
 {
-	struct fsnotify_mark_entry *lentry;
+	struct fsnotify_mark_entry *lentry = NULL;
 	int ret = 0;
 
 	inode = igrab(inode);
@@ -335,7 +336,8 @@ int fsnotify_add_mark(struct fsnotify_mark_entry *entry,
 	entry->group = group;
 	entry->inode = inode;
 
-	lentry = fsnotify_find_mark_entry(group, inode);
+	if (!allow_dups)
+		lentry = fsnotify_find_mark_entry(group, inode);
 	if (!lentry) {
 		hlist_add_head(&entry->i_list, &inode->i_fsnotify_mark_entries);
 		list_add(&entry->g_list, &group->mark_entries);
diff --git a/fs/notify/inotify/inotify_user.c b/fs/notify/inotify/inotify_user.c
index 982a412..289a7ce 100644
--- a/fs/notify/inotify/inotify_user.c
+++ b/fs/notify/inotify/inotify_user.c
@@ -467,7 +467,7 @@ find_entry:
 			goto out_err;
 		}
 
-		ret = fsnotify_add_mark(&ientry->fsn_entry, group, inode);
+		ret = fsnotify_add_mark(&ientry->fsn_entry, group, inode, 0);
 		if (ret == -EEXIST)
 			goto find_entry;
 		else if (ret)
diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 4c187c6..2ab2b7d 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -345,7 +345,7 @@ extern struct fsnotify_mark_entry *fsnotify_find_mark_entry(struct fsnotify_grou
 /* copy the values from old into new */
 extern void fsnotify_duplicate_mark(struct fsnotify_mark_entry *new, struct fsnotify_mark_entry *old);
 /* attach the mark to both the group and the inode */
-extern int fsnotify_add_mark(struct fsnotify_mark_entry *entry, struct fsnotify_group *group, struct inode *inode);
+extern int fsnotify_add_mark(struct fsnotify_mark_entry *entry, struct fsnotify_group *group, struct inode *inode, int allow_dups);
 /* given a mark, flag it to be freed when all references are dropped */
 extern void fsnotify_destroy_mark_by_entry(struct fsnotify_mark_entry *entry);
 /* run all the marks in a group, and flag them to be freed */
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index 231f2a6..e56286b 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -163,7 +163,7 @@ static struct audit_parent *audit_init_parent(struct path *parent_path)
 
 	fsnotify_init_mark(&parent->mark, audit_watch_free_mark);
 	parent->mark.mask = AUDIT_FS_WATCH;
-	ret = fsnotify_add_mark(&parent->mark, audit_watch_group, inode);
+	ret = fsnotify_add_mark(&parent->mark, audit_watch_group, inode, 0);
 	if (ret < 0) {
 		audit_free_parent(parent);
 		return ERR_PTR(ret);

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 6/7] audit: reimplement audit_trees using fsnotify rather than inotify
  2009-06-12 20:31 [PATCH 1/7] audit: convert audit watches to use fsnotify instead of inotify Eric Paris
                   ` (3 preceding siblings ...)
  2009-06-12 20:32 ` [PATCH 5/7] fsnotify: allow addition of duplicate fsnotify marks Eric Paris
@ 2009-06-12 20:32 ` Eric Paris
  2009-06-12 20:32 ` [PATCH 7/7] audit: move audit to a subdirectory Eric Paris
  2009-06-16 15:25 ` [PATCH 1/7] audit: convert audit watches to use fsnotify instead of inotify Klaus Heinrich Kiwi
  6 siblings, 0 replies; 11+ messages in thread
From: Eric Paris @ 2009-06-12 20:32 UTC (permalink / raw)
  To: linux-audit; +Cc: viro

Simply switch audit_trees from using inotify to using fsnotify for it's
inode pinning and disappearing act information.

Signed-off-by: Eric Paris <eparis@redhat.com>
---

 include/linux/fsnotify_backend.h |    5 +
 init/Kconfig                     |    2 
 kernel/audit_tree.c              |  223 +++++++++++++++++++++-----------------
 kernel/auditsc.c                 |    4 -
 4 files changed, 130 insertions(+), 104 deletions(-)

diff --git a/include/linux/fsnotify_backend.h b/include/linux/fsnotify_backend.h
index 2ab2b7d..730188c 100644
--- a/include/linux/fsnotify_backend.h
+++ b/include/linux/fsnotify_backend.h
@@ -62,8 +62,9 @@
 
 /* listeners that hard code group numbers near the top */
 #define DNOTIFY_GROUP_NUM	UINT_MAX
-#define AUDIT_WATCH_GROUP_NUM  (DNOTIFY_GROUP_NUM-1)
-#define INOTIFY_GROUP_NUM      (AUDIT_WATCH_GROUP_NUM-1)
+#define AUDIT_WATCH_GROUP_NUM	(DNOTIFY_GROUP_NUM-1)
+#define AUDIT_TREE_GROUP_NUM	(AUDIT_WATCH_GROUP_NUM-1)
+#define INOTIFY_GROUP_NUM	(AUDIT_TREE_GROUP_NUM-1)
 
 struct fsnotify_group;
 struct fsnotify_event;
diff --git a/init/Kconfig b/init/Kconfig
index 9170fc4..371619b 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -303,7 +303,7 @@ config AUDITSYSCALL
 config AUDIT_TREE
 	def_bool y
 	depends on AUDITSYSCALL
-	select INOTIFY
+	select FSNOTIFY
 
 menu "RCU Subsystem"
 
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index 3ff0731..a030513 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -1,5 +1,5 @@
 #include "audit.h"
-#include <linux/inotify.h>
+#include <linux/fsnotify_backend.h>
 #include <linux/namei.h>
 #include <linux/mount.h>
 
@@ -20,7 +20,7 @@ struct audit_tree {
 
 struct audit_chunk {
 	struct list_head hash;
-	struct inotify_watch watch;
+	struct fsnotify_mark_entry mark;
 	struct list_head trees;		/* with root here */
 	int dead;
 	int count;
@@ -66,7 +66,7 @@ static LIST_HEAD(prune_list);
  * that makes a difference.  Some.
  */
 
-static struct inotify_handle *rtree_ih;
+static struct fsnotify_group *audit_tree_group;
 
 static struct audit_tree *alloc_tree(const char *s)
 {
@@ -109,29 +109,6 @@ const char *audit_tree_path(struct audit_tree *tree)
 	return tree->pathname;
 }
 
-static struct audit_chunk *alloc_chunk(int count)
-{
-	struct audit_chunk *chunk;
-	size_t size;
-	int i;
-
-	size = offsetof(struct audit_chunk, owners) + count * sizeof(struct node);
-	chunk = kzalloc(size, GFP_KERNEL);
-	if (!chunk)
-		return NULL;
-
-	INIT_LIST_HEAD(&chunk->hash);
-	INIT_LIST_HEAD(&chunk->trees);
-	chunk->count = count;
-	atomic_long_set(&chunk->refs, 1);
-	for (i = 0; i < count; i++) {
-		INIT_LIST_HEAD(&chunk->owners[i].list);
-		chunk->owners[i].index = i;
-	}
-	inotify_init_watch(&chunk->watch);
-	return chunk;
-}
-
 static void free_chunk(struct audit_chunk *chunk)
 {
 	int i;
@@ -155,6 +132,35 @@ static void __put_chunk(struct rcu_head *rcu)
 	audit_put_chunk(chunk);
 }
 
+static void audit_tree_destroy_watch(struct fsnotify_mark_entry *entry)
+{
+	struct audit_chunk *chunk = container_of(entry, struct audit_chunk, mark);
+	call_rcu(&chunk->head, __put_chunk);
+}
+
+static struct audit_chunk *alloc_chunk(int count)
+{
+	struct audit_chunk *chunk;
+	size_t size;
+	int i;
+
+	size = offsetof(struct audit_chunk, owners) + count * sizeof(struct node);
+	chunk = kzalloc(size, GFP_KERNEL);
+	if (!chunk)
+		return NULL;
+
+	INIT_LIST_HEAD(&chunk->hash);
+	INIT_LIST_HEAD(&chunk->trees);
+	chunk->count = count;
+	atomic_long_set(&chunk->refs, 1);
+	for (i = 0; i < count; i++) {
+		INIT_LIST_HEAD(&chunk->owners[i].list);
+		chunk->owners[i].index = i;
+	}
+	fsnotify_init_mark(&chunk->mark, audit_tree_destroy_watch);
+	return chunk;
+}
+
 enum {HASH_SIZE = 128};
 static struct list_head chunk_hash_heads[HASH_SIZE];
 static __cacheline_aligned_in_smp DEFINE_SPINLOCK(hash_lock);
@@ -165,10 +171,15 @@ static inline struct list_head *chunk_hash(const struct inode *inode)
 	return chunk_hash_heads + n % HASH_SIZE;
 }
 
-/* hash_lock is held by caller */
+/* hash_lock & entry->lock is held by caller */
 static void insert_hash(struct audit_chunk *chunk)
 {
-	struct list_head *list = chunk_hash(chunk->watch.inode);
+	struct fsnotify_mark_entry *entry = &chunk->mark;
+	struct list_head *list;
+
+	if (!entry->inode)
+		return;
+	list = chunk_hash(entry->inode);
 	list_add_rcu(&chunk->hash, list);
 }
 
@@ -179,7 +190,8 @@ struct audit_chunk *audit_tree_lookup(const struct inode *inode)
 	struct audit_chunk *p;
 
 	list_for_each_entry_rcu(p, list, hash) {
-		if (p->watch.inode == inode) {
+		/* mark.inode may have gone NULL, but who cares? */
+		if (p->mark.inode == inode) {
 			atomic_long_inc(&p->refs);
 			return p;
 		}
@@ -208,38 +220,19 @@ static struct audit_chunk *find_chunk(struct node *p)
 static void untag_chunk(struct node *p)
 {
 	struct audit_chunk *chunk = find_chunk(p);
+	struct fsnotify_mark_entry *entry = &chunk->mark;
 	struct audit_chunk *new;
 	struct audit_tree *owner;
 	int size = chunk->count - 1;
 	int i, j;
 
-	if (!pin_inotify_watch(&chunk->watch)) {
-		/*
-		 * Filesystem is shutting down; all watches are getting
-		 * evicted, just take it off the node list for this
-		 * tree and let the eviction logics take care of the
-		 * rest.
-		 */
-		owner = p->owner;
-		if (owner->root == chunk) {
-			list_del_init(&owner->same_root);
-			owner->root = NULL;
-		}
-		list_del_init(&p->list);
-		p->owner = NULL;
-		put_tree(owner);
-		return;
-	}
+	fsnotify_get_mark(entry);
 
 	spin_unlock(&hash_lock);
 
-	/*
-	 * pin_inotify_watch() succeeded, so the watch won't go away
-	 * from under us.
-	 */
-	mutex_lock(&chunk->watch.inode->inotify_mutex);
-	if (chunk->dead) {
-		mutex_unlock(&chunk->watch.inode->inotify_mutex);
+	spin_lock(&entry->lock);
+	if (chunk->dead || !entry->inode) {
+		spin_unlock(&entry->lock);
 		goto out;
 	}
 
@@ -254,16 +247,17 @@ static void untag_chunk(struct node *p)
 		list_del_init(&p->list);
 		list_del_rcu(&chunk->hash);
 		spin_unlock(&hash_lock);
-		inotify_evict_watch(&chunk->watch);
-		mutex_unlock(&chunk->watch.inode->inotify_mutex);
-		put_inotify_watch(&chunk->watch);
+		spin_unlock(&entry->lock);
+		fsnotify_destroy_mark_by_entry(entry);
+		fsnotify_put_mark(entry);
 		goto out;
 	}
 
 	new = alloc_chunk(size);
 	if (!new)
 		goto Fallback;
-	if (inotify_clone_watch(&chunk->watch, &new->watch) < 0) {
+	fsnotify_duplicate_mark(&new->mark, entry);
+	if (fsnotify_add_mark(&new->mark, new->mark.group, new->mark.inode, 1)) {
 		free_chunk(new);
 		goto Fallback;
 	}
@@ -296,9 +290,9 @@ static void untag_chunk(struct node *p)
 	list_for_each_entry(owner, &new->trees, same_root)
 		owner->root = new;
 	spin_unlock(&hash_lock);
-	inotify_evict_watch(&chunk->watch);
-	mutex_unlock(&chunk->watch.inode->inotify_mutex);
-	put_inotify_watch(&chunk->watch);
+	spin_unlock(&entry->lock);
+	fsnotify_destroy_mark_by_entry(entry);
+	fsnotify_put_mark(entry);
 	goto out;
 
 Fallback:
@@ -312,31 +306,33 @@ Fallback:
 	p->owner = NULL;
 	put_tree(owner);
 	spin_unlock(&hash_lock);
-	mutex_unlock(&chunk->watch.inode->inotify_mutex);
+	spin_unlock(&entry->lock);
 out:
-	unpin_inotify_watch(&chunk->watch);
+	fsnotify_put_mark(entry);
 	spin_lock(&hash_lock);
 }
 
 static int create_chunk(struct inode *inode, struct audit_tree *tree)
 {
+	struct fsnotify_mark_entry *entry;
 	struct audit_chunk *chunk = alloc_chunk(1);
 	if (!chunk)
 		return -ENOMEM;
 
-	if (inotify_add_watch(rtree_ih, &chunk->watch, inode, IN_IGNORED | IN_DELETE_SELF) < 0) {
+	entry = &chunk->mark;
+	if (fsnotify_add_mark(entry, audit_tree_group, inode, 0)) {
 		free_chunk(chunk);
 		return -ENOSPC;
 	}
 
-	mutex_lock(&inode->inotify_mutex);
+	spin_lock(&entry->lock);
 	spin_lock(&hash_lock);
 	if (tree->goner) {
 		spin_unlock(&hash_lock);
 		chunk->dead = 1;
-		inotify_evict_watch(&chunk->watch);
-		mutex_unlock(&inode->inotify_mutex);
-		put_inotify_watch(&chunk->watch);
+		spin_unlock(&entry->lock);
+		fsnotify_destroy_mark_by_entry(entry);
+		fsnotify_put_mark(entry);
 		return 0;
 	}
 	chunk->owners[0].index = (1U << 31);
@@ -349,30 +345,33 @@ static int create_chunk(struct inode *inode, struct audit_tree *tree)
 	}
 	insert_hash(chunk);
 	spin_unlock(&hash_lock);
-	mutex_unlock(&inode->inotify_mutex);
+	spin_unlock(&entry->lock);
 	return 0;
 }
 
 /* the first tagged inode becomes root of tree */
 static int tag_chunk(struct inode *inode, struct audit_tree *tree)
 {
-	struct inotify_watch *watch;
+	struct fsnotify_mark_entry *old_entry, *chunk_entry;
 	struct audit_tree *owner;
 	struct audit_chunk *chunk, *old;
 	struct node *p;
 	int n;
 
-	if (inotify_find_watch(rtree_ih, inode, &watch) < 0)
+	spin_lock(&inode->i_lock);
+	old_entry = fsnotify_find_mark_entry(audit_tree_group, inode);
+	spin_unlock(&inode->i_lock);
+	if (!old_entry)
 		return create_chunk(inode, tree);
 
-	old = container_of(watch, struct audit_chunk, watch);
+	old = container_of(old_entry, struct audit_chunk, mark);
 
 	/* are we already there? */
 	spin_lock(&hash_lock);
 	for (n = 0; n < old->count; n++) {
 		if (old->owners[n].owner == tree) {
 			spin_unlock(&hash_lock);
-			put_inotify_watch(watch);
+			fsnotify_put_mark(old_entry);
 			return 0;
 		}
 	}
@@ -381,22 +380,40 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
 	chunk = alloc_chunk(old->count + 1);
 	if (!chunk)
 		return -ENOMEM;
+	chunk_entry = &chunk->mark;
 
-	mutex_lock(&inode->inotify_mutex);
-	if (inotify_clone_watch(&old->watch, &chunk->watch) < 0) {
-		mutex_unlock(&inode->inotify_mutex);
-		put_inotify_watch(&old->watch);
+	spin_lock(&old_entry->lock);
+	if (!old_entry->inode) {
+		/* old_entry is being shot, lets just lie */
+		spin_unlock(&old_entry->lock);
+		fsnotify_put_mark(old_entry);
 		free_chunk(chunk);
+		return -ENOENT;
+	}
+
+	fsnotify_duplicate_mark(chunk_entry, old_entry);
+	if (fsnotify_add_mark(chunk_entry, chunk_entry->group, chunk_entry->inode, 1)) {
+		spin_unlock(&old_entry->lock);
+		free_chunk(chunk);
+		fsnotify_put_mark(old_entry);
 		return -ENOSPC;
 	}
+
+	/* even though we hold old_entry->lock, this is safe since chunk_entry->lock could NEVER have been grabbed before */
+	spin_lock(&chunk_entry->lock);
 	spin_lock(&hash_lock);
+
+	/* we now hold old_entry->lock, chunk_entry->lock, and hash_lock */
 	if (tree->goner) {
 		spin_unlock(&hash_lock);
 		chunk->dead = 1;
-		inotify_evict_watch(&chunk->watch);
-		mutex_unlock(&inode->inotify_mutex);
-		put_inotify_watch(&old->watch);
-		put_inotify_watch(&chunk->watch);
+		spin_unlock(&chunk_entry->lock);
+		spin_unlock(&old_entry->lock);
+
+		fsnotify_destroy_mark_by_entry(chunk_entry);
+
+		fsnotify_put_mark(chunk_entry);
+		fsnotify_put_mark(old_entry);
 		return 0;
 	}
 	list_replace_init(&old->trees, &chunk->trees);
@@ -422,9 +439,10 @@ static int tag_chunk(struct inode *inode, struct audit_tree *tree)
 		list_add(&tree->same_root, &chunk->trees);
 	}
 	spin_unlock(&hash_lock);
-	inotify_evict_watch(&old->watch);
-	mutex_unlock(&inode->inotify_mutex);
-	put_inotify_watch(&old->watch);
+	spin_unlock(&chunk_entry->lock);
+	spin_unlock(&old_entry->lock);
+	fsnotify_destroy_mark_by_entry(old_entry);
+	fsnotify_put_mark(old_entry);
 	return 0;
 }
 
@@ -575,7 +593,8 @@ void audit_trim_trees(void)
 		spin_lock(&hash_lock);
 		list_for_each_entry(node, &tree->chunks, list) {
 			struct audit_chunk *chunk = find_chunk(node);
-			struct inode *inode = chunk->watch.inode;
+			/* this could be NULL if the watch is dieing else where... */
+			struct inode *inode = chunk->mark.inode;
 			struct vfsmount *mnt;
 			node->index |= 1U<<31;
 			list_for_each_entry(mnt, &list, mnt_list) {
@@ -879,34 +898,40 @@ static void evict_chunk(struct audit_chunk *chunk)
 	mutex_unlock(&audit_filter_mutex);
 }
 
-static void handle_event(struct inotify_watch *watch, u32 wd, u32 mask,
-                         u32 cookie, const char *dname, struct inode *inode)
+static int audit_tree_handle_event(struct fsnotify_group *group, struct fsnotify_event *event)
 {
-	struct audit_chunk *chunk = container_of(watch, struct audit_chunk, watch);
+	BUG();
+	return -EOPNOTSUPP;
+}
 
-	if (mask & IN_IGNORED) {
-		evict_chunk(chunk);
-		put_inotify_watch(watch);
-	}
+static void audit_tree_freeing_mark(struct fsnotify_mark_entry *entry, struct fsnotify_group *group)
+{
+	struct audit_chunk *chunk = container_of(entry, struct audit_chunk, mark);
+
+	evict_chunk(chunk);
+	fsnotify_put_mark(entry);
 }
 
-static void destroy_watch(struct inotify_watch *watch)
+static bool audit_tree_send_event(struct fsnotify_group *group, struct inode *inode, __u32 mask)
 {
-	struct audit_chunk *chunk = container_of(watch, struct audit_chunk, watch);
-	call_rcu(&chunk->head, __put_chunk);
+	return 0;
 }
 
-static const struct inotify_operations rtree_inotify_ops = {
-	.handle_event	= handle_event,
-	.destroy_watch	= destroy_watch,
+static const struct fsnotify_ops audit_tree_ops = {
+	.handle_event = audit_tree_handle_event,
+	.should_send_event = audit_tree_send_event,
+	.free_group_priv = NULL,
+	.free_event_priv = NULL,
+	.freeing_mark = audit_tree_freeing_mark,
 };
 
 static int __init audit_tree_init(void)
 {
 	int i;
 
-	rtree_ih = inotify_init(&rtree_inotify_ops);
-	if (IS_ERR(rtree_ih))
+	audit_tree_group = fsnotify_obtain_group(AUDIT_TREE_GROUP_NUM,
+						 0, &audit_tree_ops);
+	if (IS_ERR(audit_tree_group))
 		audit_panic("cannot initialize inotify handle for rectree watches");
 
 	for (i = 0; i < HASH_SIZE; i++)
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 2d08728..af95d93 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1718,7 +1718,7 @@ static inline void handle_one(const struct inode *inode)
 	struct audit_tree_refs *p;
 	struct audit_chunk *chunk;
 	int count;
-	if (likely(list_empty(&inode->inotify_watches)))
+	if (likely(hlist_empty(&inode->i_fsnotify_mark_entries)))
 		return;
 	context = current->audit_context;
 	p = context->trees;
@@ -1761,7 +1761,7 @@ retry:
 	seq = read_seqbegin(&rename_lock);
 	for(;;) {
 		struct inode *inode = d->d_inode;
-		if (inode && unlikely(!list_empty(&inode->inotify_watches))) {
+		if (inode && unlikely(!hlist_empty(&inode->i_fsnotify_mark_entries))) {
 			struct audit_chunk *chunk;
 			chunk = audit_tree_lookup(inode);
 			if (chunk) {

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* [PATCH 7/7] audit: move audit to a subdirectory
  2009-06-12 20:31 [PATCH 1/7] audit: convert audit watches to use fsnotify instead of inotify Eric Paris
                   ` (4 preceding siblings ...)
  2009-06-12 20:32 ` [PATCH 6/7] audit: reimplement audit_trees using fsnotify rather than inotify Eric Paris
@ 2009-06-12 20:32 ` Eric Paris
  2009-06-16 15:25 ` [PATCH 1/7] audit: convert audit watches to use fsnotify instead of inotify Klaus Heinrich Kiwi
  6 siblings, 0 replies; 11+ messages in thread
From: Eric Paris @ 2009-06-12 20:32 UTC (permalink / raw)
  To: linux-audit; +Cc: viro

The audit subsystem currently has 5 files in kernel/ and soon to be 6.
Simply move them into an easily organized subdir for cleanup and move the
audit Kconfig from init/Kconfig into kernel/audit/Kconfig to make it easier to
maintain.

Signed-off-by: Eric Paris <eparis@redhat.com>
---

 MAINTAINERS                |    2 
 init/Kconfig               |   24 
 kernel/Makefile            |    4 
 kernel/audit.c             | 1521 ---------------------------
 kernel/audit.h             |  158 ---
 kernel/audit/Kconfig       |   23 
 kernel/audit/Makefile      |    7 
 kernel/audit/audit.c       | 1521 +++++++++++++++++++++++++++
 kernel/audit/audit.h       |  158 +++
 kernel/audit/audit_tree.c  |  942 ++++++++++++++++
 kernel/audit/audit_watch.c |  574 ++++++++++
 kernel/audit/auditfilter.c | 1366 ++++++++++++++++++++++++
 kernel/audit/auditsc.c     | 2522 ++++++++++++++++++++++++++++++++++++++++++++
 kernel/audit_tree.c        |  942 ----------------
 kernel/audit_watch.c       |  574 ----------
 kernel/auditfilter.c       | 1366 ------------------------
 kernel/auditsc.c           | 2522 --------------------------------------------
 kernel/signal.c            |    2 
 18 files changed, 7117 insertions(+), 7111 deletions(-)
 delete mode 100644 kernel/audit.c
 delete mode 100644 kernel/audit.h
 create mode 100644 kernel/audit/Kconfig
 create mode 100644 kernel/audit/Makefile
 create mode 100644 kernel/audit/audit.c
 create mode 100644 kernel/audit/audit.h
 create mode 100644 kernel/audit/audit_tree.c
 create mode 100644 kernel/audit/audit_watch.c
 create mode 100644 kernel/audit/auditfilter.c
 create mode 100644 kernel/audit/auditsc.c
 delete mode 100644 kernel/audit_tree.c
 delete mode 100644 kernel/audit_watch.c
 delete mode 100644 kernel/auditfilter.c
 delete mode 100644 kernel/auditsc.c

diff --git a/MAINTAINERS b/MAINTAINERS
index e8b08f2..5184232 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1058,7 +1058,7 @@ W:	http://people.redhat.com/sgrubb/audit/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/viro/audit-current.git
 S:	Maintained
 F:	include/linux/audit.h
-F:	kernel/audit*
+F:	kernel/audit/
 
 AUXILIARY DISPLAY DRIVERS
 P:	Miguel Ojeda Sandonis
diff --git a/init/Kconfig b/init/Kconfig
index 371619b..eae9df5 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -281,29 +281,7 @@ config TASK_IO_ACCOUNTING
 
 	  Say N if unsure.
 
-config AUDIT
-	bool "Auditing support"
-	depends on NET
-	help
-	  Enable auditing infrastructure that can be used with another
-	  kernel subsystem, such as SELinux (which requires this for
-	  logging of avc messages output).  Does not do system-call
-	  auditing without CONFIG_AUDITSYSCALL.
-
-config AUDITSYSCALL
-	bool "Enable system-call auditing support"
-	depends on AUDIT && (X86 || PPC || PPC64 || S390 || IA64 || UML || SPARC64|| SUPERH)
-	default y if SECURITY_SELINUX
-	help
-	  Enable low-overhead system-call auditing infrastructure that
-	  can be used independently or with another kernel subsystem,
-	  such as SELinux.  To use audit's filesystem watch feature, please
-	  ensure that INOTIFY is configured.
-
-config AUDIT_TREE
-	def_bool y
-	depends on AUDITSYSCALL
-	select FSNOTIFY
+source "kernel/audit/Kconfig"
 
 menu "RCU Subsystem"
 
diff --git a/kernel/Makefile b/kernel/Makefile
index e5122f5..3ef28c0 100644
--- a/kernel/Makefile
+++ b/kernel/Makefile
@@ -68,9 +68,7 @@ obj-$(CONFIG_IKCONFIG) += configs.o
 obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o
 obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
 obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o
-obj-$(CONFIG_AUDIT) += audit.o auditfilter.o
-obj-$(CONFIG_AUDITSYSCALL) += auditsc.o audit_watch.o
-obj-$(CONFIG_AUDIT_TREE) += audit_tree.o
+obj-y += audit/
 obj-$(CONFIG_KPROBES) += kprobes.o
 obj-$(CONFIG_KGDB) += kgdb.o
 obj-$(CONFIG_DETECT_SOFTLOCKUP) += softlockup.o
diff --git a/kernel/audit/Kconfig b/kernel/audit/Kconfig
new file mode 100644
index 0000000..4f2d357
--- /dev/null
+++ b/kernel/audit/Kconfig
@@ -0,0 +1,23 @@
+config AUDIT
+	bool "Auditing support"
+	depends on NET
+	help
+	  Enable auditing infrastructure that can be used with another
+	  kernel subsystem, such as SELinux (which requires this for
+	  logging of avc messages output).  Does not do system-call
+	  auditing without CONFIG_AUDITSYSCALL.
+
+config AUDITSYSCALL
+	bool "Enable system-call auditing support"
+	depends on AUDIT && (X86 || PPC || PPC64 || S390 || IA64 || UML || SPARC64|| SUPERH)
+	default y if SECURITY_SELINUX
+	help
+	  Enable low-overhead system-call auditing infrastructure that
+	  can be used independently or with another kernel subsystem,
+	  such as SELinux.  To use audit's filesystem watch feature, please
+	  ensure that FSNOTIFY is configured.
+
+config AUDIT_TREE
+	def_bool y
+	depends on AUDITSYSCALL
+	select FSNOTIFY
diff --git a/kernel/audit/Makefile b/kernel/audit/Makefile
new file mode 100644
index 0000000..7752c2c
--- /dev/null
+++ b/kernel/audit/Makefile
@@ -0,0 +1,7 @@
+#
+# Makefile for audit
+#
+
+obj-$(CONFIG_AUDIT) += audit.o auditfilter.o
+obj-$(CONFIG_AUDITSYSCALL) += auditsc.o audit_watch.o
+obj-$(CONFIG_AUDIT_TREE) += audit_tree.o
diff --git a/kernel/audit.c b/kernel/audit/audit.c
similarity index 100%
rename from kernel/audit.c
rename to kernel/audit/audit.c
diff --git a/kernel/audit.h b/kernel/audit/audit.h
similarity index 100%
rename from kernel/audit.h
rename to kernel/audit/audit.h
diff --git a/kernel/audit_tree.c b/kernel/audit/audit_tree.c
similarity index 100%
rename from kernel/audit_tree.c
rename to kernel/audit/audit_tree.c
diff --git a/kernel/audit_watch.c b/kernel/audit/audit_watch.c
similarity index 100%
rename from kernel/audit_watch.c
rename to kernel/audit/audit_watch.c
diff --git a/kernel/auditfilter.c b/kernel/audit/auditfilter.c
similarity index 100%
rename from kernel/auditfilter.c
rename to kernel/audit/auditfilter.c
diff --git a/kernel/auditsc.c b/kernel/audit/auditsc.c
similarity index 100%
rename from kernel/auditsc.c
rename to kernel/audit/auditsc.c
diff --git a/kernel/signal.c b/kernel/signal.c
index d81f495..dd4c3e7 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -33,7 +33,7 @@
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
 #include <asm/siginfo.h>
-#include "audit.h"	/* audit_signal_info() */
+#include "audit/audit.h"	/* audit_signal_info() */
 
 /*
  * SLAB caches for signal bits.

^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/7] audit: convert audit watches to use fsnotify instead of inotify
  2009-06-12 20:31 [PATCH 1/7] audit: convert audit watches to use fsnotify instead of inotify Eric Paris
                   ` (5 preceding siblings ...)
  2009-06-12 20:32 ` [PATCH 7/7] audit: move audit to a subdirectory Eric Paris
@ 2009-06-16 15:25 ` Klaus Heinrich Kiwi
  2009-06-16 15:43   ` Eric Paris
  6 siblings, 1 reply; 11+ messages in thread
From: Klaus Heinrich Kiwi @ 2009-06-16 15:25 UTC (permalink / raw)
  To: Eric Paris; +Cc: linux-audit

On Fri, 2009-06-12 at 16:31 -0400, Eric Paris wrote:
> Audit currently uses inotify to pin inodes in core and to detect when
> watched inodes are deleted or unmounted.  This patch uses fsnotify instead
> of inotify.
>     
> Signed-off-by: Eric Paris <eparis@redhat.com>

Sorry for being lazy and not googling around, but what changes between
inotify and fsnotify, specially in terms of filesystem auditing? Is
there any performance/features/usability changes?

Thanks,

 -Klaus

-- 
Klaus Heinrich Kiwi <klausk@linux.vnet.ibm.com>
Linux Security Development, IBM Linux Technology Center

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/7] audit: convert audit watches to use fsnotify instead of inotify
  2009-06-16 15:25 ` [PATCH 1/7] audit: convert audit watches to use fsnotify instead of inotify Klaus Heinrich Kiwi
@ 2009-06-16 15:43   ` Eric Paris
  2009-06-16 16:09     ` Klaus Heinrich Kiwi
  0 siblings, 1 reply; 11+ messages in thread
From: Eric Paris @ 2009-06-16 15:43 UTC (permalink / raw)
  To: Klaus Heinrich Kiwi; +Cc: linux-audit

On Tue, 2009-06-16 at 12:25 -0300, Klaus Heinrich Kiwi wrote:
> On Fri, 2009-06-12 at 16:31 -0400, Eric Paris wrote:
> > Audit currently uses inotify to pin inodes in core and to detect when
> > watched inodes are deleted or unmounted.  This patch uses fsnotify instead
> > of inotify.
> >     
> > Signed-off-by: Eric Paris <eparis@redhat.com>
> 
> Sorry for being lazy and not googling around, but what changes between
> inotify and fsnotify, specially in terms of filesystem auditing? Is
> there any performance/features/usability changes?

Basically, none.  fsnotify is a new infrastructure on which inotify and
dnotify have been implemented.  It is generic, much like the inotify.c
(as opposed to inotify_user.c) was supposed to be.  But fsnotify is more
generic and better thought out.

The main drivers for fsnotify are:
1. smaller struct inode
2. equal performance (actually slightly better since we don't have to
run inotify and dnotify every time)
3. significantly better locking and object lifetime (see how much more
simple the audit watch locking gets with fsnotify in the next couple
patches?)

Note that audit watches don't use inotify to do any of the actual
auditing.  They just use inotify to discover the watched files were
created or removed.  So we weren't using much of the inotify feature
set.

So this patch does little but get me one step closing to kicking
inotify.c out of the kernel

-Eric

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/7] audit: convert audit watches to use fsnotify instead of inotify
  2009-06-16 15:43   ` Eric Paris
@ 2009-06-16 16:09     ` Klaus Heinrich Kiwi
  2009-06-19 21:03       ` Eric Paris
  0 siblings, 1 reply; 11+ messages in thread
From: Klaus Heinrich Kiwi @ 2009-06-16 16:09 UTC (permalink / raw)
  To: Eric Paris; +Cc: linux-audit

On Tue, 2009-06-16 at 11:43 -0400, Eric Paris wrote:
> Note that audit watches don't use inotify to do any of the actual
> auditing.  They just use inotify to discover the watched files were
> created or removed.  So we weren't using much of the inotify feature
> set.

Eric, 

 thanks for the thorough explanation.

It's been a while since I last looked, but the file watches are being
audited at the syscall level, right? So inotify/fsnotify is used to
associate a filename to an inode when the file is created, or to
deassociate when it is removed. Is the rename/mv also covered by those
or differently? I remember that moving a file around doesn't invalidate
it's rule (the file's inode is still the same), but auditctl -l doesn't
follow the name around, for example.

But that's also probably the right thing to do in that case, I'm not
sure.

 -Klaus
-- 
Klaus Heinrich Kiwi <klausk@linux.vnet.ibm.com>
Linux Security Development, IBM Linux Technology Center

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: [PATCH 1/7] audit: convert audit watches to use fsnotify instead of inotify
  2009-06-16 16:09     ` Klaus Heinrich Kiwi
@ 2009-06-19 21:03       ` Eric Paris
  0 siblings, 0 replies; 11+ messages in thread
From: Eric Paris @ 2009-06-19 21:03 UTC (permalink / raw)
  To: Klaus Heinrich Kiwi; +Cc: linux-audit

On Tue, 2009-06-16 at 13:09 -0300, Klaus Heinrich Kiwi wrote:
> On Tue, 2009-06-16 at 11:43 -0400, Eric Paris wrote:
> > Note that audit watches don't use inotify to do any of the actual
> > auditing.  They just use inotify to discover the watched files were
> > created or removed.  So we weren't using much of the inotify feature
> > set.
> 
> Eric, 
> 
>  thanks for the thorough explanation.
> 
> It's been a while since I last looked, but the file watches are being
> audited at the syscall level, right? So inotify/fsnotify is used to
> associate a filename to an inode when the file is created, or to
> deassociate when it is removed. Is the rename/mv also covered by those
> or differently? I remember that moving a file around doesn't invalidate
> it's rule (the file's inode is still the same), but auditctl -l doesn't
> follow the name around, for example.
> 
> But that's also probably the right thing to do in that case, I'm not
> sure.

So fsnotify and inotify are the same in these regards.  Basically a
watch is really on a "directory inode + a name"  it's easiest to explain
what goes on in examples.

-F path=/tmp/dir1/file1 so the inotify/fsnotify watch is attached to
the /tmp/dir1 inode.  We also maintain that what we care about is
"file1"

If you mv /tmp/dir1 to /tmp/dir2 the rule is deleted from the system
(and an audit config change record is written in the logs)

If instead you create /tmp/dir1/file1 we get a notification, update the
lists with the new inode number for /tmp/dir1/file1 and at syscall exit
will output a record if the /tmp/dir1/file1 was accessed.

If you delete /tmp/dir1/file1 or move it to /tmp/dir1/file2 we will
update the lists with the fact that there is no inode
for /tmp/dir1/file1 and so when a syscall exits it will not obviously
not find that it needs to output a record.

So we handle add/remove/mv of the actual file of a watch as would be
expected.  If the file this syscall accessed was called [blah] at
syscall exit we will emit a watch.  If the file wasn't called [blah] we
won't.  The only thing interested is removing or moving the parent
directory, which actually removes the whole rule never to return.

-Eric

^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2009-06-19 21:03 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-06-12 20:31 [PATCH 1/7] audit: convert audit watches to use fsnotify instead of inotify Eric Paris
2009-06-12 20:32 ` [PATCH 2/7] audit: redo audit watch locking and refcnt in light of fsnotify Eric Paris
2009-06-12 20:32 ` [PATCH 3/7] audit: do not get and put just to free a watch Eric Paris
2009-06-12 20:32 ` [PATCH 4/7] fsnotify: duplicate fsnotify_mark_entry data between 2 marks Eric Paris
2009-06-12 20:32 ` [PATCH 5/7] fsnotify: allow addition of duplicate fsnotify marks Eric Paris
2009-06-12 20:32 ` [PATCH 6/7] audit: reimplement audit_trees using fsnotify rather than inotify Eric Paris
2009-06-12 20:32 ` [PATCH 7/7] audit: move audit to a subdirectory Eric Paris
2009-06-16 15:25 ` [PATCH 1/7] audit: convert audit watches to use fsnotify instead of inotify Klaus Heinrich Kiwi
2009-06-16 15:43   ` Eric Paris
2009-06-16 16:09     ` Klaus Heinrich Kiwi
2009-06-19 21:03       ` Eric Paris

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