ANDROID: sdcardfs: add support for user permission isolation

This allows you to hide the existence of a package from
a user by adding them to an exclude list. If a user
creates that package's folder and is on the exclude list,
they will not see that package's id.

Signed-off-by: Daniel Rosenberg <drosen@google.com>
Bug: 34542611
Change-Id: I9eb82e0bf2457d7eb81ee56153b9c7d2f6646323
diff --git a/fs/sdcardfs/derived_perm.c b/fs/sdcardfs/derived_perm.c
index 9408a54..a6d87d9 100644
--- a/fs/sdcardfs/derived_perm.c
+++ b/fs/sdcardfs/derived_perm.c
@@ -103,7 +103,7 @@
 		case PERM_ANDROID_OBB:
 		case PERM_ANDROID_MEDIA:
 			appid = get_appid(newdentry->d_name.name);
-			if (appid != 0) {
+			if (appid != 0 && !is_excluded(newdentry->d_name.name, parent_info->userid)) {
 				info->d_uid = multiuser_get_uid(parent_info->userid, appid);
 			}
 			set_top(info, &info->vfs_inode);
@@ -116,8 +116,11 @@
 	get_derived_permission_new(parent, dentry, dentry);
 }
 
-static int descendant_may_need_fixup(perm_t perm) {
-	if (perm == PERM_PRE_ROOT || perm == PERM_ROOT || perm == PERM_ANDROID)
+static int descendant_may_need_fixup(struct sdcardfs_inode_info *info, struct limit_search *limit)
+{
+	if (info->perm == PERM_ROOT)
+		return (limit->flags & BY_USERID)?info->userid == limit->userid:1;
+	if (info->perm == PERM_PRE_ROOT || info->perm == PERM_ANDROID)
 		return 1;
 	return 0;
 }
@@ -129,7 +132,8 @@
 	return 0;
 }
 
-void fixup_perms_recursive(struct dentry *dentry, const char* name, size_t len) {
+void fixup_perms_recursive(struct dentry *dentry, struct limit_search *limit)
+{
 	struct dentry *child;
 	struct sdcardfs_inode_info *info;
 	if (!dget(dentry))
@@ -143,22 +147,22 @@
 	if (needs_fixup(info->perm)) {
 		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;
-					}
+			dget(child);
+			if (!(limit->flags & BY_NAME) || !strncasecmp(child->d_name.name, limit->name, limit->length)) {
+				if (d_inode(child)) {
+					get_derived_permission(dentry, child);
+					fixup_tmp_permissions(d_inode(child));
+					dput(child);
+					break;
 				}
-				dput(child);
+			}
+			dput(child);
 		}
 		spin_unlock(&dentry->d_lock);
-	} else 	if (descendant_may_need_fixup(info->perm)) {
+	} 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, name, len);
+				fixup_perms_recursive(child, limit);
 		}
 		spin_unlock(&dentry->d_lock);
 	}