ANDROID: sdcardfs: Fix locking issue with permision fix up
authorDaniel Rosenberg <drosen@google.com>
Tue, 27 Dec 2016 20:36:29 +0000 (12:36 -0800)
committerAmit Pundir <amit.pundir@linaro.org>
Fri, 3 Feb 2017 09:34:29 +0000 (15:04 +0530)
Don't use lookup_one_len so we can grab the spinlock that
protects d_subdirs.

Bug: 30954918
Change-Id: I0c6a393252db7beb467e0d563739a3a14e1b5115
Signed-off-by: Daniel Rosenberg <drosen@google.com>
fs/sdcardfs/derived_perm.c

index 066edbbb6ad6285ebf5599fbecd9ca56e25d76f3..c77695c8f729cb4a408e01ecb616991786158794 100644 (file)
@@ -141,32 +141,26 @@ void fixup_perms_recursive(struct dentry *dentry, const char* name, size_t len)
        info = SDCARDFS_I(d_inode(dentry));
 
        if (needs_fixup(info->perm)) {
-               /* We need permission to fix up these values.
-                * Since permissions are based of of the mount, and
-                * we are accessing without the mount point, we create
-                * a fake mount with the permissions we will be using.
-                */
-               struct vfsmount fakemnt;
-               struct sdcardfs_vfsmount_options opts;
-               fakemnt.data = &opts;
-               opts.gid = AID_SDCARD_RW;
-               opts.mask = 0;
-               mutex_lock(&d_inode(dentry)->i_mutex);
-               child = lookup_one_len2(name, &fakemnt, dentry, len);
-               mutex_unlock(&d_inode(dentry)->i_mutex);
-               if (!IS_ERR(child)) {
-                       if (d_inode(child)) {
-                               get_derived_permission(dentry, child);
-                               fixup_tmp_permissions(d_inode(child));
-                       }
-                       dput(child);
+               spin_lock(&dentry->d_lock);
+               list_for_each_entry(child, &dentry->d_subdirs, d_child) {
+                               dget(child);
+                               if (!strncasecmp(child->d_name.name, name, len)) {
+                                       if (d_inode(child)) {
+                                               get_derived_permission(dentry, child);
+                                               fixup_tmp_permissions(d_inode(child));
+                                               dput(child);
+                                               break;
+                                       }
+                               }
+                               dput(child);
                }
+               spin_unlock(&dentry->d_lock);
        } else  if (descendant_may_need_fixup(info->perm)) {
-               mutex_lock(&d_inode(dentry)->i_mutex);
+               spin_lock(&dentry->d_lock);
                list_for_each_entry(child, &dentry->d_subdirs, d_child) {
                                fixup_perms_recursive(child, name, len);
                }
-               mutex_unlock(&d_inode(dentry)->i_mutex);
+               spin_unlock(&dentry->d_lock);
        }
        dput(dentry);
 }