diff options
author | Konrad Lipinski <k.lipinski2@samsung.com> | 2022-07-26 12:52:49 +0200 |
---|---|---|
committer | Konrad Lipinski <k.lipinski2@samsung.com> | 2022-08-04 16:05:58 +0200 |
commit | acd9399f569c69a8e8c4d07eef48483ea08a801b (patch) | |
tree | a3c87bbe62a242d930616180ac8c1248d4857dc2 | |
parent | a1178be84298b594b487c68cae215dc58e3609b5 (diff) | |
download | security-manager-acd9399f569c69a8e8c4d07eef48483ea08a801b.tar.gz security-manager-acd9399f569c69a8e8c4d07eef48483ea08a801b.tar.bz2 security-manager-acd9399f569c69a8e8c4d07eef48483ea08a801b.zip |
Add subsession bind mount isolation
By introducing prepare_app2(app_id, subsession_id) and implementing
prepare_app(app_id) as prepare_app2(app_id, nullptr). Null subsession_id
indicates the default subsession.
The selected subsession is mounted over the "apps_rw" directory. Other
subsessions are hidden by mounting an empty directory over the user's
"subsession" directory if it exists.
Change-Id: I19c884bdd64c53b82fef3447470378c8a8cfae3e
-rw-r--r-- | src/client/client-security-manager.cpp | 45 | ||||
-rw-r--r-- | src/common/include/config.h | 4 | ||||
-rw-r--r-- | src/common/include/mount-namespace.h | 3 | ||||
-rw-r--r-- | src/common/mount-namespace.cpp | 27 | ||||
-rw-r--r-- | src/include/app-runtime.h | 18 |
5 files changed, 86 insertions, 11 deletions
diff --git a/src/client/client-security-manager.cpp b/src/client/client-security-manager.cpp index 2ba22b79..ff9f7da1 100644 --- a/src/client/client-security-manager.cpp +++ b/src/client/client-security-manager.cpp @@ -819,6 +819,24 @@ int security_manager_drop_process_privileges(void) return SECURITY_MANAGER_SUCCESS; } +static int setupSubsession(TizenPlatformConfig &tpc, const std::string &userAppsRWDir, + const char *subsession_id) +{ + const auto subsessionsDir = tpc.ctxGetEnv(TZ_USER_HOME).append("/subsession/"); + + if (subsession_id) { + // bind the subsession over the main dir + const auto ret = MountNS::bindMountRW(subsessionsDir + subsession_id + "/apps_rw", userAppsRWDir); + if (ret != SECURITY_MANAGER_SUCCESS) + return ret; + // hide all subsessions + return MountNS::bindMountRO(EMPTY_DIRECTORY, subsessionsDir); + } + + // hide all subsessions if subsessionsDir exists + return MountNS::bindMountROIfExists(EMPTY_DIRECTORY, subsessionsDir); +} + static int setupSharedRO(const std::string &pkg_name, bool enabledSharedRO, const std::string &userAppsRWDir, const std::string &userAppsRWSharedDir) { @@ -910,18 +928,25 @@ int security_manager_prepare_app_candidate(void) static inline int security_manager_setup_namespace_internal(const MountNS::PrivilegePathsMap &privilegePathMap, const std::string &pkg_name, bool enabledSharedRO, const std::vector<bool> &privPathsStatusVector, - const std::string &app_label) + const std::string &app_label, const char *subsession_id) { // mount namespace setup was made by other process when userAppsRWSharedDir is read only, we can skip it TizenPlatformConfig tpc(geteuid()); std::string userAppsRWDir = tpc.ctxGetEnv(TZ_USER_APP); + + int ret = setupSubsession(tpc, userAppsRWDir, subsession_id); + if (ret != SECURITY_MANAGER_SUCCESS) { + LogError("Failed to setup subsession: " << security_manager_strerror(static_cast<lib_retcode>(ret))); + return ret; + } + std::string userAppsRWSharedDir = userAppsRWDir + "/.shared/"; if (FS::directoryStatus(userAppsRWSharedDir) > 0 && access(userAppsRWSharedDir.c_str(), W_OK) == -1) { LogDebug("Mount namespace setup was made by other process of multi-process app zygote"); return SECURITY_MANAGER_SUCCESS; } - int ret = setupSharedRO(pkg_name, enabledSharedRO, userAppsRWDir, userAppsRWSharedDir); + ret = setupSharedRO(pkg_name, enabledSharedRO, userAppsRWDir, userAppsRWSharedDir); if (ret != SECURITY_MANAGER_SUCCESS) { LogError("Failed to setup app SharedRO: " << security_manager_strerror(static_cast<lib_retcode>(ret))); return ret; @@ -939,14 +964,24 @@ static inline int security_manager_setup_namespace_internal(const MountNS::Privi SECURITY_MANAGER_API int security_manager_prepare_app(const char *app_name) { - LOG_EXECUTION_TIME("security_manager_prepare_app(" + std::string(app_name) + ")", Credentials::getCredentialsFromSelf()); + return security_manager_prepare_app2(app_name, nullptr); +} +SECURITY_MANAGER_API +int security_manager_prepare_app2(const char *app_name, const char *subsession_id) +{ if (app_name == nullptr) { LogError("app_name is NULL"); return SECURITY_MANAGER_ERROR_INPUT_PARAM; } - LogDebug("security_manager_prepare_app() called for app " << app_name); + LOG_EXECUTION_TIME("security_manager_prepare_app2(" + std::string(app_name) + "," + + (subsession_id ?: "(default)") + ")", Credentials::getCredentialsFromSelf()); + + if (subsession_id) + LogDebug("security_manager_prepare_app2() called for app " << app_name << " subsession " << subsession_id); + else + LogDebug("security_manager_prepare_app2() called for app " << app_name); return try_catch([&] { @@ -969,7 +1004,7 @@ int security_manager_prepare_app(const char *app_name) } ret = security_manager_setup_namespace_internal(privilegePathMap, pkgName, - prepareAppFlags & PREPARE_APP_SHARED_RO_FLAG, privPathsStatusVector, appLabel); + prepareAppFlags & PREPARE_APP_SHARED_RO_FLAG, privPathsStatusVector, appLabel, subsession_id); if (ret != SECURITY_MANAGER_SUCCESS) { LogError("Unable to setup namespace for application " << app_name); return ret; diff --git a/src/common/include/config.h b/src/common/include/config.h index 7596c9a9..532915a5 100644 --- a/src/common/include/config.h +++ b/src/common/include/config.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015-2020 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (c) 2015-2022 Samsung Electronics Co., Ltd. All rights reserved. * * This file is licensed under the terms of MIT License or the Apache License * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details. @@ -45,6 +45,8 @@ /* Files used in permitted label managment */ #define APPS_LABELS_FILE "apps-labels" +#define EMPTY_DIRECTORY DATA_INSTALL_DIR "/dummy" + /* Policy files */ #define PRIVILEGE_MOUNT_LIST_FILE POLICY_INSTALL_DIR "/privilege-mount.list" diff --git a/src/common/include/mount-namespace.h b/src/common/include/mount-namespace.h index 17a7eb51..8147d2f4 100644 --- a/src/common/include/mount-namespace.h +++ b/src/common/include/mount-namespace.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (c) 2017-2022 Samsung Electronics Co., Ltd. All rights reserved. * * This file is licensed under the terms of MIT License or the Apache License * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details. @@ -63,6 +63,7 @@ int makeMountSlave(const Path &mountPoint); int makeMountPrivate(const Path &mountPoint); int bindMountRW(const Path &source, const Path &target); int bindMountRO(const Path &source, const Path &target); +int bindMountROIfExists(const Path &source, const Path &target); int uMount(const Path &target); bool isPathBound(const Path &what, const Path &where); diff --git a/src/common/mount-namespace.cpp b/src/common/mount-namespace.cpp index f3c86359..8294a581 100644 --- a/src/common/mount-namespace.cpp +++ b/src/common/mount-namespace.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2020 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (c) 2017-2022 Samsung Electronics Co., Ltd. All rights reserved. * * This file is licensed under the terms of MIT License or the Apache License * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details. @@ -219,13 +219,34 @@ int bindMountRW(const Path &source, const Path &target) int bindMountRO(const Path &source, const Path &target) { - int ret = mount(source.c_str(), target.c_str(), NULL, MS_BIND|MS_RDONLY, NULL); + int ret = mount(source.c_str(), target.c_str(), NULL, MS_BIND, NULL); + if (ret != 0) { + LogError("Failed to bind directory " << source << " to " << target << " " << GetErrnoString(errno)); + return SECURITY_MANAGER_ERROR_MOUNT_ERROR; + } + + ret = mount(NULL, target.c_str(), NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, NULL); if (ret != 0) { LogError("Failed to RO bind directory " << source << " to " << target << " " << GetErrnoString(errno)); return SECURITY_MANAGER_ERROR_MOUNT_ERROR; } - ret = mount("none", target.c_str(), NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, NULL); + return SECURITY_MANAGER_SUCCESS; +} + +int bindMountROIfExists(const Path &source, const Path &target) +{ + int ret = mount(source.c_str(), target.c_str(), NULL, MS_BIND, NULL); + if (ret != 0) { + if (errno == ENOENT) { + LogDebug("ENOENT when binding " << source << " to " << target << ", skipping"); + return SECURITY_MANAGER_SUCCESS; + } + LogError("Failed to bind directory " << source << " to " << target << " " << GetErrnoString(errno)); + return SECURITY_MANAGER_ERROR_MOUNT_ERROR; + } + + ret = mount(NULL, target.c_str(), NULL, MS_BIND|MS_RDONLY|MS_REMOUNT, NULL); if (ret != 0) { LogError("Failed to RO bind directory " << source << " to " << target << " " << GetErrnoString(errno)); return SECURITY_MANAGER_ERROR_MOUNT_ERROR; diff --git a/src/include/app-runtime.h b/src/include/app-runtime.h index 9d7b5b31..82734031 100644 --- a/src/include/app-runtime.h +++ b/src/include/app-runtime.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016-2020 Samsung Electronics Co., Ltd. All rights reserved. + * Copyright (c) 2016-2022 Samsung Electronics Co., Ltd. All rights reserved. * * This file is licensed under the terms of MIT License or the Apache License * Version 2.0 of your choice. See the LICENSE.MIT file for MIT license details. @@ -110,6 +110,22 @@ int security_manager_prepare_app_candidate(void); int security_manager_prepare_app(const char *app_id); /** + * A convenience function for launchers for preparing security context for an + * application process. It should be called before running actual application code. + * + * This function has to be called in a process where security_manager_prepare_app_candidate() was + * already called and all existing threads are already in the same namespaces. + * + * This function can be called in multithreaded environment. + * However, threads must not be spawned or terminated while the function's running. + * + * \param[in] app_id Application identifier + * \param[in] subsession_id Subsession identifier, NULL if default session + * \return API return code or error code + */ +int security_manager_prepare_app2(const char *app_id, const char *subsession_id); + +/** * This function is intended for launchers for cleaning security context for an * application process. It should be called after application termination. * |