diff options
-rw-r--r-- | fs_mgr/fs_mgr.cpp | 58 | ||||
-rw-r--r-- | fs_mgr/fs_mgr_overlayfs.cpp | 7 | ||||
-rw-r--r-- | libcutils/fs_config.cpp | 1 | ||||
-rw-r--r-- | libprocessgroup/include/processgroup/processgroup.h | 2 | ||||
-rw-r--r-- | libprocessgroup/processgroup.cpp | 9 | ||||
-rw-r--r-- | libprocessgroup/task_profiles.cpp | 296 | ||||
-rw-r--r-- | libprocessgroup/task_profiles.h | 66 | ||||
-rw-r--r-- | rootdir/init.rc | 52 | ||||
-rw-r--r-- | trusty/storage/proxy/Android.bp | 5 | ||||
-rw-r--r-- | trusty/storage/proxy/checkpoint_handling.cpp | 15 | ||||
-rw-r--r-- | trusty/storage/proxy/checkpoint_handling.h | 2 | ||||
-rw-r--r-- | trusty/storage/proxy/proxy.c | 7 | ||||
-rw-r--r-- | trusty/storage/proxy/storage.c | 46 |
13 files changed, 386 insertions, 180 deletions
diff --git a/fs_mgr/fs_mgr.cpp b/fs_mgr/fs_mgr.cpp index 21df8af8c..8896ec33c 100644 --- a/fs_mgr/fs_mgr.cpp +++ b/fs_mgr/fs_mgr.cpp @@ -170,6 +170,22 @@ static bool should_force_check(int fs_stat) { FS_STAT_SET_RESERVED_BLOCKS_FAILED | FS_STAT_ENABLE_ENCRYPTION_FAILED); } +static bool umount_retry(const std::string& mount_point) { + int retry_count = 5; + bool umounted = false; + + while (retry_count-- > 0) { + umounted = umount(mount_point.c_str()) == 0; + if (umounted) { + LINFO << __FUNCTION__ << "(): unmount(" << mount_point << ") succeeded"; + break; + } + PERROR << __FUNCTION__ << "(): umount(" << mount_point << ") failed"; + if (retry_count) sleep(1); + } + return umounted; +} + static void check_fs(const std::string& blk_device, const std::string& fs_type, const std::string& target, int* fs_stat) { int status; @@ -209,25 +225,12 @@ static void check_fs(const std::string& blk_device, const std::string& fs_type, tmpmnt_opts.c_str()); PINFO << __FUNCTION__ << "(): mount(" << blk_device << "," << target << "," << fs_type << ")=" << ret; - if (!ret) { - bool umounted = false; - int retry_count = 5; - while (retry_count-- > 0) { - umounted = umount(target.c_str()) == 0; - if (umounted) { - LINFO << __FUNCTION__ << "(): unmount(" << target << ") succeeded"; - break; - } - PERROR << __FUNCTION__ << "(): umount(" << target << ") failed"; - if (retry_count) sleep(1); - } - if (!umounted) { - // boot may fail but continue and leave it to later stage for now. - PERROR << __FUNCTION__ << "(): umount(" << target << ") timed out"; - *fs_stat |= FS_STAT_RO_UNMOUNT_FAILED; - } - } else { + if (ret) { *fs_stat |= FS_STAT_RO_MOUNT_FAILED; + } else if (!umount_retry(target)) { + // boot may fail but continue and leave it to later stage for now. + PERROR << __FUNCTION__ << "(): umount(" << target << ") timed out"; + *fs_stat |= FS_STAT_RO_UNMOUNT_FAILED; } } @@ -268,12 +271,12 @@ static void check_fs(const std::string& blk_device, const std::string& fs_type, LINFO << "Running " << F2FS_FSCK_BIN << " -f -c 10000 --debug-cache " << realpath(blk_device); ret = logwrap_fork_execvp(ARRAY_SIZE(f2fs_fsck_forced_argv), f2fs_fsck_forced_argv, - &status, false, LOG_KLOG | LOG_FILE, false, FSCK_LOG_FILE); + &status, false, LOG_KLOG | LOG_FILE, false, nullptr); } else { LINFO << "Running " << F2FS_FSCK_BIN << " -a -c 10000 --debug-cache " << realpath(blk_device); ret = logwrap_fork_execvp(ARRAY_SIZE(f2fs_fsck_argv), f2fs_fsck_argv, &status, false, - LOG_KLOG | LOG_FILE, false, FSCK_LOG_FILE); + LOG_KLOG | LOG_FILE, false, nullptr); } if (ret < 0) { /* No need to check for error in fork, we can't really handle it now */ @@ -1029,12 +1032,11 @@ static int handle_encryptable(const FstabEntry& entry) { return FS_MGR_MNTALL_DEV_NOT_ENCRYPTED; } } else if (should_use_metadata_encryption(entry)) { - if (umount(entry.mount_point.c_str()) == 0) { + if (umount_retry(entry.mount_point)) { return FS_MGR_MNTALL_DEV_NEEDS_METADATA_ENCRYPTION; - } else { - PERROR << "Could not umount " << entry.mount_point << " - fail since can't encrypt"; - return FS_MGR_MNTALL_FAIL; } + PERROR << "Could not umount " << entry.mount_point << " - fail since can't encrypt"; + return FS_MGR_MNTALL_FAIL; } else if (entry.fs_mgr_flags.file_encryption || entry.fs_mgr_flags.force_fde_or_fbe) { LINFO << entry.mount_point << " is file encrypted"; return FS_MGR_MNTALL_DEV_FILE_ENCRYPTED; @@ -1880,9 +1882,13 @@ int fs_mgr_do_mount_one(const FstabEntry& entry, const std::string& alt_mount_po auto& mount_point = alt_mount_point.empty() ? entry.mount_point : alt_mount_point; // Run fsck if needed - prepare_fs_for_mount(entry.blk_device, entry, mount_point); + int ret = prepare_fs_for_mount(entry.blk_device, entry, mount_point); + // Wiped case doesn't require to try __mount below. + if (ret & FS_STAT_INVALID_MAGIC) { + return FS_MGR_DOMNT_FAILED; + } - int ret = __mount(entry.blk_device, mount_point, entry); + ret = __mount(entry.blk_device, mount_point, entry); if (ret) { ret = (errno == EBUSY) ? FS_MGR_DOMNT_BUSY : FS_MGR_DOMNT_FAILED; } diff --git a/fs_mgr/fs_mgr_overlayfs.cpp b/fs_mgr/fs_mgr_overlayfs.cpp index 4d32bda80..cb2f249bb 100644 --- a/fs_mgr/fs_mgr_overlayfs.cpp +++ b/fs_mgr/fs_mgr_overlayfs.cpp @@ -866,9 +866,14 @@ bool fs_mgr_overlayfs_mount_scratch(const std::string& device_path, const std::s errno = save_errno; } entry.flags &= ~MS_RDONLY; + entry.flags |= MS_SYNCHRONOUS; + entry.fs_options = "nodiscard"; fs_mgr_set_blk_ro(device_path, false); } - entry.fs_mgr_flags.check = true; + // check_fs requires apex runtime library + if (fs_mgr_overlayfs_already_mounted("/data", false)) { + entry.fs_mgr_flags.check = true; + } auto save_errno = errno; if (mounted) mounted = fs_mgr_do_mount_one(entry) == 0; if (!mounted) { diff --git a/libcutils/fs_config.cpp b/libcutils/fs_config.cpp index e9497a806..a6835fc70 100644 --- a/libcutils/fs_config.cpp +++ b/libcutils/fs_config.cpp @@ -211,6 +211,7 @@ static const struct fs_path_config android_files[] = { { 00755, AID_ROOT, AID_ROOT, 0, "first_stage_ramdisk/system/bin/resize2fs" }, { 00755, AID_ROOT, AID_ROOT, 0, "first_stage_ramdisk/system/bin/snapuserd" }, { 00755, AID_ROOT, AID_ROOT, 0, "first_stage_ramdisk/system/bin/tune2fs" }, + { 00755, AID_ROOT, AID_ROOT, 0, "first_stage_ramdisk/system/bin/fsck.f2fs" }, // generic defaults { 00755, AID_ROOT, AID_ROOT, 0, "bin/*" }, { 00640, AID_ROOT, AID_SHELL, 0, "fstab.*" }, diff --git a/libprocessgroup/include/processgroup/processgroup.h b/libprocessgroup/include/processgroup/processgroup.h index fa2642d86..50416fa80 100644 --- a/libprocessgroup/include/processgroup/processgroup.h +++ b/libprocessgroup/include/processgroup/processgroup.h @@ -34,6 +34,8 @@ bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector<std::string>& pr #ifndef __ANDROID_VNDK__ +bool SetProcessProfilesCached(uid_t uid, pid_t pid, const std::vector<std::string>& profiles); + static constexpr const char* CGROUPS_RC_PATH = "/dev/cgroup_info/cgroup.rc"; bool UsePerAppMemcg(); diff --git a/libprocessgroup/processgroup.cpp b/libprocessgroup/processgroup.cpp index c824376e5..2ce3fa0c7 100644 --- a/libprocessgroup/processgroup.cpp +++ b/libprocessgroup/processgroup.cpp @@ -112,11 +112,16 @@ static bool isMemoryCgroupSupported() { } void DropTaskProfilesResourceCaching() { - TaskProfiles::GetInstance().DropResourceCaching(); + TaskProfiles::GetInstance().DropResourceCaching(ProfileAction::RCT_TASK); + TaskProfiles::GetInstance().DropResourceCaching(ProfileAction::RCT_PROCESS); } bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector<std::string>& profiles) { - return TaskProfiles::GetInstance().SetProcessProfiles(uid, pid, profiles); + return TaskProfiles::GetInstance().SetProcessProfiles(uid, pid, profiles, false); +} + +bool SetProcessProfilesCached(uid_t uid, pid_t pid, const std::vector<std::string>& profiles) { + return TaskProfiles::GetInstance().SetProcessProfiles(uid, pid, profiles, true); } bool SetTaskProfiles(int tid, const std::vector<std::string>& profiles, bool use_fd_cache) { diff --git a/libprocessgroup/task_profiles.cpp b/libprocessgroup/task_profiles.cpp index 3834f9194..74ba7f61a 100644 --- a/libprocessgroup/task_profiles.cpp +++ b/libprocessgroup/task_profiles.cpp @@ -51,6 +51,67 @@ static constexpr const char* TASK_PROFILE_DB_VENDOR_FILE = "/vendor/etc/task_pro static constexpr const char* TEMPLATE_TASK_PROFILE_API_FILE = "/etc/task_profiles/task_profiles_%u.json"; +class FdCacheHelper { + public: + enum FdState { + FDS_INACCESSIBLE = -1, + FDS_APP_DEPENDENT = -2, + FDS_NOT_CACHED = -3, + }; + + static void Cache(const std::string& path, android::base::unique_fd& fd); + static void Drop(android::base::unique_fd& fd); + static void Init(const std::string& path, android::base::unique_fd& fd); + static bool IsCached(const android::base::unique_fd& fd) { return fd > FDS_INACCESSIBLE; } + + private: + static bool IsAppDependentPath(const std::string& path); +}; + +void FdCacheHelper::Init(const std::string& path, android::base::unique_fd& fd) { + // file descriptors for app-dependent paths can't be cached + if (IsAppDependentPath(path)) { + // file descriptor is not cached + fd.reset(FDS_APP_DEPENDENT); + return; + } + // file descriptor can be cached later on request + fd.reset(FDS_NOT_CACHED); +} + +void FdCacheHelper::Cache(const std::string& path, android::base::unique_fd& fd) { + if (fd != FDS_NOT_CACHED) { + return; + } + + if (access(path.c_str(), W_OK) != 0) { + // file is not accessible + fd.reset(FDS_INACCESSIBLE); + return; + } + + unique_fd tmp_fd(TEMP_FAILURE_RETRY(open(path.c_str(), O_WRONLY | O_CLOEXEC))); + if (tmp_fd < 0) { + PLOG(ERROR) << "Failed to cache fd '" << path << "'"; + fd.reset(FDS_INACCESSIBLE); + return; + } + + fd = std::move(tmp_fd); +} + +void FdCacheHelper::Drop(android::base::unique_fd& fd) { + if (fd == FDS_NOT_CACHED) { + return; + } + + fd.reset(FDS_NOT_CACHED); +} + +bool FdCacheHelper::IsAppDependentPath(const std::string& path) { + return path.find("<uid>", 0) != std::string::npos || path.find("<pid>", 0) != std::string::npos; +} + void ProfileAttribute::Reset(const CgroupController& controller, const std::string& file_name) { controller_ = controller; file_name_ = file_name; @@ -144,57 +205,11 @@ bool SetAttributeAction::ExecuteForTask(int tid) const { return true; } -void CachedFdProfileAction::EnableResourceCaching() { - std::lock_guard<std::mutex> lock(fd_mutex_); - if (fd_ != FDS_NOT_CACHED) { - return; - } - - std::string tasks_path = GetPath(); - - if (access(tasks_path.c_str(), W_OK) != 0) { - // file is not accessible - fd_.reset(FDS_INACCESSIBLE); - return; - } - - unique_fd fd(TEMP_FAILURE_RETRY(open(tasks_path.c_str(), O_WRONLY | O_CLOEXEC))); - if (fd < 0) { - PLOG(ERROR) << "Failed to cache fd '" << tasks_path << "'"; - fd_.reset(FDS_INACCESSIBLE); - return; - } - - fd_ = std::move(fd); -} - -void CachedFdProfileAction::DropResourceCaching() { - std::lock_guard<std::mutex> lock(fd_mutex_); - if (fd_ == FDS_NOT_CACHED) { - return; - } - - fd_.reset(FDS_NOT_CACHED); -} - -bool CachedFdProfileAction::IsAppDependentPath(const std::string& path) { - return path.find("<uid>", 0) != std::string::npos || path.find("<pid>", 0) != std::string::npos; -} - -void CachedFdProfileAction::InitFd(const std::string& path) { - // file descriptors for app-dependent paths can't be cached - if (IsAppDependentPath(path)) { - // file descriptor is not cached - fd_.reset(FDS_APP_DEPENDENT); - return; - } - // file descriptor can be cached later on request - fd_.reset(FDS_NOT_CACHED); -} - SetCgroupAction::SetCgroupAction(const CgroupController& c, const std::string& p) : controller_(c), path_(p) { - InitFd(controller_.GetTasksFilePath(path_)); + FdCacheHelper::Init(controller_.GetTasksFilePath(path_), fd_[ProfileAction::RCT_TASK]); + // uid and pid don't matter because IsAppDependentPath ensures the path doesn't use them + FdCacheHelper::Init(controller_.GetProcsFilePath(path_, 0, 0), fd_[ProfileAction::RCT_PROCESS]); } bool SetCgroupAction::AddTidToCgroup(int tid, int fd, const char* controller_name) { @@ -232,7 +247,40 @@ bool SetCgroupAction::AddTidToCgroup(int tid, int fd, const char* controller_nam return false; } +ProfileAction::CacheUseResult SetCgroupAction::UseCachedFd(ResourceCacheType cache_type, + int id) const { + std::lock_guard<std::mutex> lock(fd_mutex_); + if (FdCacheHelper::IsCached(fd_[cache_type])) { + // fd is cached, reuse it + if (!AddTidToCgroup(id, fd_[cache_type], controller()->name())) { + LOG(ERROR) << "Failed to add task into cgroup"; + return ProfileAction::FAIL; + } + return ProfileAction::SUCCESS; + } + + if (fd_[cache_type] == FdCacheHelper::FDS_INACCESSIBLE) { + // no permissions to access the file, ignore + return ProfileAction::SUCCESS; + } + + if (cache_type == ResourceCacheType::RCT_TASK && + fd_[cache_type] == FdCacheHelper::FDS_APP_DEPENDENT) { + // application-dependent path can't be used with tid + PLOG(ERROR) << "Application profile can't be applied to a thread"; + return ProfileAction::FAIL; + } + + return ProfileAction::UNUSED; +} + bool SetCgroupAction::ExecuteForProcess(uid_t uid, pid_t pid) const { + CacheUseResult result = UseCachedFd(ProfileAction::RCT_PROCESS, pid); + if (result != ProfileAction::UNUSED) { + return result == ProfileAction::SUCCESS; + } + + // fd was not cached or cached fd can't be used std::string procs_path = controller()->GetProcsFilePath(path_, uid, pid); unique_fd tmp_fd(TEMP_FAILURE_RETRY(open(procs_path.c_str(), O_WRONLY | O_CLOEXEC))); if (tmp_fd < 0) { @@ -248,28 +296,12 @@ bool SetCgroupAction::ExecuteForProcess(uid_t uid, pid_t pid) const { } bool SetCgroupAction::ExecuteForTask(int tid) const { - std::lock_guard<std::mutex> lock(fd_mutex_); - if (IsFdValid()) { - // fd is cached, reuse it - if (!AddTidToCgroup(tid, fd_, controller()->name())) { - LOG(ERROR) << "Failed to add task into cgroup"; - return false; - } - return true; - } - - if (fd_ == FDS_INACCESSIBLE) { - // no permissions to access the file, ignore - return true; + CacheUseResult result = UseCachedFd(ProfileAction::RCT_TASK, tid); + if (result != ProfileAction::UNUSED) { + return result == ProfileAction::SUCCESS; } - if (fd_ == FDS_APP_DEPENDENT) { - // application-dependent path can't be used with tid - PLOG(ERROR) << "Application profile can't be applied to a thread"; - return false; - } - - // fd was not cached because cached fd can't be used + // fd was not cached or cached fd can't be used std::string tasks_path = controller()->GetTasksFilePath(path_); unique_fd tmp_fd(TEMP_FAILURE_RETRY(open(tasks_path.c_str(), O_WRONLY | O_CLOEXEC))); if (tmp_fd < 0) { @@ -284,10 +316,36 @@ bool SetCgroupAction::ExecuteForTask(int tid) const { return true; } +void SetCgroupAction::EnableResourceCaching(ResourceCacheType cache_type) { + std::lock_guard<std::mutex> lock(fd_mutex_); + // Return early to prevent unnecessary calls to controller_.Get{Tasks|Procs}FilePath() which + // include regex evaluations + if (fd_[cache_type] != FdCacheHelper::FDS_NOT_CACHED) { + return; + } + switch (cache_type) { + case (ProfileAction::RCT_TASK): + FdCacheHelper::Cache(controller_.GetTasksFilePath(path_), fd_[cache_type]); + break; + case (ProfileAction::RCT_PROCESS): + // uid and pid don't matter because IsAppDependentPath ensures the path doesn't use them + FdCacheHelper::Cache(controller_.GetProcsFilePath(path_, 0, 0), fd_[cache_type]); + break; + default: + LOG(ERROR) << "Invalid cache type is specified!"; + break; + } +} + +void SetCgroupAction::DropResourceCaching(ResourceCacheType cache_type) { + std::lock_guard<std::mutex> lock(fd_mutex_); + FdCacheHelper::Drop(fd_[cache_type]); +} + WriteFileAction::WriteFileAction(const std::string& path, const std::string& value, bool logfailures) : path_(path), value_(value), logfailures_(logfailures) { - InitFd(path_); + FdCacheHelper::Init(path_, fd_); } bool WriteFileAction::WriteValueToFile(const std::string& value, const std::string& path, @@ -309,13 +367,43 @@ bool WriteFileAction::WriteValueToFile(const std::string& value, const std::stri return true; } -bool WriteFileAction::ExecuteForProcess(uid_t uid, pid_t pid) const { +ProfileAction::CacheUseResult WriteFileAction::UseCachedFd(ResourceCacheType cache_type, + const std::string& value) const { std::lock_guard<std::mutex> lock(fd_mutex_); + if (FdCacheHelper::IsCached(fd_)) { + // fd is cached, reuse it + if (!WriteStringToFd(value, fd_)) { + if (logfailures_) PLOG(ERROR) << "Failed to write '" << value << "' to " << path_; + return ProfileAction::FAIL; + } + return ProfileAction::SUCCESS; + } + + if (fd_ == FdCacheHelper::FDS_INACCESSIBLE) { + // no permissions to access the file, ignore + return ProfileAction::SUCCESS; + } + + if (cache_type == ResourceCacheType::RCT_TASK && fd_ == FdCacheHelper::FDS_APP_DEPENDENT) { + // application-dependent path can't be used with tid + PLOG(ERROR) << "Application profile can't be applied to a thread"; + return ProfileAction::FAIL; + } + return ProfileAction::UNUSED; +} + +bool WriteFileAction::ExecuteForProcess(uid_t uid, pid_t pid) const { std::string value(value_); - std::string path(path_); value = StringReplace(value, "<uid>", std::to_string(uid), true); value = StringReplace(value, "<pid>", std::to_string(pid), true); + + CacheUseResult result = UseCachedFd(ProfileAction::RCT_PROCESS, value); + if (result != ProfileAction::UNUSED) { + return result == ProfileAction::SUCCESS; + } + + std::string path(path_); path = StringReplace(path, "<uid>", std::to_string(uid), true); path = StringReplace(path, "<pid>", std::to_string(pid), true); @@ -323,41 +411,33 @@ bool WriteFileAction::ExecuteForProcess(uid_t uid, pid_t pid) const { } bool WriteFileAction::ExecuteForTask(int tid) const { - std::lock_guard<std::mutex> lock(fd_mutex_); std::string value(value_); int uid = getuid(); value = StringReplace(value, "<uid>", std::to_string(uid), true); value = StringReplace(value, "<pid>", std::to_string(tid), true); - if (IsFdValid()) { - // fd is cached, reuse it - if (!WriteStringToFd(value, fd_)) { - if (logfailures_) PLOG(ERROR) << "Failed to write '" << value << "' to " << path_; - return false; - } - return true; + CacheUseResult result = UseCachedFd(ProfileAction::RCT_TASK, value); + if (result != ProfileAction::UNUSED) { + return result == ProfileAction::SUCCESS; } - if (fd_ == FDS_INACCESSIBLE) { - // no permissions to access the file, ignore - return true; - } + return WriteValueToFile(value, path_, logfailures_); +} - if (fd_ == FDS_APP_DEPENDENT) { - // application-dependent path can't be used with tid - PLOG(ERROR) << "Application profile can't be applied to a thread"; - return false; - } +void WriteFileAction::EnableResourceCaching(ResourceCacheType) { + std::lock_guard<std::mutex> lock(fd_mutex_); + FdCacheHelper::Cache(path_, fd_); +} - return WriteValueToFile(value, path_, logfailures_); +void WriteFileAction::DropResourceCaching(ResourceCacheType) { + std::lock_guard<std::mutex> lock(fd_mutex_); + FdCacheHelper::Drop(fd_); } bool ApplyProfileAction::ExecuteForProcess(uid_t uid, pid_t pid) const { for (const auto& profile : profiles_) { - if (!profile->ExecuteForProcess(uid, pid)) { - PLOG(WARNING) << "ExecuteForProcess failed for aggregate profile"; - } + profile->ExecuteForProcess(uid, pid); } return true; } @@ -369,15 +449,15 @@ bool ApplyProfileAction::ExecuteForTask(int tid) const { return true; } -void ApplyProfileAction::EnableResourceCaching() { +void ApplyProfileAction::EnableResourceCaching(ResourceCacheType cache_type) { for (const auto& profile : profiles_) { - profile->EnableResourceCaching(); + profile->EnableResourceCaching(cache_type); } } -void ApplyProfileAction::DropResourceCaching() { +void ApplyProfileAction::DropResourceCaching(ResourceCacheType cache_type) { for (const auto& profile : profiles_) { - profile->DropResourceCaching(); + profile->DropResourceCaching(cache_type); } } @@ -407,33 +487,33 @@ bool TaskProfile::ExecuteForTask(int tid) const { return true; } -void TaskProfile::EnableResourceCaching() { +void TaskProfile::EnableResourceCaching(ProfileAction::ResourceCacheType cache_type) { if (res_cached_) { return; } for (auto& element : elements_) { - element->EnableResourceCaching(); + element->EnableResourceCaching(cache_type); } res_cached_ = true; } -void TaskProfile::DropResourceCaching() { +void TaskProfile::DropResourceCaching(ProfileAction::ResourceCacheType cache_type) { if (!res_cached_) { return; } for (auto& element : elements_) { - element->DropResourceCaching(); + element->DropResourceCaching(cache_type); } res_cached_ = false; } -void TaskProfiles::DropResourceCaching() const { +void TaskProfiles::DropResourceCaching(ProfileAction::ResourceCacheType cache_type) const { for (auto& iter : profiles_) { - iter.second->DropResourceCaching(); + iter.second->DropResourceCaching(cache_type); } } @@ -457,8 +537,7 @@ TaskProfiles::TaskProfiles() { android::base::StringPrintf(TEMPLATE_TASK_PROFILE_API_FILE, api_level); if (!access(api_profiles_path.c_str(), F_OK) || errno != ENOENT) { if (!Load(CgroupMap::GetInstance(), api_profiles_path)) { - LOG(ERROR) << "Loading " << api_profiles_path << " for [" << getpid() - << "] failed"; + LOG(ERROR) << "Loading " << api_profiles_path << " for [" << getpid() << "] failed"; } } } @@ -651,10 +730,13 @@ const ProfileAttribute* TaskProfiles::GetAttribute(const std::string& name) cons } bool TaskProfiles::SetProcessProfiles(uid_t uid, pid_t pid, - const std::vector<std::string>& profiles) { + const std::vector<std::string>& profiles, bool use_fd_cache) { for (const auto& name : profiles) { TaskProfile* profile = GetProfile(name); if (profile != nullptr) { + if (use_fd_cache) { + profile->EnableResourceCaching(ProfileAction::RCT_PROCESS); + } if (!profile->ExecuteForProcess(uid, pid)) { PLOG(WARNING) << "Failed to apply " << name << " process profile"; } @@ -671,7 +753,7 @@ bool TaskProfiles::SetTaskProfiles(int tid, const std::vector<std::string>& prof TaskProfile* profile = GetProfile(name); if (profile != nullptr) { if (use_fd_cache) { - profile->EnableResourceCaching(); + profile->EnableResourceCaching(ProfileAction::RCT_TASK); } if (!profile->ExecuteForTask(tid)) { PLOG(WARNING) << "Failed to apply " << name << " task profile"; diff --git a/libprocessgroup/task_profiles.h b/libprocessgroup/task_profiles.h index 278892dd5..1aaa196ba 100644 --- a/libprocessgroup/task_profiles.h +++ b/libprocessgroup/task_profiles.h @@ -45,14 +45,19 @@ class ProfileAttribute { // Abstract profile element class ProfileAction { public: + enum ResourceCacheType { RCT_TASK = 0, RCT_PROCESS, RCT_COUNT }; + virtual ~ProfileAction() {} // Default implementations will fail virtual bool ExecuteForProcess(uid_t, pid_t) const { return false; }; virtual bool ExecuteForTask(int) const { return false; }; - virtual void EnableResourceCaching() {} - virtual void DropResourceCaching() {} + virtual void EnableResourceCaching(ResourceCacheType) {} + virtual void DropResourceCaching(ResourceCacheType) {} + + protected: + enum CacheUseResult { SUCCESS, FAIL, UNUSED }; }; // Profile actions @@ -108,67 +113,47 @@ class SetAttributeAction : public ProfileAction { std::string value_; }; -// Abstract profile element for cached fd -class CachedFdProfileAction : public ProfileAction { - public: - virtual void EnableResourceCaching(); - virtual void DropResourceCaching(); - - protected: - enum FdState { - FDS_INACCESSIBLE = -1, - FDS_APP_DEPENDENT = -2, - FDS_NOT_CACHED = -3, - }; - - android::base::unique_fd fd_; - mutable std::mutex fd_mutex_; - - static bool IsAppDependentPath(const std::string& path); - - void InitFd(const std::string& path); - bool IsFdValid() const { return fd_ > FDS_INACCESSIBLE; } - - virtual const std::string GetPath() const = 0; -}; - // Set cgroup profile element -class SetCgroupAction : public CachedFdProfileAction { +class SetCgroupAction : public ProfileAction { public: SetCgroupAction(const CgroupController& c, const std::string& p); virtual bool ExecuteForProcess(uid_t uid, pid_t pid) const; virtual bool ExecuteForTask(int tid) const; + virtual void EnableResourceCaching(ResourceCacheType cache_type); + virtual void DropResourceCaching(ResourceCacheType cache_type); const CgroupController* controller() const { return &controller_; } - protected: - const std::string GetPath() const override { return controller_.GetTasksFilePath(path_); } - private: CgroupController controller_; std::string path_; + android::base::unique_fd fd_[ProfileAction::RCT_COUNT]; + mutable std::mutex fd_mutex_; static bool AddTidToCgroup(int tid, int fd, const char* controller_name); + CacheUseResult UseCachedFd(ResourceCacheType cache_type, int id) const; }; // Write to file action -class WriteFileAction : public CachedFdProfileAction { +class WriteFileAction : public ProfileAction { public: WriteFileAction(const std::string& path, const std::string& value, bool logfailures); virtual bool ExecuteForProcess(uid_t uid, pid_t pid) const; virtual bool ExecuteForTask(int tid) const; - - protected: - const std::string GetPath() const override { return path_; } + virtual void EnableResourceCaching(ResourceCacheType cache_type); + virtual void DropResourceCaching(ResourceCacheType cache_type); private: std::string path_, value_; bool logfailures_; + android::base::unique_fd fd_; + mutable std::mutex fd_mutex_; static bool WriteValueToFile(const std::string& value, const std::string& path, bool logfailures); + CacheUseResult UseCachedFd(ResourceCacheType cache_type, const std::string& value) const; }; class TaskProfile { @@ -180,8 +165,8 @@ class TaskProfile { bool ExecuteForProcess(uid_t uid, pid_t pid) const; bool ExecuteForTask(int tid) const; - void EnableResourceCaching(); - void DropResourceCaching(); + void EnableResourceCaching(ProfileAction::ResourceCacheType cache_type); + void DropResourceCaching(ProfileAction::ResourceCacheType cache_type); private: bool res_cached_; @@ -196,8 +181,8 @@ class ApplyProfileAction : public ProfileAction { virtual bool ExecuteForProcess(uid_t uid, pid_t pid) const; virtual bool ExecuteForTask(int tid) const; - virtual void EnableResourceCaching(); - virtual void DropResourceCaching(); + virtual void EnableResourceCaching(ProfileAction::ResourceCacheType cache_type); + virtual void DropResourceCaching(ProfileAction::ResourceCacheType cache_type); private: std::vector<std::shared_ptr<TaskProfile>> profiles_; @@ -210,8 +195,9 @@ class TaskProfiles { TaskProfile* GetProfile(const std::string& name) const; const ProfileAttribute* GetAttribute(const std::string& name) const; - void DropResourceCaching() const; - bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector<std::string>& profiles); + void DropResourceCaching(ProfileAction::ResourceCacheType cache_type) const; + bool SetProcessProfiles(uid_t uid, pid_t pid, const std::vector<std::string>& profiles, + bool use_fd_cache); bool SetTaskProfiles(int tid, const std::vector<std::string>& profiles, bool use_fd_cache); private: diff --git a/rootdir/init.rc b/rootdir/init.rc index 5116c0fea..8a385595e 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -142,11 +142,21 @@ on init chown system system /dev/stune/background/tasks chown system system /dev/stune/top-app/tasks chown system system /dev/stune/rt/tasks + chown system system /dev/stune/cgroup.procs + chown system system /dev/stune/foreground/cgroup.procs + chown system system /dev/stune/background/cgroup.procs + chown system system /dev/stune/top-app/cgroup.procs + chown system system /dev/stune/rt/cgroup.procs chmod 0664 /dev/stune/tasks chmod 0664 /dev/stune/foreground/tasks chmod 0664 /dev/stune/background/tasks chmod 0664 /dev/stune/top-app/tasks chmod 0664 /dev/stune/rt/tasks + chmod 0664 /dev/stune/cgroup.procs + chmod 0664 /dev/stune/foreground/cgroup.procs + chmod 0664 /dev/stune/background/cgroup.procs + chmod 0664 /dev/stune/top-app/cgroup.procs + chmod 0664 /dev/stune/rt/cgroup.procs # cpuctl hierarchy for devices using utilclamp mkdir /dev/cpuctl/foreground @@ -172,6 +182,14 @@ on init chown system system /dev/cpuctl/system/tasks chown system system /dev/cpuctl/system-background/tasks chown system system /dev/cpuctl/dex2oat/tasks + chown system system /dev/cpuctl/cgroup.procs + chown system system /dev/cpuctl/foreground/cgroup.procs + chown system system /dev/cpuctl/background/cgroup.procs + chown system system /dev/cpuctl/top-app/cgroup.procs + chown system system /dev/cpuctl/rt/cgroup.procs + chown system system /dev/cpuctl/system/cgroup.procs + chown system system /dev/cpuctl/system-background/cgroup.procs + chown system system /dev/cpuctl/dex2oat/cgroup.procs chmod 0664 /dev/cpuctl/tasks chmod 0664 /dev/cpuctl/foreground/tasks chmod 0664 /dev/cpuctl/background/tasks @@ -180,12 +198,22 @@ on init chmod 0664 /dev/cpuctl/system/tasks chmod 0664 /dev/cpuctl/system-background/tasks chmod 0664 /dev/cpuctl/dex2oat/tasks + chmod 0664 /dev/cpuctl/cgroup.procs + chmod 0664 /dev/cpuctl/foreground/cgroup.procs + chmod 0664 /dev/cpuctl/background/cgroup.procs + chmod 0664 /dev/cpuctl/top-app/cgroup.procs + chmod 0664 /dev/cpuctl/rt/cgroup.procs + chmod 0664 /dev/cpuctl/system/cgroup.procs + chmod 0664 /dev/cpuctl/system-background/cgroup.procs + chmod 0664 /dev/cpuctl/dex2oat/cgroup.procs # Create a cpu group for NNAPI HAL processes mkdir /dev/cpuctl/nnapi-hal chown system system /dev/cpuctl/nnapi-hal chown system system /dev/cpuctl/nnapi-hal/tasks + chown system system /dev/cpuctl/nnapi-hal/cgroup.procs chmod 0664 /dev/cpuctl/nnapi-hal/tasks + chmod 0664 /dev/cpuctl/nnapi-hal/cgroup.procs write /dev/cpuctl/nnapi-hal/cpu.uclamp.min 1 write /dev/cpuctl/nnapi-hal/cpu.uclamp.latency_sensitive 1 @@ -193,19 +221,25 @@ on init mkdir /dev/cpuctl/camera-daemon chown system system /dev/cpuctl/camera-daemon chown system system /dev/cpuctl/camera-daemon/tasks + chown system system /dev/cpuctl/camera-daemon/cgroup.procs chmod 0664 /dev/cpuctl/camera-daemon/tasks + chmod 0664 /dev/cpuctl/camera-daemon/cgroup.procs # Create an stune group for camera-specific processes mkdir /dev/stune/camera-daemon chown system system /dev/stune/camera-daemon chown system system /dev/stune/camera-daemon/tasks + chown system system /dev/stune/camera-daemon/cgroup.procs chmod 0664 /dev/stune/camera-daemon/tasks + chmod 0664 /dev/stune/camera-daemon/cgroup.procs # Create an stune group for NNAPI HAL processes mkdir /dev/stune/nnapi-hal chown system system /dev/stune/nnapi-hal chown system system /dev/stune/nnapi-hal/tasks + chown system system /dev/stune/nnapi-hal/cgroup.procs chmod 0664 /dev/stune/nnapi-hal/tasks + chmod 0664 /dev/stune/nnapi-hal/cgroup.procs write /dev/stune/nnapi-hal/schedtune.boost 1 write /dev/stune/nnapi-hal/schedtune.prefer_idle 1 @@ -217,8 +251,12 @@ on init chown system system /dev/blkio/background chown system system /dev/blkio/tasks chown system system /dev/blkio/background/tasks + chown system system /dev/blkio/cgroup.procs + chown system system /dev/blkio/background/cgroup.procs chmod 0664 /dev/blkio/tasks chmod 0664 /dev/blkio/background/tasks + chmod 0664 /dev/blkio/cgroup.procs + chmod 0664 /dev/blkio/background/cgroup.procs write /dev/blkio/blkio.weight 1000 write /dev/blkio/background/blkio.weight 200 write /dev/blkio/background/blkio.bfq.weight 10 @@ -367,6 +405,13 @@ on init chown system system /dev/cpuset/top-app/tasks chown system system /dev/cpuset/restricted/tasks chown system system /dev/cpuset/camera-daemon/tasks + chown system system /dev/cpuset/cgroup.procs + chown system system /dev/cpuset/foreground/cgroup.procs + chown system system /dev/cpuset/background/cgroup.procs + chown system system /dev/cpuset/system-background/cgroup.procs + chown system system /dev/cpuset/top-app/cgroup.procs + chown system system /dev/cpuset/restricted/cgroup.procs + chown system system /dev/cpuset/camera-daemon/cgroup.procs # set system-background to 0775 so SurfaceFlinger can touch it chmod 0775 /dev/cpuset/system-background @@ -378,6 +423,13 @@ on init chmod 0664 /dev/cpuset/restricted/tasks chmod 0664 /dev/cpuset/tasks chmod 0664 /dev/cpuset/camera-daemon/tasks + chmod 0664 /dev/cpuset/foreground/cgroup.procs + chmod 0664 /dev/cpuset/background/cgroup.procs + chmod 0664 /dev/cpuset/system-background/cgroup.procs + chmod 0664 /dev/cpuset/top-app/cgroup.procs + chmod 0664 /dev/cpuset/restricted/cgroup.procs + chmod 0664 /dev/cpuset/cgroup.procs + chmod 0664 /dev/cpuset/camera-daemon/cgroup.procs # make the PSI monitor accessible to others chown system system /proc/pressure/memory diff --git a/trusty/storage/proxy/Android.bp b/trusty/storage/proxy/Android.bp index 38d868508..94f26d8a6 100644 --- a/trusty/storage/proxy/Android.bp +++ b/trusty/storage/proxy/Android.bp @@ -35,7 +35,10 @@ cc_binary { "liblog", "libhardware_legacy", ], - header_libs: ["libcutils_headers"], + header_libs: [ + "libcutils_headers", + "libgsi_headers", + ], static_libs: [ "libfstab", diff --git a/trusty/storage/proxy/checkpoint_handling.cpp b/trusty/storage/proxy/checkpoint_handling.cpp index 6c2fd363e..3305d8da2 100644 --- a/trusty/storage/proxy/checkpoint_handling.cpp +++ b/trusty/storage/proxy/checkpoint_handling.cpp @@ -18,9 +18,12 @@ #include "log.h" #include <fstab/fstab.h> +#include <unistd.h> #include <cstring> #include <string> +#include <libgsi/libgsi.h> + namespace { bool checkpointingDoneForever = false; @@ -75,3 +78,15 @@ int is_data_checkpoint_active(bool* active) { return 0; } + +/** + * is_gsi_running() - Check if a GSI image is running via DSU. + * + * This function is equivalent to android::gsi::IsGsiRunning(), but this API is + * not yet vendor-accessible although the underlying metadata file is. + * + */ +bool is_gsi_running() { + /* TODO(b/210501710): Expose GSI image running state to vendor storageproxyd */ + return !access(android::gsi::kGsiBootedIndicatorFile, F_OK); +} diff --git a/trusty/storage/proxy/checkpoint_handling.h b/trusty/storage/proxy/checkpoint_handling.h index f1bf27c8d..dfe294778 100644 --- a/trusty/storage/proxy/checkpoint_handling.h +++ b/trusty/storage/proxy/checkpoint_handling.h @@ -32,6 +32,8 @@ extern "C" { */ int is_data_checkpoint_active(bool* active); +bool is_gsi_running(); + #ifdef __cplusplus } #endif diff --git a/trusty/storage/proxy/proxy.c b/trusty/storage/proxy/proxy.c index c690a2876..262003427 100644 --- a/trusty/storage/proxy/proxy.c +++ b/trusty/storage/proxy/proxy.c @@ -104,8 +104,11 @@ static int drop_privs(void) { return -1; } - /* no-execute for user, no access for group and other */ - umask(S_IXUSR | S_IRWXG | S_IRWXO); + /* + * No access for group and other. We need execute access for user to create + * an accessible directory. + */ + umask(S_IRWXG | S_IRWXO); return 0; } diff --git a/trusty/storage/proxy/storage.c b/trusty/storage/proxy/storage.c index 2fde30f84..d74a70807 100644 --- a/trusty/storage/proxy/storage.c +++ b/trusty/storage/proxy/storage.c @@ -16,6 +16,7 @@ #include <errno.h> #include <fcntl.h> #include <inttypes.h> +#include <libgen.h> #include <stdbool.h> #include <stdlib.h> #include <string.h> @@ -24,13 +25,16 @@ #include <sys/types.h> #include <unistd.h> -#include "log.h" +#include "checkpoint_handling.h" #include "ipc.h" +#include "log.h" #include "storage.h" #define FD_TBL_SIZE 64 #define MAX_READ_SIZE 4096 +#define ALTERNATE_DATA_DIR "alternate/" + enum sync_state { SS_UNUSED = -1, SS_CLEAN = 0, @@ -44,6 +48,8 @@ static enum sync_state fs_state; static enum sync_state dir_state; static enum sync_state fd_state[FD_TBL_SIZE]; +static bool alternate_mode; + static struct { struct storage_file_read_resp hdr; uint8_t data[MAX_READ_SIZE]; @@ -216,6 +222,7 @@ int storage_file_open(struct storage_msg *msg, const void *r, size_t req_len) { char *path = NULL; + char* parent_path; const struct storage_file_open_req *req = r; struct storage_file_open_resp resp = {0}; @@ -234,6 +241,24 @@ int storage_file_open(struct storage_msg *msg, goto err_response; } + /* + * TODO(b/210501710): Expose GSI image running state to vendor + * storageproxyd. We want to control data file paths in vendor_init, but we + * don't have access to the necessary property there yet. When we have + * access to that property we can set the root data path read-only and only + * allow creation of files in alternate/. Checking paths here temporarily + * until that is fixed. + * + * We are just checking for "/" instead of "alternate/" because we still + * want to still allow access to "persist/" in alternate mode (for now, this + * may change in the future). + */ + if (alternate_mode && !strchr(req->name, '/')) { + ALOGE("%s: Cannot open root data file \"%s\" in alternate mode\n", __func__, req->name); + msg->result = STORAGE_ERR_ACCESS; + goto err_response; + } + int rc = asprintf(&path, "%s/%s", ssdir_name, req->name); if (rc < 0) { ALOGE("%s: asprintf failed\n", __func__); @@ -246,7 +271,23 @@ int storage_file_open(struct storage_msg *msg, if (req->flags & STORAGE_FILE_OPEN_TRUNCATE) open_flags |= O_TRUNC; + parent_path = dirname(path); if (req->flags & STORAGE_FILE_OPEN_CREATE) { + /* + * Create the alternate parent dir if needed & allowed. + * + * TODO(b/210501710): Expose GSI image running state to vendor + * storageproxyd. This directory should be created by vendor_init, once + * it has access to the necessary bit of information. + */ + if (strstr(req->name, ALTERNATE_DATA_DIR) == req->name) { + rc = mkdir(parent_path, S_IRWXU); + if (rc && errno != EEXIST) { + ALOGE("%s: Could not create parent directory \"%s\": %s\n", __func__, parent_path, + strerror(errno)); + } + } + /* open or create */ if (req->flags & STORAGE_FILE_OPEN_CREATE_EXCLUSIVE) { /* create exclusive */ @@ -467,6 +508,9 @@ err_response: int storage_init(const char *dirname) { + /* If there is an active DSU image, use the alternate fs mode. */ + alternate_mode = is_gsi_running(); + fs_state = SS_CLEAN; dir_state = SS_CLEAN; for (uint i = 0; i < FD_TBL_SIZE; i++) { |