This change reduces the number of IPCs and SQL queries needed to setup mount namespace.
The goal is to reduce the application start time.
Change-Id: Ib6ee820f097f07add9228346cd9a191abb16a97c
return SECURITY_MANAGER_SUCCESS;
}
-static inline int security_manager_bind_namespace_internal(const char *app_name)
+static int setupMountNamespace(const std::string appName, std::vector<std::pair<std::string, bool>> &privilegeStatusVector)
{
- using namespace SecurityManager;
- return try_catch([&]() -> int {
- ClientRequest request(SecurityModuleCall::APP_BIND_NAMESPACE);
- return request.send(std::string(app_name)).getStatus();
- });
+ ClientRequest request(SecurityModuleCall::APP_SETUP_NAMESPACE);
+ if (request.send(appName).failed())
+ return request.getStatus();
+
+ request.recv(privilegeStatusVector);
+ return SECURITY_MANAGER_SUCCESS;
}
static inline int security_manager_create_namespace_internal(const char *app_name)
{
- int ret, result;
-
- if (app_name == nullptr) {
- LogError("app_name is NULL");
- return SECURITY_MANAGER_ERROR_INPUT_PARAM;
- }
+ if (!MountNS::isMountNamespaceEnabled())
+ return SECURITY_MANAGER_SUCCESS;
- ret = MountNS::createMountNamespace();
+ int ret = MountNS::createMountNamespace();
if (ret != SECURITY_MANAGER_SUCCESS)
return ret;
if (ret != SECURITY_MANAGER_SUCCESS)
return ret;
+ std::vector<std::pair<std::string, bool>> privilegeStatusVector;
+ ret = setupMountNamespace(app_name, privilegeStatusVector);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ LogError("Failed to setup app namespace: " << security_manager_strerror(static_cast<lib_retcode>(ret)) << " App name:" << app_name);
+ return ret;
+ }
+
auto storagePrivilegePathMap = MountNS::getPrivilegePathMap(getuid());
- for (auto &it : storagePrivilegePathMap) {
- ret = security_manager_app_has_privilege(app_name, it.first.c_str(), getuid(), &result);
- if (ret != SECURITY_MANAGER_SUCCESS) {
- LogError("Error: " << security_manager_strerror(static_cast<lib_retcode>(ret)) << " App name: " << app_name << ", " << it.first);
- return ret;
- }
+ for (auto &privilegeStatus : privilegeStatusVector) {
+ auto it = storagePrivilegePathMap.find(privilegeStatus.first);
+ if (it == storagePrivilegePathMap.end())
+ continue;
- for (auto &privilegePath : it.second) {
+ for (auto &privilegePath : it->second) {
if (FS::directoryStatus(privilegePath.dstPath) == 0) {
- LogWarning("Not enforcing privilege " << it.first << " for application " << app_name << " : " <<
- "directory " << privilegePath.dstPath << " doesn't exist");
+ LogWarning("Not enforcing privilege " << it->first << " for application " << app_name << " : " <<
+ "directory " << privilegePath.dstPath << " doesn't exist");
continue;
}
- ret = MountNS::applyPrivilegePath(result, privilegePath);
+ ret = MountNS::applyPrivilegePath(privilegeStatus.second, privilegePath);
if (ret != SECURITY_MANAGER_SUCCESS)
return ret;
}
}
- ret = security_manager_bind_namespace_internal(app_name);
- if (ret != SECURITY_MANAGER_SUCCESS) {
- LogError("Failed to bind app namespace: " << security_manager_strerror(static_cast<lib_retcode>(ret)) << " App name:" << app_name);
- return ret;
- }
-
return SECURITY_MANAGER_SUCCESS;
}
return ret;
}
- if (MountNS::isMountNamespaceEnabled()) {
- ret = security_manager_create_namespace_internal(app_name);
- if (ret != SECURITY_MANAGER_SUCCESS) {
- LogError("Unable to setup namespace for application " << app_name);
- return ret;
- }
+ ret = security_manager_create_namespace_internal(app_name);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ LogError("Unable to setup namespace for application " << app_name);
+ return ret;
}
ret = security_manager_sync_threads_internal(app_name);
GET_APP_DEFINED_PRIVILEGE_PROVIDER,
GET_APP_DEFINED_PRIVILEGE_LICENSE,
GET_CLIENT_PRIVILEGE_LICENSE,
- APP_BIND_NAMESPACE,
+ APP_SETUP_NAMESPACE,
APP_CLEAN_NAMESPACE,
NOOP = 0x90,
};
std::string &license);
/**
- * Bind app namespace to file
+ * Setup app namespace
*
* @param[in] creds credentials of the requesting process
* @param[in] appName application identifier
+ * @param[out] privilegeStatusVector returned vector of privilege-status pair
*
* @return API return code, as defined in protocols.h
*/
- int appBindNamespace(const Credentials &creds, const std::string &appName);
+ int appSetupNamespace(const Credentials &creds, const std::string &appName,
+ std::vector<std::pair<std::string, bool>> &privilegeStatusVector);
/**
* Register channel for communication with worker process.
return SECURITY_MANAGER_SUCCESS;
}
-int ServiceImpl::appBindNamespace(const Credentials &creds, const std::string &appName)
+int ServiceImpl::appSetupNamespace(const Credentials &creds, const std::string &appName,
+ std::vector<std::pair<std::string, bool>> &privilegeStatusVector)
{
int ret;
-
if (!authenticate(creds, Config::PRIVILEGE_APP_NAMESPACE)) {
- LogError("Request from uid=" << creds.uid << ", Smack=" << creds.label << " for app bind denied");
+ LogError("Request from uid=" << creds.uid << ", Smack=" << creds.label << " for setup app namespace denied");
return SECURITY_MANAGER_ERROR_AUTHENTICATION_FAILED;
}
- const std::string appProcessLabel = getAppProcessLabel(appName);
- const std::string appsDir = MountNS::getUserAppsMountPointsPath(creds.uid);
- const std::string appFile = MountNS::getUserAppMountPointPath(creds.uid, appProcessLabel);
- const std::string procFile = "/proc/" + std::to_string(creds.pid) + "/ns/mnt";
+ try {
+ const std::string appProcessLabel = getAppProcessLabel(appName);
+ const std::string uidStr = std::to_string(creds.uid);
+ const std::string appsDir = MountNS::getUserAppsMountPointsPath(creds.uid);
+ const std::string appFile = MountNS::getUserAppMountPointPath(creds.uid, appProcessLabel);
+ const std::string procFile = "/proc/" + std::to_string(creds.pid) + "/ns/mnt";
+
+ if (FS::directoryStatus(appsDir) == 0) { // directory does not exist
+ ret = FS::createDirectory(appsDir);
+ if (ret != SECURITY_MANAGER_SUCCESS)
+ return ret;
- if (FS::directoryStatus(appsDir) == 0) { // directory does not exist
- ret = FS::createDirectory(appsDir);
- if (ret != SECURITY_MANAGER_SUCCESS)
- return ret;
+ ret = MountNS::bindMount(appsDir, appsDir);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ FS::removeDirectory(appsDir);
+ return ret;
+ }
- ret = MountNS::bindMount(appsDir, appsDir);
- if (ret != SECURITY_MANAGER_SUCCESS) {
- FS::removeDirectory(appsDir);
- return ret;
+ ret = MountNS::makeMountPrivate(appsDir);
+ if (ret != SECURITY_MANAGER_SUCCESS) {
+ MountNS::uMount(appsDir);
+ FS::removeDirectory(appsDir);
+ return ret;
+ }
+ }
+
+ if (FS::fileStatus(appFile) == 0) { // file does not exist
+ ret = FS::createFile(appFile);
+ if (ret != SECURITY_MANAGER_SUCCESS)
+ return ret;
+ } else {
+ MountNS::uMount(appFile);
}
- ret = MountNS::makeMountPrivate(appsDir);
+ ret = MountNS::bindMount(procFile, appFile);
if (ret != SECURITY_MANAGER_SUCCESS) {
- MountNS::uMount(appsDir);
- FS::removeDirectory(appsDir);
+ FS::removeFile(appFile);
return ret;
}
- }
- if (FS::fileStatus(appFile) == 0) { // file does not exist
- ret = FS::createFile(appFile);
- if (ret != SECURITY_MANAGER_SUCCESS)
- return ret;
- } else {
- MountNS::uMount(appFile);
- }
+ auto storagePrivilegePathMap = MountNS::getPrivilegePathMap(creds.uid);
+ for (auto &it : storagePrivilegePathMap) {
+ bool result = m_cynara.check(appProcessLabel, it.first.c_str(), uidStr, "");
+ privilegeStatusVector.push_back(make_pair(it.first, result));
+ }
- ret = MountNS::bindMount(procFile, appFile);
- if (ret != SECURITY_MANAGER_SUCCESS) {
- FS::removeFile(appFile);
- return ret;
+ } catch (const CynaraException::Base &e) {
+ LogError("Error while querying Cynara for permissions: " << e.DumpToString());
+ return SECURITY_MANAGER_ERROR_SERVER_ERROR;
+ } catch (const SmackException::InvalidLabel &e) {
+ LogError("Error while generating Smack labels: " << e.DumpToString());
+ return SECURITY_MANAGER_ERROR_SERVER_ERROR;
+ } catch (const std::bad_alloc &e) {
+ LogError("Memory allocation failed: " << e.what());
+ return SECURITY_MANAGER_ERROR_MEMORY;
+ } catch (...) {
+ LogError("Unknown exception thrown");
+ return SECURITY_MANAGER_ERROR_UNKNOWN;
}
-
return SECURITY_MANAGER_SUCCESS;
}
void processGetClientPrivilegeLicense(MessageBuffer &buffer, MessageBuffer &send);
/**
- * Process bind namespace to file
+ * Process setup app namespace
*
* @param buffer Raw received data buffer
* @param send Raw data buffer to be sent
* @param creds credentials of the requesting process
*/
- void processAppBindNamespace(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds);
+ void processAppSetupNamespace(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds);
/**
* Process clean app namespace
LogDebug("call_type: SecurityModuleCall::GET_CLIENT_PRIVILEGE_PROVIDER");
processGetClientPrivilegeLicense(buffer, send);
break;
- case SecurityModuleCall::APP_BIND_NAMESPACE:
- LogDebug("call_type: SecurityModuleCall::APP_BIND_NAMESPACE");
- processAppBindNamespace(buffer, send, creds);
+ case SecurityModuleCall::APP_SETUP_NAMESPACE:
+ LogDebug("call_type: SecurityModuleCall::APP_SETUP_NAMESPACE");
+ processAppSetupNamespace(buffer, send, creds);
break;
case SecurityModuleCall::APP_CLEAN_NAMESPACE:
LogDebug("call_type: SecurityModuleCall::APP_CLEAN_NAMESPACE");
Serialization::Serialize(send, license);
}
-void Service::processAppBindNamespace(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds)
+void Service::processAppSetupNamespace(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds)
{
std::string appName;
+ std::vector<std::pair<std::string, bool>> privilegeStatusVector;
+
Deserialization::Deserialize(buffer, appName);
- int ret = serviceImpl.appBindNamespace(creds, appName);
+ int ret = serviceImpl.appSetupNamespace(creds, appName, privilegeStatusVector);
Serialization::Serialize(send, ret);
+ if (ret == SECURITY_MANAGER_SUCCESS)
+ Serialization::Serialize(send, privilegeStatusVector);
}
void Service::processAppCleanNamespace(MessageBuffer &buffer, MessageBuffer &send, const Credentials &creds)