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 <[email protected]>
---

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

--
Linux-audit mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/linux-audit

Reply via email to