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)
committerDaniel Rosenberg <drosen@google.com>
Tue, 30 Jan 2018 03:40:01 +0000 (19:40 -0800)
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 60ae94bb99f79769ef0f78e00ef6abf5c5a7aeac..9408a5477adab9590dfd40ec450445752127887a 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 (child->d_inode) {
+                                               get_derived_permission(dentry, child);
+                                               fixup_tmp_permissions(child->d_inode);
+                                               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);
 }