mmc: s3c6410: enable ADMA feature in 6410 sdhci controller
[safe/jmp/linux-2.6] / kernel / audit_watch.c
index da8be6d..8df4369 100644 (file)
@@ -27,6 +27,7 @@
 #include <linux/namei.h>
 #include <linux/netlink.h>
 #include <linux/sched.h>
+#include <linux/slab.h>
 #include <linux/inotify.h>
 #include <linux/security.h>
 #include "audit.h"
@@ -45,8 +46,8 @@
 
 struct audit_watch {
        atomic_t                count;  /* reference count */
-       char                    *path;  /* insertion path */
        dev_t                   dev;    /* associated superblock device */
+       char                    *path;  /* insertion path */
        unsigned long           ino;    /* associated inode number */
        struct audit_parent     *parent; /* associated parent */
        struct list_head        wlist;  /* entry in parent->watches list */
@@ -234,11 +235,7 @@ static void audit_watch_log_rule_change(struct audit_krule *r, struct audit_watc
                audit_log_string(ab, op);
                audit_log_format(ab, " path=");
                audit_log_untrustedstring(ab, w->path);
-               if (r->filterkey) {
-                       audit_log_format(ab, " key=");
-                       audit_log_untrustedstring(ab, r->filterkey);
-               } else
-                       audit_log_format(ab, " key=(null)");
+               audit_log_key(ab, r->filterkey);
                audit_log_format(ab, " list=%d res=1", r->listnr);
                audit_log_end(ab);
        }
@@ -345,7 +342,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 +377,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 +423,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 +452,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 +474,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)