[PATCH 7/7] audit: use kern_path rather than namei for watch creation

Eric Paris eparis at redhat.com
Thu May 28 23:23:17 UTC 2009


kernel watches jump through stupid allocation hoops to get the namei data
for the path in question and it's parent.  All useless crap since we just
need to hold a struct path for a bit.

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

 kernel/audit/audit_watch.c |   68 ++++++++++++++++----------------------------
 1 files changed, 25 insertions(+), 43 deletions(-)

diff --git a/kernel/audit/audit_watch.c b/kernel/audit/audit_watch.c
index 2ba999e..b5e369d 100644
--- a/kernel/audit/audit_watch.c
+++ b/kernel/audit/audit_watch.c
@@ -130,7 +130,7 @@ dev_t audit_watch_dev(struct audit_watch *watch)
 }
 
 /* Initialize a parent watch entry. */
-static struct audit_parent *audit_init_parent(struct nameidata *ndp)
+static struct audit_parent *audit_init_parent(struct path *parent_path)
 {
 	struct audit_parent *parent;
 	s32 wd;
@@ -146,7 +146,7 @@ static struct audit_parent *audit_init_parent(struct nameidata *ndp)
 	/* 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,
-			       ndp->path.dentry->d_inode, AUDIT_IN_WATCH);
+			       parent_path->dentry->d_inode, AUDIT_IN_WATCH);
 	if (wd < 0) {
 		audit_free_parent(&parent->wdata);
 		return ERR_PTR(wd);
@@ -355,51 +355,33 @@ void audit_inotify_unregister(struct list_head *in_list)
 }
 
 /* Get path information necessary for adding watches. */
-static int audit_get_nd(char *path, struct nameidata **ndp, struct nameidata **ndw)
+static int audit_get_path(const char *path, struct path *parent_path,
+			  struct path *watch_path)
 {
-	struct nameidata *ndparent, *ndwatch;
 	int err;
 
-	ndparent = kmalloc(sizeof(*ndparent), GFP_KERNEL);
-	if (unlikely(!ndparent))
-		return -ENOMEM;
+	parent_path->dentry = NULL;
+	watch_path->dentry = NULL;
 
-	ndwatch = kmalloc(sizeof(*ndwatch), GFP_KERNEL);
-	if (unlikely(!ndwatch)) {
-		kfree(ndparent);
-		return -ENOMEM;
-	}
-
-	err = path_lookup(path, LOOKUP_PARENT, ndparent);
-	if (err) {
-		kfree(ndparent);
-		kfree(ndwatch);
+	err = kern_path(path, LOOKUP_PARENT, parent_path);
+	if (err)
 		return err;
-	}
 
-	err = path_lookup(path, 0, ndwatch);
-	if (err) {
-		kfree(ndwatch);
-		ndwatch = NULL;
-	}
-
-	*ndp = ndparent;
-	*ndw = ndwatch;
+	/* watch_path might not exist, we don't care about errors here. */
+	kern_path(path, 0, watch_path);
 
 	return 0;
 }
 
 /* Release resources used for watch path information. */
-static void audit_put_nd(struct nameidata *ndp, struct nameidata *ndw)
+static void audit_put_path(struct path *parent_path, struct path *watch_path)
 {
-	if (ndp) {
-		path_put(&ndp->path);
-		kfree(ndp);
-	}
-	if (ndw) {
-		path_put(&ndw->path);
-		kfree(ndw);
-	}
+	/* there should always be a valid parent path */
+	if (parent_path->dentry)
+		path_put(parent_path);
+	/* creating a watch on a non-existant file may not have a watch_path->dentry */
+	if (watch_path->dentry)
+		path_put(watch_path);
 }
 
 /* Associate the given rule with an existing parent inotify_watch.
@@ -441,13 +423,13 @@ int audit_add_watch(struct audit_krule *krule)
 	struct audit_watch *watch = krule->watch;
 	struct inotify_watch *i_watch;
 	struct audit_parent *parent;
-	struct nameidata *ndp = NULL, *ndw = NULL;
+	struct path parent_path, watch_path;
 	int ret = 0;
 
 	mutex_unlock(&audit_filter_mutex);
 
 	/* Avoid calling path_lookup under audit_filter_mutex. */
-	ret = audit_get_nd(watch->path, &ndp, &ndw);
+	ret = audit_get_path(watch->path, &parent_path, &watch_path);
 	if (ret) {
 		/* caller expects mutex locked */
 		mutex_lock(&audit_filter_mutex);
@@ -455,9 +437,9 @@ int audit_add_watch(struct audit_krule *krule)
 	}
 
 	/* update watch filter fields */
-	if (ndw) {
-		watch->dev = ndw->path.dentry->d_inode->i_sb->s_dev;
-		watch->ino = ndw->path.dentry->d_inode->i_ino;
+	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
@@ -465,9 +447,9 @@ int audit_add_watch(struct audit_krule *krule)
 	 * inotify watch is found, inotify_find_watch() grabs a reference before
 	 * returning.
 	 */
-	if (inotify_find_watch(audit_ih, ndp->path.dentry->d_inode,
+	if (inotify_find_watch(audit_ih, parent_path.dentry->d_inode,
 			       &i_watch) < 0) {
-		parent = audit_init_parent(ndp);
+		parent = audit_init_parent(&parent_path);
 		if (IS_ERR(parent)) {
 			/* caller expects mutex locked */
 			mutex_lock(&audit_filter_mutex);
@@ -489,7 +471,7 @@ int audit_add_watch(struct audit_krule *krule)
 	put_inotify_watch(&parent->wdata);
 
 error:
-	audit_put_nd(ndp, ndw);		/* NULL args OK */
+	audit_put_path(&parent_path, &watch_path);
 	return ret;
 
 }




More information about the Linux-audit mailing list