diff --git a/FsCrypt.cpp b/FsCrypt.cpp index 9bdade5..45edc9d 100644 --- a/FsCrypt.cpp +++ b/FsCrypt.cpp @@ -791,6 +791,11 @@ bool fscrypt_lock_user_key(userid_t user_id) { static bool prepare_subdirs(const std::string& action, const std::string& volume_uuid, userid_t user_id, int flags) { + // TODO(b/141677108): Remove this & make it the default behavior + if (android::base::GetProperty("ro.vold.level_from_user", "0") == "1") { + flags |= android::os::IVold::STORAGE_FLAG_LEVEL_FROM_USER; + } + if (0 != android::vold::ForkExecvp( std::vector{prepare_subdirs_path, action, volume_uuid, std::to_string(user_id), std::to_string(flags)})) { diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl index d0e753e..61e1e54 100644 --- a/binder/android/os/IVold.aidl +++ b/binder/android/os/IVold.aidl @@ -164,6 +164,7 @@ interface IVold { const int STORAGE_FLAG_DE = 1; const int STORAGE_FLAG_CE = 2; + const int STORAGE_FLAG_LEVEL_FROM_USER = 4; const int REMOUNT_MODE_NONE = 0; const int REMOUNT_MODE_DEFAULT = 1; diff --git a/vold_prepare_subdirs.cpp b/vold_prepare_subdirs.cpp index d624d73..0283614 100644 --- a/vold_prepare_subdirs.cpp +++ b/vold_prepare_subdirs.cpp @@ -54,20 +54,33 @@ static bool valid_uuid(const std::string& s) { return s.size() < 40 && s.find_first_not_of("0123456789abcdefABCDEF-_") == std::string::npos; } -static bool prepare_dir(struct selabel_handle* sehandle, mode_t mode, uid_t uid, gid_t gid, - const std::string& path) { +static bool prepare_dir_for_user(struct selabel_handle* sehandle, mode_t mode, uid_t uid, gid_t gid, + const std::string& path, uid_t user_id) { auto clearfscreatecon = android::base::make_scope_guard([] { setfscreatecon(nullptr); }); auto secontext = std::unique_ptr(nullptr, freecon); - char* tmp_secontext; - if (sehandle && selabel_lookup(sehandle, &tmp_secontext, path.c_str(), S_IFDIR) == 0) { - secontext.reset(tmp_secontext); + if (sehandle) { + char* tmp_secontext; + + if (selabel_lookup(sehandle, &tmp_secontext, path.c_str(), S_IFDIR) == 0) { + secontext.reset(tmp_secontext); + + if (user_id != (uid_t)-1) { + if (selinux_android_context_with_level(secontext.get(), &tmp_secontext, user_id, + (uid_t)-1) != 0) { + PLOG(ERROR) << "Unable to create context with level for: " << path; + return false; + } + secontext.reset(tmp_secontext); // Free the context + } + } } + LOG(DEBUG) << "Setting up mode " << std::oct << mode << std::dec << " uid " << uid << " gid " << gid << " context " << (secontext ? secontext.get() : "null") << " on path: " << path; if (secontext) { if (setfscreatecon(secontext.get()) != 0) { - PLOG(ERROR) << "Unable to read setfscreatecon for: " << path; + PLOG(ERROR) << "Unable to setfscreatecon for: " << path; return false; } } @@ -93,6 +106,11 @@ static bool prepare_dir(struct selabel_handle* sehandle, mode_t mode, uid_t uid, return true; } +static bool prepare_dir(struct selabel_handle* sehandle, mode_t mode, uid_t uid, gid_t gid, + const std::string& path) { + return prepare_dir_for_user(sehandle, mode, uid, gid, path, (uid_t)-1); +} + static bool rmrf_contents(const std::string& path) { auto dirp = std::unique_ptr(opendir(path.c_str()), closedir); if (!dirp) { @@ -148,8 +166,17 @@ static bool prepare_apex_subdirs(struct selabel_handle* sehandle, const std::str static bool prepare_subdirs(const std::string& volume_uuid, int user_id, int flags) { struct selabel_handle* sehandle = selinux_android_file_context_handle(); - if (volume_uuid.empty()) { - if (flags & android::os::IVold::STORAGE_FLAG_DE) { + const uid_t user_for_level = + (flags & android::os::IVold::STORAGE_FLAG_LEVEL_FROM_USER) ? user_id : -1; + + if (flags & android::os::IVold::STORAGE_FLAG_DE) { + auto user_de_path = android::vold::BuildDataUserDePath(volume_uuid, user_id); + if (!prepare_dir_for_user(sehandle, 0771, AID_SYSTEM, AID_SYSTEM, user_de_path, + user_for_level)) { + return false; + } + + if (volume_uuid.empty()) { auto misc_de_path = android::vold::BuildDataMiscDePath(user_id); if (!prepare_dir(sehandle, 0700, 0, 0, misc_de_path + "/vold")) return false; if (!prepare_dir(sehandle, 0700, 0, 0, misc_de_path + "/storaged")) return false; @@ -158,6 +185,12 @@ static bool prepare_subdirs(const std::string& volume_uuid, int user_id, int fla prepare_dir(sehandle, 0700, 0, 0, misc_de_path + "/apexrollback"); prepare_apex_subdirs(sehandle, misc_de_path); + auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id); + if (!prepare_dir_for_user(sehandle, 0771, AID_SYSTEM, AID_SYSTEM, profiles_de_path, + user_for_level)) { + return false; + } + auto vendor_de_path = android::vold::BuildDataVendorDePath(user_id); if (!prepare_dir(sehandle, 0700, AID_SYSTEM, AID_SYSTEM, vendor_de_path + "/fpdata")) { return false; @@ -167,11 +200,20 @@ static bool prepare_subdirs(const std::string& volume_uuid, int user_id, int fla return false; } } - if (flags & android::os::IVold::STORAGE_FLAG_CE) { + } + if (flags & android::os::IVold::STORAGE_FLAG_CE) { + auto user_ce_path = android::vold::BuildDataUserCePath(volume_uuid, user_id); + if (!prepare_dir_for_user(sehandle, 0771, AID_SYSTEM, AID_SYSTEM, user_ce_path, + user_for_level)) { + return false; + } + + if (volume_uuid.empty()) { auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id); if (!prepare_dir(sehandle, 0700, 0, 0, misc_ce_path + "/vold")) return false; if (!prepare_dir(sehandle, 0700, 0, 0, misc_ce_path + "/storaged")) return false; if (!prepare_dir(sehandle, 0700, 0, 0, misc_ce_path + "/rollback")) return false; + // TODO: Return false if this returns false once sure this should succeed. prepare_dir(sehandle, 0700, 0, 0, misc_ce_path + "/apexrollback"); prepare_apex_subdirs(sehandle, misc_ce_path);