OSDN Git Service

MIPS: VDSO: Prevent use of smp_processor_id()
[android-x86/kernel.git] / kernel / audit_watch.c
index 0d302a8..f036b6a 100644 (file)
@@ -419,6 +419,13 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list)
        struct path parent_path;
        int h, ret = 0;
 
+       /*
+        * When we will be calling audit_add_to_parent, krule->watch might have
+        * been updated and watch might have been freed.
+        * So we need to keep a reference of watch.
+        */
+       audit_get_watch(watch);
+
        mutex_unlock(&audit_filter_mutex);
 
        /* Avoid calling path_lookup under audit_filter_mutex. */
@@ -427,8 +434,10 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list)
        /* caller expects mutex locked */
        mutex_lock(&audit_filter_mutex);
 
-       if (ret)
+       if (ret) {
+               audit_put_watch(watch);
                return ret;
+       }
 
        /* either find an old parent or attach a new one */
        parent = audit_find_parent(d_backing_inode(parent_path.dentry));
@@ -446,6 +455,7 @@ int audit_add_watch(struct audit_krule *krule, struct list_head **list)
        *list = &audit_inode_hash[h];
 error:
        path_put(&parent_path);
+       audit_put_watch(watch);
        return ret;
 }
 
@@ -457,13 +467,15 @@ void audit_remove_watch_rule(struct audit_krule *krule)
        list_del(&krule->rlist);
 
        if (list_empty(&watch->rules)) {
+               /*
+                * audit_remove_watch() drops our reference to 'parent' which
+                * can get freed. Grab our own reference to be safe.
+                */
+               audit_get_parent(parent);
                audit_remove_watch(watch);
-
-               if (list_empty(&parent->watches)) {
-                       audit_get_parent(parent);
+               if (list_empty(&parent->watches))
                        fsnotify_destroy_mark(&parent->mark, audit_watch_group);
-                       audit_put_parent(parent);
-               }
+               audit_put_parent(parent);
        }
 }