diff options
| author | Daniel Rosenberg <drosen@google.com> | 2017-03-02 15:11:27 -0800 |
|---|---|---|
| committer | Mister Oyster <oysterized@gmail.com> | 2017-04-13 12:35:18 +0200 |
| commit | e2da9b7973ae3dc2dde1094091add50b77c79c12 (patch) | |
| tree | 923945ae01234f49f8d5ca0cd40253d69262ac27 | |
| parent | 5f4b8762512cc370114c0f69baa9f521884aed66 (diff) | |
ANDROID: sdcardfs: Replace get/put with d_lock
dput cannot be called with a spin_lock. Instead,
we protect our accesses by holding the d_lock.
Signed-off-by: Daniel Rosenberg <drosen@google.com>
Bug: 35643557
Change-Id: I22cf30856d75b5616cbb0c223724f5ab866b5114
| -rwxr-xr-x | fs/sdcardfs/derived_perm.c | 32 |
1 files changed, 19 insertions, 13 deletions
diff --git a/fs/sdcardfs/derived_perm.c b/fs/sdcardfs/derived_perm.c index d31c19f31..ce2f9d34a 100755 --- a/fs/sdcardfs/derived_perm.c +++ b/fs/sdcardfs/derived_perm.c @@ -254,40 +254,46 @@ static int needs_fixup(perm_t perm) { return 0; } -void fixup_perms_recursive(struct dentry *dentry, struct limit_search *limit) { +static void __fixup_perms_recursive(struct dentry *dentry, struct limit_search *limit, int depth) { struct dentry *child; struct sdcardfs_inode_info *info; - if (!dget(dentry)) - return; + + /* + * All paths will terminate their recursion on hitting PERM_ANDROID_OBB, + * PERM_ANDROID_MEDIA, or PERM_ANDROID_DATA. This happens at a depth of + * at most 3. + */ + WARN(depth > 3, "%s: Max expected depth exceeded!\n", __func__); + spin_lock_nested(&dentry->d_lock, depth); if (!dentry->d_inode) { - dput(dentry); + spin_unlock(&dentry->d_lock); return; } info = SDCARDFS_I(dentry->d_inode); if (needs_fixup(info->perm)) { - spin_lock(&dentry->d_lock); list_for_each_entry(child, &dentry->d_subdirs, d_child) { - dget(child); + spin_lock_nested(&child->d_lock, depth + 1); if (!(limit->flags & BY_NAME) || !strncasecmp(child->d_name.name, limit->name, limit->length)) { if (child->d_inode) { get_derived_permission(dentry, child); fixup_tmp_permissions(child->d_inode); - dput(child); + spin_unlock(&child->d_lock); break; } } - dput(child); + spin_unlock(&child->d_lock); } - spin_unlock(&dentry->d_lock); } else if (descendant_may_need_fixup(info, limit)) { - spin_lock(&dentry->d_lock); list_for_each_entry(child, &dentry->d_subdirs, d_child) { - fixup_perms_recursive(child, limit); + __fixup_perms_recursive(child, limit, depth + 1); } - spin_unlock(&dentry->d_lock); } - dput(dentry); + spin_unlock(&dentry->d_lock); +} + +void fixup_perms_recursive(struct dentry *dentry, struct limit_search *limit) { + __fixup_perms_recursive(dentry, limit, 0); } void drop_recursive(struct dentry *parent) { |
