diff options
Diffstat (limited to 'sdcard')
-rw-r--r-- | sdcard/sdcard.c | 66 |
1 files changed, 31 insertions, 35 deletions
diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c index 041c37a..4712e90 100644 --- a/sdcard/sdcard.c +++ b/sdcard/sdcard.c @@ -146,8 +146,6 @@ typedef enum { PERM_ANDROID_OBB, /* This node is "/Android/media" */ PERM_ANDROID_MEDIA, - /* This node is "/Android/user" */ - PERM_ANDROID_USER, } perm_t; /* Permissions structure to derive */ @@ -252,7 +250,7 @@ struct fuse { __u32 inode_ctr; Hashmap* package_to_appid; - Hashmap* appid_with_rw; + Hashmap* uid_with_rw; }; /* Private data used by a single fuse handler. */ @@ -474,6 +472,8 @@ static void derive_permissions_locked(struct fuse* fuse, struct node *parent, /* Legacy internal layout places users at top level */ node->perm = PERM_ROOT; node->userid = strtoul(node->name, NULL, 10); + node->gid = multiuser_get_uid(node->userid, AID_SDCARD_R); + node->mode = 0771; break; case PERM_ROOT: /* Assume masked off by default. */ @@ -485,14 +485,14 @@ static void derive_permissions_locked(struct fuse* fuse, struct node *parent, } else if (fuse->split_perms) { if (!strcasecmp(node->name, "DCIM") || !strcasecmp(node->name, "Pictures")) { - node->gid = AID_SDCARD_PICS; + node->gid = multiuser_get_uid(node->userid, AID_SDCARD_PICS); } else if (!strcasecmp(node->name, "Alarms") || !strcasecmp(node->name, "Movies") || !strcasecmp(node->name, "Music") || !strcasecmp(node->name, "Notifications") || !strcasecmp(node->name, "Podcasts") || !strcasecmp(node->name, "Ringtones")) { - node->gid = AID_SDCARD_AV; + node->gid = multiuser_get_uid(node->userid, AID_SDCARD_AV); } } break; @@ -512,13 +512,6 @@ static void derive_permissions_locked(struct fuse* fuse, struct node *parent, /* App-specific directories inside; let anyone traverse */ node->perm = PERM_ANDROID_MEDIA; node->mode = 0771; - } else if (!strcasecmp(node->name, "user")) { - /* User directories must only be accessible to system, protected - * by sdcard_all. Zygote will bind mount the appropriate user- - * specific path. */ - node->perm = PERM_ANDROID_USER; - node->gid = AID_SDCARD_ALL; - node->mode = 0770; } break; case PERM_ANDROID_DATA: @@ -530,13 +523,6 @@ static void derive_permissions_locked(struct fuse* fuse, struct node *parent, } node->mode = 0770; break; - case PERM_ANDROID_USER: - /* Root of a secondary user */ - node->perm = PERM_ROOT; - node->userid = strtoul(node->name, NULL, 10); - node->gid = AID_SDCARD_R; - node->mode = 0771; - break; } } @@ -547,8 +533,7 @@ static bool get_caller_has_rw_locked(struct fuse* fuse, const struct fuse_in_hea return true; } - appid_t appid = multiuser_get_app_id(hdr->uid); - return hashmapContainsKey(fuse->appid_with_rw, (void*) (uintptr_t) appid); + return hashmapContainsKey(fuse->uid_with_rw, (void*) (uintptr_t) hdr->uid); } /* Kernel has already enforced everything we returned through @@ -729,7 +714,7 @@ static struct node* acquire_or_create_child_locked( } static void fuse_init(struct fuse *fuse, int fd, const char *source_path, - gid_t write_gid, derive_t derive, bool split_perms) { + gid_t write_gid, userid_t owner_user, derive_t derive, bool split_perms) { pthread_mutex_init(&fuse->lock, NULL); fuse->fd = fd; @@ -761,10 +746,10 @@ static void fuse_init(struct fuse *fuse, int fd, const char *source_path, * places user_id at the top directory level, with the actual roots * just below that. Shared OBB path is also at top level. */ fuse->root.perm = PERM_LEGACY_PRE_ROOT; - fuse->root.mode = 0771; + fuse->root.mode = 0711; fuse->root.gid = AID_SDCARD_R; fuse->package_to_appid = hashmapCreate(256, str_hash, str_icase_equals); - fuse->appid_with_rw = hashmapCreate(128, int_hash, int_equals); + fuse->uid_with_rw = hashmapCreate(128, int_hash, int_equals); snprintf(fuse->obbpath, sizeof(fuse->obbpath), "%s/obb", source_path); fs_prepare_dir(fuse->obbpath, 0775, getuid(), getgid()); break; @@ -773,9 +758,10 @@ static void fuse_init(struct fuse *fuse, int fd, const char *source_path, * /Android/user and shared OBB path under /Android/obb. */ fuse->root.perm = PERM_ROOT; fuse->root.mode = 0771; - fuse->root.gid = AID_SDCARD_R; + fuse->root.userid = owner_user; + fuse->root.gid = multiuser_get_uid(owner_user, AID_SDCARD_R); fuse->package_to_appid = hashmapCreate(256, str_hash, str_icase_equals); - fuse->appid_with_rw = hashmapCreate(128, int_hash, int_equals); + fuse->uid_with_rw = hashmapCreate(128, int_hash, int_equals); snprintf(fuse->obbpath, sizeof(fuse->obbpath), "%s/Android/obb", source_path); break; } @@ -1710,7 +1696,7 @@ static int read_package_list(struct fuse *fuse) { pthread_mutex_lock(&fuse->lock); hashmapForEach(fuse->package_to_appid, remove_str_to_int, fuse->package_to_appid); - hashmapForEach(fuse->appid_with_rw, remove_int_to_null, fuse->appid_with_rw); + hashmapForEach(fuse->uid_with_rw, remove_int_to_null, fuse->uid_with_rw); FILE* file = fopen(kPackagesListFile, "r"); if (!file) { @@ -1731,9 +1717,14 @@ static int read_package_list(struct fuse *fuse) { char* token = strtok(gids, ","); while (token != NULL) { - if (strtoul(token, NULL, 10) == fuse->write_gid) { - hashmapPut(fuse->appid_with_rw, (void*) (uintptr_t) appid, (void*) (uintptr_t) 1); - break; + // Current packages.list format is a bit funky; it blends per + // user GID membership into a single per-app line. Here we + // work backwards from the groups to build the per-user UIDs + // that have write permission. + gid_t gid = strtoul(token, NULL, 10); + if (multiuser_get_app_id(gid) == fuse->write_gid) { + uid_t uid = multiuser_get_uid(multiuser_get_user_id(gid), appid); + hashmapPut(fuse->uid_with_rw, (void*) (uintptr_t) uid, (void*) (uintptr_t) 1); } token = strtok(NULL, ","); } @@ -1742,7 +1733,7 @@ static int read_package_list(struct fuse *fuse) { TRACE("read_package_list: found %zu packages, %zu with write_gid\n", hashmapSize(fuse->package_to_appid), - hashmapSize(fuse->appid_with_rw)); + hashmapSize(fuse->uid_with_rw)); fclose(file); pthread_mutex_unlock(&fuse->lock); return 0; @@ -1867,7 +1858,7 @@ static int usage() } static int run(const char* source_path, const char* dest_path, uid_t uid, - gid_t gid, gid_t write_gid, int num_threads, derive_t derive, + gid_t gid, gid_t write_gid, userid_t owner_user, int num_threads, derive_t derive, bool split_perms) { int fd; char opts[256]; @@ -1912,7 +1903,7 @@ static int run(const char* source_path, const char* dest_path, uid_t uid, goto error; } - fuse_init(&fuse, fd, source_path, write_gid, derive, split_perms); + fuse_init(&fuse, fd, source_path, write_gid, owner_user, derive, split_perms); umask(0); res = ignite_fuse(&fuse, num_threads); @@ -1933,6 +1924,7 @@ int main(int argc, char **argv) uid_t uid = 0; gid_t gid = 0; gid_t write_gid = AID_SDCARD_RW; + userid_t owner_user = 0; int num_threads = DEFAULT_NUM_THREADS; derive_t derive = DERIVE_NONE; bool split_perms = false; @@ -1941,7 +1933,7 @@ int main(int argc, char **argv) int fs_version; int opt; - while ((opt = getopt(argc, argv, "u:g:w:t:dls")) != -1) { + while ((opt = getopt(argc, argv, "u:g:w:o:t:dls")) != -1) { switch (opt) { case 'u': uid = strtoul(optarg, NULL, 10); @@ -1952,6 +1944,9 @@ int main(int argc, char **argv) case 'w': write_gid = strtoul(optarg, NULL, 10); break; + case 'o': + owner_user = strtoul(optarg, NULL, 10); + break; case 't': num_threads = strtoul(optarg, NULL, 10); break; @@ -2018,6 +2013,7 @@ int main(int argc, char **argv) sleep(1); } - res = run(source_path, dest_path, uid, gid, write_gid, num_threads, derive, split_perms); + res = run(source_path, dest_path, uid, gid, write_gid, owner_user, + num_threads, derive, split_perms); return res < 0 ? 1 : 0; } |