summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonrad Lipinski <k.lipinski2@samsung.com>2022-07-26 12:52:49 +0200
committerKonrad Lipinski <k.lipinski2@samsung.com>2022-08-04 16:05:58 +0200
commitacd9399f569c69a8e8c4d07eef48483ea08a801b (patch)
treea3c87bbe62a242d930616180ac8c1248d4857dc2
parenta1178be84298b594b487c68cae215dc58e3609b5 (diff)
downloadsecurity-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.cpp45
-rw-r--r--src/common/include/config.h4
-rw-r--r--src/common/include/mount-namespace.h3
-rw-r--r--src/common/mount-namespace.cpp27
-rw-r--r--src/include/app-runtime.h18
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.
*