summaryrefslogtreecommitdiffstats
path: root/kernel/audit_watch.c
diff options
context:
space:
mode:
authorEric Paris <eparis@redhat.com>2009-06-11 14:31:36 -0400
committerAl Viro <viro@zeniv.linux.org.uk>2009-06-23 23:51:05 -0400
commit35fe4d0b1b12286a81938e9c5fdfaf639ac0ce5b (patch)
treec520706593fd33748944315bb87d789a7f31960e /kernel/audit_watch.c
parentcfcad62c74abfef83762dc05a556d21bdf3980a2 (diff)
Audit: move audit_get_nd completely into audit_watch
audit_get_nd() is only used by audit_watch and could be more cleanly implemented by having the audit watch functions call it when needed rather than making the generic audit rule parsing code deal with those objects. Signed-off-by: Eric Paris <eparis@redhat.com>
Diffstat (limited to 'kernel/audit_watch.c')
-rw-r--r--kernel/audit_watch.c27
1 files changed, 20 insertions, 7 deletions
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index da8be6d39c1..b49ab019fdf 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -345,7 +345,7 @@ void audit_inotify_unregister(struct list_head *in_list)
}
/* Get path information necessary for adding watches. */
-int audit_get_nd(char *path, struct nameidata **ndp, struct nameidata **ndw)
+static int audit_get_nd(char *path, struct nameidata **ndp, struct nameidata **ndw)
{
struct nameidata *ndparent, *ndwatch;
int err;
@@ -380,7 +380,7 @@ int audit_get_nd(char *path, struct nameidata **ndp, struct nameidata **ndw)
}
/* Release resources used for watch path information. */
-void audit_put_nd(struct nameidata *ndp, struct nameidata *ndw)
+static void audit_put_nd(struct nameidata *ndp, struct nameidata *ndw)
{
if (ndp) {
path_put(&ndp->path);
@@ -426,14 +426,24 @@ static void audit_add_to_parent(struct audit_krule *krule,
/* Find a matching watch entry, or add this one.
* Caller must hold audit_filter_mutex. */
-int audit_add_watch(struct audit_krule *krule, struct nameidata *ndp,
- struct nameidata *ndw)
+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;
int ret = 0;
+ mutex_unlock(&audit_filter_mutex);
+
+ /* Avoid calling path_lookup under audit_filter_mutex. */
+ ret = audit_get_nd(watch->path, &ndp, &ndw);
+ if (ret) {
+ /* caller expects mutex locked */
+ mutex_lock(&audit_filter_mutex);
+ goto error;
+ }
+
/* update watch filter fields */
if (ndw) {
watch->dev = ndw->path.dentry->d_inode->i_sb->s_dev;
@@ -445,15 +455,14 @@ int audit_add_watch(struct audit_krule *krule, struct nameidata *ndp,
* inotify watch is found, inotify_find_watch() grabs a reference before
* returning.
*/
- mutex_unlock(&audit_filter_mutex);
-
if (inotify_find_watch(audit_ih, ndp->path.dentry->d_inode,
&i_watch) < 0) {
parent = audit_init_parent(ndp);
if (IS_ERR(parent)) {
/* caller expects mutex locked */
mutex_lock(&audit_filter_mutex);
- return PTR_ERR(parent);
+ ret = PTR_ERR(parent);
+ goto error;
}
} else
parent = container_of(i_watch, struct audit_parent, wdata);
@@ -468,7 +477,11 @@ int audit_add_watch(struct audit_krule *krule, struct nameidata *ndp,
/* match get in audit_init_parent or inotify_find_watch */
put_inotify_watch(&parent->wdata);
+
+error:
+ audit_put_nd(ndp, ndw); /* NULL args OK */
return ret;
+
}
void audit_remove_watch_rule(struct audit_krule *krule, struct list_head *list)