From mboxrd@z Thu Jan 1 00:00:00 1970 From: Eric Paris Subject: [PATCH 7/7] audit: use kern_path rather than namei for watch creation Date: Thu, 28 May 2009 19:23:17 -0400 Message-ID: <20090528232317.15072.25657.stgit@paris.rdu.redhat.com> References: <20090528232244.15072.67812.stgit@paris.rdu.redhat.com> Mime-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: <20090528232244.15072.67812.stgit@paris.rdu.redhat.com> List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-audit-bounces@redhat.com Errors-To: linux-audit-bounces@redhat.com To: linux-audit@redhat.com Cc: viro@ZenIV.linux.org.uk List-Id: linux-audit@redhat.com 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 --- 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; }