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

Eric Paris
2009-05-28T23:23:17Z

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

}