-# Copyright (c) 2012-2015 Samsung Electronics Co., Ltd All Rights Reserved
+# Copyright (c) 2012-2020 Samsung Electronics Co., Ltd. All rights reserved
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
ADD_DEFINITIONS("-Wno-variadic-macros") # Inhibit variadic macros warnings (needed for ORM)
ADD_DEFINITIONS("-Wno-deprecated") # No warnings about deprecated features
ADD_DEFINITIONS("-Wno-deprecated-declarations") # No warnings about deprecated features
+ADD_DEFINITIONS("-Wno-implicit-fallthrough") # No warnings about switc() statements, often done on purpose
ADD_DEFINITIONS("-DCYNARA_DB_DIR=\"${CYNARA_DB_DIR}\"")
ADD_DEFINITIONS("-DAPP_USER=\"${APP_USER}\"")
/*
- * Copyright (c) 2016 - 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2016-2020 Samsung Electronics Co., Ltd. All rights reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
auto manager = CKM::Manager::create();
RUNNER_ASSERT_MSG(NULL != cert.get(), "Certificate should not be empty");
- RUNNER_ASSERT_MSG(false != cert1.get(), "Certificate should not be empty");
tmp = manager->getCertificateChain(cert,
EMPTY_CERT_VECTOR,
/*
- * Copyright (c) 2014-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2019 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
#include "app_install_helper.h"
namespace {
+
+const gid_t FILE_GROUP = 100;
+
std::string genSkelPath() {
static std::string skelPkgDir;
if (!skelPkgDir.empty())
case RootType::SKEL:
info.path = genSkelPath() + "/" + getPkgId();
break;
+ case RootType::SHARED:
+ if (m_isLocal)
+ info.path = TzPlatformConfig::appDirPath(getUID()) + ".shared/" + getPkgId();
+ else
+ info.path = TzPlatformConfig::globalAppDir() + "/.shared/" + getPkgId();
+ break;
+ case RootType::SHARED_TMP:
+ if (m_isLocal)
+ info.path = TzPlatformConfig::appDirPath(getUID()) + ".shared_tmp/" + getPkgId();
+ else
+ info.path = TzPlatformConfig::globalAppDir() + "/.shared_tmp/" + getPkgId();
+ break;
}
}
break;
case PathType::FILE:
// put files in the directory of the same type
- path = getInstallDir(rType) + "/" + typeToPath.at(smType) + "_dir0/" + typeToPath.at(smType) + std::to_string(i);
+ path = getPath(smType, PathType::DIR, 0, rType) + "/" + typeToPath.at(smType) + std::to_string(i);
break;
}
return path;
}
std::string AppInstallHelper::getSharedRODir(int i, RootType type) const {
- return getPath(SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO, PathType::DIR, i, type);
+return getPath(SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO, PathType::DIR, i, type);
+}
+
+std::string AppInstallHelper::getSharedROPath(int i, RootType type) const {
+ return getPath(SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO, PathType::FILE, i, type);
}
std::string AppInstallHelper::getAppId() const {
bool AppInstallHelper::createFile(app_install_path_type smType, const std::string &path) {
if (creat(path.c_str(), 0751) == 0) {
// Local paths need user change
- m_fileTypeMap[smType].push_back(std::move(path));
- if (!m_isLocal || chown(path.c_str(), m_uidGid, m_uidGid) == 0)
+ m_fileTypeMap[smType].push_back(path);
+ if (!m_isLocal || chown(path.c_str(), m_uidGid, FILE_GROUP) == 0)
return true;
}
return false;
mktreeSafe(path, 0777);
// Dont pass base pkg dirs to SM, because transmute will be forced on RO subdirs
if (!isBasePath)
- m_dirTypeMap[smType].push_back(std::move(path));
- if (!m_isLocal || chown(path.c_str(), m_uidGid, m_uidGid) == 0)
+ m_dirTypeMap[smType].push_back(path);
+ if (!m_isLocal || chown(path.c_str(), m_uidGid, FILE_GROUP) == 0)
return true;
return false;
createDir(smType, path);
break;
case PathType::FILE:
- createPath(smType, PathType::DIR, i, rType);
+ createPath(smType, PathType::DIR, 0, rType);
createFile(smType, path);
break;
}
}
+void AppInstallHelper::createDirLink(app_install_path_type smType, const std::string &dest, int i,
+ RootType rType)
+{
+ createInstallDir(rType);
+ std::string linkPath = getPath(smType, PathType::DIR, i, rType);
+ if (symlink(dest.c_str(), linkPath.c_str()) == 0) {
+ m_fileTypeMap[smType].push_back(linkPath);
+ if (m_isLocal) {
+ chown(linkPath.c_str(), m_uidGid, FILE_GROUP);
+ }
+ }
+}
+
void AppInstallHelper::createTrustedDir(int i, RootType type) {
createPath(SECURITY_MANAGER_PATH_TRUSTED_RW, PathType::DIR, i, type);
}
}
void AppInstallHelper::createSharedRODir(int i, RootType type) {
- createPath(SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO, PathType::DIR, i, type);
+ createPath(SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO, PathType::DIR, i, RootType::SHARED);
+ createInstallDir(RootType::SHARED_TMP);
+ auto linkPath = getSharedRODir(i, RootType::SHARED);
+ createDirLink(SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO, linkPath, i, type);
+}
+
+void AppInstallHelper::createSharedROFile(int i, RootType type) {
+ createPath(SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO, PathType::FILE, i, type);
}
void AppInstallHelper::createPrivateRODir(int i, RootType type) {
/*
- * Copyright (c) 2014-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2019 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
enum RootType {
BASE,
SKEL,
- EXTENDED
+ EXTENDED,
+ SHARED,
+ SHARED_TMP
};
enum PathType {
void createPublicDir(RootType type = RootType::BASE);
void createPrivateFile(int i = 0, RootType type = RootType::BASE);
void createSharedRODir(int i = 0, RootType type = RootType::BASE);
+ void createSharedROFile(int i = 0, RootType type = RootType::BASE);
void createPrivateRODir(int i = 0, RootType type = RootType::BASE);
void removePaths();
std::string getPublicDir(RootType type = RootType::BASE) const;
std::string getPrivatePath(int i = 0, RootType type = RootType::BASE) const;
std::string getSharedRODir(int i = 0, RootType type = RootType::BASE) const;
+ std::string getSharedROPath(int i = 0, RootType type = RootType::BASE) const;
const TypePathsMap& getDirsMap() const;
const TypePathsMap& getFilesMap() const;
bool createFile(app_install_path_type smType, const std::string &path);
bool createDir(app_install_path_type smType, const std::string &path, bool isBasePath = false);
+ void createDirLink(app_install_path_type smType, const std::string &dest, int i = 0,
+ RootType rType = RootType::BASE);
void createInstallDir(RootType type);
std::string m_appName;
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017-2019 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
return generatePathRWLabel(pkgId) + "::RO";
}
-std::string generatePathSharedROLabel(const std::string &pkgId)
-{
- return generatePathRWLabel(pkgId) + "::SharedRO";
-}
-
std::string generatePathTrustedLabel(int64_t authorId)
{
return "User::Author::" + std::to_string(authorId);
{
return "User::Home";
}
+
+std::string getSharedROPathLabel()
+{
+ return "User::App::Shared";
+}
/*
- * Copyright (c) 2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2017-2019 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
std::string generateProcessLabel(const std::string &appId, const std::string &pkgId, bool isHybrid = false);
std::string generatePathRWLabel(const std::string &pkgId);
std::string generatePathROLabel(const std::string &pkgId);
-std::string generatePathSharedROLabel(const std::string &pkgId);
std::string generatePathTrustedLabel(int64_t authorId);
std::string getPublicPathLabel();
+std::string getSharedROPathLabel();
/*
- * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2016-2019 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
class ScopedInstaller {
public:
ScopedInstaller(const AppInstallHelper &app, bool requestUid = true)
- : m_appId(app.getAppId()),
+ : m_appIds({app.getAppId()}),
m_uid(app.getUID()),
m_installType(app.getInstallType()),
m_shouldUninstall(true),
SecurityManagerTest::Api::install(instReq);
}
+ ScopedInstaller(const std::vector<std::string> &appIds, const std::string &pkgId)
+ : m_appIds(appIds),
+ m_uid(0),
+ m_installType(SM_APP_INSTALL_NONE),
+ m_shouldUninstall(true),
+ m_requestUid(false),
+ m_creatorPid(getpid())
+ {
+ SecurityManagerTest::InstallRequest instReq;
+
+ instReq.setPkgId(pkgId);
+ for (unsigned int i = 0; i < appIds.size(); i++) {
+ if (i > 0)
+ instReq.nextApp();
+
+ instReq.setAppId(appIds[i]);
+ }
+
+ SecurityManagerTest::Api::install(instReq);
+ }
+
ScopedInstaller(const ScopedInstaller &) = delete;
ScopedInstaller(ScopedInstaller &&other)
- : m_appId(std::move(other.m_appId)),
+ : m_appIds(std::move(other.m_appIds)),
m_uid(other.m_uid),
m_installType(other.m_installType),
m_shouldUninstall(other.m_shouldUninstall),
if (!m_shouldUninstall)
return;
SecurityManagerTest::InstallRequest uninstReq;
- uninstReq.setAppId(m_appId);
+ for (unsigned int i = 0; i < m_appIds.size(); i++) {
+ if (i > 0)
+ uninstReq.nextApp();
+
+ uninstReq.setAppId(m_appIds[i]);
+ }
if (m_requestUid)
uninstReq.setUid(m_uid);
if (m_installType != SM_APP_INSTALL_NONE)
}
protected:
- std::string m_appId;
+ std::vector<std::string> m_appIds;
uid_t m_uid;
app_install_type m_installType;
bool m_shouldUninstall;
/*
- * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2019 Samsung Electronics Co., Ltd. All rights reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
<< " Expected result: " << expectedResult);
}
+void prepareAppCandidate(lib_retcode expectedResult)
+{
+ int result = security_manager_prepare_app_candidate();
+ RUNNER_ASSERT_MSG((lib_retcode) result == expectedResult,
+ "preparing app candidate process returned wrong value."
+ << " Result: " << result << ";"
+ << " Expected result: " << expectedResult);
+}
+
void prepareApp(const std::string &appId, lib_retcode expectedResult)
{
int result = security_manager_prepare_app(appId.c_str());
/*
- * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2019 Samsung Electronics Co., Ltd. All rights reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
void setProcessGroups(const std::string &appId, lib_retcode expectedResult = SECURITY_MANAGER_SUCCESS);
void dropProcessPrivileges(lib_retcode expectedResult = SECURITY_MANAGER_SUCCESS);
void prepareApp(const std::string &appId, lib_retcode expectedResult = SECURITY_MANAGER_SUCCESS);
+void prepareAppCandidate(lib_retcode expectedResult = SECURITY_MANAGER_SUCCESS);
void cleanupApp(const std::string &appId, uid_t uid, pid_t pid, lib_retcode expectedResult = SECURITY_MANAGER_SUCCESS);
void addUser(const UserRequest &request, lib_retcode expectedResult = SECURITY_MANAGER_SUCCESS);
void deleteUser(const UserRequest &request, lib_retcode expectedResult = SECURITY_MANAGER_SUCCESS);
/*
- * Copyright (c) 2014-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2019 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
<< " App id: " << appId << ";"
<< " Result: " << result << ";"
<< " Expected result: " << expectedResult);
- m_appId = std::move(appId);
}
void InstallRequest::setPkgId(std::string pkgId, lib_retcode expectedResult)
<< " Expected result: " << expectedResult);
}
+void InstallRequest::nextApp(lib_retcode expectedResult)
+{
+ int result = security_manager_app_inst_req_next(m_req);
+ RUNNER_ASSERT_MSG((lib_retcode)result == expectedResult,
+ "security_manager_app_inst_req_next() returned wrong value."
+ << " Result: " << result << ";"
+ << " Expected result: " << expectedResult);
+}
+
std::ostream& operator<<(std::ostream &os, const InstallRequest &request)
{
- if (!request.m_appId.empty())
- os << "app id: " << request.m_appId << "; ";
if (!request.m_pkgId.empty())
os << "pkg id: " << request.m_pkgId << "; ";
if (!request.m_privileges.empty()) {
/*
- * Copyright (c) 2014-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2019 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
InstallRequest& operator=(const InstallRequest&) = delete;
InstallRequest(InstallRequest &&other)
: m_req(std::move(other.m_req)),
- m_appId(std::move(other.m_appId)),
m_pkgId(std::move(other.m_pkgId)),
m_authorId(std::move(other.m_authorId)),
m_privileges(std::move(other.m_privileges)),
void setAuthorId(std::string authorId, lib_retcode expectedResult= SECURITY_MANAGER_SUCCESS);
void setInstallType(const enum app_install_type &type, lib_retcode expectedResult = SECURITY_MANAGER_SUCCESS);
void setHybrid(lib_retcode expectedResult = SECURITY_MANAGER_SUCCESS);
+ void nextApp(lib_retcode expectedResult = SECURITY_MANAGER_SUCCESS);
std::string getPkgId() const { return m_pkgId; }
std::string getAppTizenVersion() const { return m_tizenVer; }
app_inst_req *get() { return m_req; }
app_inst_req *m_req;
std::string m_tizenVer;
- std::string m_appId;
std::string m_pkgId;
std::string m_authorId;
PrivilegeVector m_privileges;
/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2015-2020 Samsung Electronics Co., Ltd. All rights reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* @brief A crippled abstraction of widely praised, but often misused communication mechanism
*/
+#include <poll.h>
#include <stdexcept>
#include <unistd.h>
}
void SynchronizationPipe::post() {
- RUNNER_ASSERT_MSG(m_epClaimed == true, "Endpoint not claimed");
- auto ret = TEMP_FAILURE_RETRY(write(m_writeEp, "#", 1));
- RUNNER_ASSERT_ERRNO_MSG(ret > 0, "Write failed ret = " << ret);
+ post("#", 1);
}
void SynchronizationPipe::wait() {
+ char dummy;
+ wait(&dummy, 1);
+}
+
+void SynchronizationPipe::pollForWait() {
+ RUNNER_ASSERT_MSG(m_epClaimed == true, "Endpoint not claimed");
+
+ pollfd fds[1];
+ fds->fd = m_readEp;
+ fds->events = POLLIN;
+ auto ret = TEMP_FAILURE_RETRY(poll(fds, 1, -1));
+ RUNNER_ASSERT_ERRNO(ret > 0);
+}
+
+void SynchronizationPipe::post(const void *data, size_t size) {
+ RUNNER_ASSERT_MSG(m_epClaimed == true, "Endpoint not claimed");
+ auto ret = TEMP_FAILURE_RETRY(write(m_writeEp, data, size));
+ RUNNER_ASSERT_ERRNO_MSG(ret > 0 && size_t(ret) == size, "Write failed size = " << size << " ret = " << ret);
+}
+
+void SynchronizationPipe::wait(void *data, size_t size) {
RUNNER_ASSERT_MSG(m_epClaimed == true, "Endpoint not claimed");
- char buf;
- auto ret = TEMP_FAILURE_RETRY(read(m_readEp, &buf, 1));
- RUNNER_ASSERT_ERRNO_MSG(ret > 0, "Read failed ret = " << ret);
+ auto ret = TEMP_FAILURE_RETRY(read(m_readEp, data, size));
+ RUNNER_ASSERT_ERRNO_MSG(ret > 0 && size_t(ret) == size, "Read failed size = " << size << " ret = " << ret);
}
/*
- * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2015-2020 Samsung Electronics Co., Ltd. All rights reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
void post();
void wait();
+ void pollForWait();
+
+ void post(const void *data, size_t size);
+ void wait(void *data, size_t size);
private:
int m_pipeCP[2]; // Child -> Parent
#include <string.h>
const uid_t APP_UID = 5001;
-const gid_t APP_GID = 5001;
+const gid_t APP_GID = 100;
const uid_t APP_UID_2 = 5200;
const gid_t APP_GID_2 = 5200;
const uid_t DB_ALARM_UID = 6001;
/*
- * Copyright (c) 2014-2015 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2014-2020 Samsung Electronics Co., Ltd. All rights reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
tv.tv_sec = timeoutSeconds;
tv.tv_usec = 0;
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wrestrict"
+
int ret;
if (m_statusMonitor.getStatus() == READ)
ret = TEMP_FAILURE_RETRY(select(fd + 1, &fds, NULL, NULL, &tv));
<< " ret = " << ret);
return;
}
+#pragma GCC diagnostic push
RUNNER_ASSERT_ERRNO_MSG(ret > 0,
"Select returned error:"
<< " ret = " << ret);
/*
- * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2011-2020 Samsung Electronics Co., Ltd. All rights reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
INTERNAL_LOG("### Function: " << function);
INTERNAL_LOG(
"################################################################################");
- } catch (Exception) {
+ } catch (Exception&) {
// Just ignore possible double errors
}
if (!testReason.empty())
testReason += "\n";
testReason += finishReason;
+ break;
case TestResult::FailStatus::NONE:
if (!cleanupReason.empty()) {
if (!testReason.empty())
${PROJECT_SOURCE_DIR}/src/security-manager-tests/security_manager_tests.cpp
${PROJECT_SOURCE_DIR}/src/security-manager-tests/common/policy_configuration.cpp
${PROJECT_SOURCE_DIR}/src/security-manager-tests/common/sm_commons.cpp
+ ${PROJECT_SOURCE_DIR}/src/security-manager-tests/common/template_parser.cpp
${PROJECT_SOURCE_DIR}/src/cynara-tests/common/cynara_test_client.cpp
${PROJECT_SOURCE_DIR}/src/cynara-tests/common/cynara_test_admin.cpp
${PROJECT_SOURCE_DIR}/src/cynara-tests/plugins/plugins.cpp
#include <grp.h>
#include <string>
#include <sys/capability.h>
+#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <unordered_map>
#include <cstdlib>
+#include <array>
#include <unordered_set>
+#include <utility>
#include <vector>
#include <security-manager-types.h>
#include <policy_configuration.h>
#include "tzplatform.h"
#include <label_generator.h>
+#include <template_parser.h>
+#include <temp_test_user.h>
using namespace SecurityManagerTest;
+#define CONF_DIR "/usr/share/security-manager/policy/"
+#define SMACK_RULES_PATH "/sys/fs/smackfs/load2"
+
+#define ALLOW 0
+#define DENY -1
+
// Common DB/nftw checks
// nftw doesn't allow passing user data to functions. Work around by using global variable
}
}
-static void check_app(const std::string &appId, const std::string &pkgId, bool shouldBeInstalled)
+static void check_app_smack_accesses(const std::string &appId, const std::string &pkgId,
+ bool isHybrid = false)
+{
+ static const std::vector<AccessRequest> rules[] =
+ {parseSmackRulesFile(CONF_DIR "pkg-rules-template.smack"),
+ parseSmackRulesFile(CONF_DIR "app-rules-template.smack")};
+
+ const std::pair<std::string, std::string> switchAliases[] =
+ {std::make_pair("~PATH_RW~", generatePathRWLabel(pkgId)),
+ std::make_pair("~PATH_RO~", generatePathROLabel(pkgId)),
+ std::make_pair("~PATH_SHARED_RO~", getSharedROPathLabel()),
+ std::make_pair("~PROCESS~", generateProcessLabel(appId, pkgId, isHybrid))};
+
+ for (auto rule : rules[isHybrid]) {
+ if (rule.object == "~PATH_TRUSTED~") {
+ continue;
+ }
+
+ for (const auto &alias : switchAliases) {
+ if (rule.subject == alias.first) {
+ rule.subject = alias.second;
+ }
+ if (rule.object == alias.first) {
+ rule.object = alias.second;
+ }
+ }
+
+ if (rule.object == "_") {
+ rule.access = "rx" + rule.access;
+ }
+
+ check_exact_smack_accesses(rule.subject, rule.object, rule.access);
+ }
+}
+
+static void assert_no_label_in_rule(const AccessRequest &rule, const std::string &label)
+{
+ RUNNER_ASSERT_MSG(rule.object != label && rule.subject != label,
+ "Smack rule left after uninstallation process." <<
+ " Subject: " << rule.subject <<
+ " object: " << rule.object <<
+ " access: " << rule.access);
+}
+
+static void check_pkg_smack_rules_after_uninstall(const std::string &appId, const std::string &pkgId)
+{
+ const std::vector<AccessRequest> rules(std::move(parseSmackRulesFile(SMACK_RULES_PATH)));
+ const std::string labels[] = {generatePathRWLabel(pkgId),
+ generatePathROLabel(pkgId),
+ generateProcessLabel(appId, pkgId, true),
+ generateProcessLabel(appId, pkgId)};
+ for (const auto &rule : rules) {
+ for (const auto &label : labels) {
+ assert_no_label_in_rule(rule, label);
+ }
+ }
+}
+
+static void check_hybrid_app_smack_rules_after_uninstall(const std::string &appId, const std::string &pkgId)
+{
+ const std::vector<AccessRequest> rules(std::move(parseSmackRulesFile(SMACK_RULES_PATH)));
+ const std::string appLabel = generateProcessLabel(appId, pkgId, true);
+ for (const auto &rule : rules) {
+ assert_no_label_in_rule(rule, appLabel);
+ }
+}
+
+static void check_app(const std::string &appId, const std::string &pkgId,
+ bool shouldBeInstalled, bool isHybrid, bool removePkg)
{
char *retPkgId;
int ret = security_manager_get_app_pkgid(&retPkgId, appId.c_str());
RUNNER_ASSERT_MSG(strcmp(pkgId.c_str(), retPkgId) == 0,
"The given appId does not belong to the given pkgId.");
}
+ check_app_smack_accesses(appId, pkgId, isHybrid);
} else {
RUNNER_ASSERT_MSG(ret == SECURITY_MANAGER_ERROR_NO_SUCH_OBJECT, "The given appId is installed.");
+
+ if (removePkg) {
+ check_pkg_smack_rules_after_uninstall(appId, pkgId);
+ } else if (isHybrid) {
+ check_hybrid_app_smack_rules_after_uninstall(appId, pkgId);
+ }
}
}
-void check_app_after_install(const std::string &app_id, const std::string &pkg_id)
+void check_app_after_install(const std::string &app_id, const std::string &pkg_id, bool isHybrid)
{
- check_app(app_id, pkg_id, true);
+ check_app(app_id, pkg_id, true, isHybrid, false);
}
static void check_app_gids(const std::string &app_id, const std::vector<gid_t> &allowed_gids)
const privileges_t &denied_privs,
bool isHybrid)
{
- check_app(app_id, pkg_id, true);
-
+ check_app(app_id, pkg_id, true, isHybrid, false);
/* Privileges should be granted to all users if root installs app */
check_app_permissions(app_id, pkg_id, ANY_USER_REPRESENTATION, allowed_privs, denied_privs, isHybrid);
RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for " << path);
}
-void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id)
+void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id,
+ bool isHybrid, bool removePkg)
{
- check_app(app_id, pkg_id, false);
+ check_app(app_id, pkg_id, false, isHybrid, removePkg);
}
void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id,
- const privileges_t &privileges, bool isHybrid)
+ const privileges_t &privileges, bool isHybrid,
+ bool removePkg)
{
- check_app(app_id, pkg_id, false);
+ check_app(app_id, pkg_id, false, isHybrid, removePkg);
/* Privileges should not be granted anymore to any user */
check_app_permissions(app_id, pkg_id, ANY_USER_REPRESENTATION, {}, privileges, isHybrid);
<< " (" << accessTypeToString.at(accessType) << ")");
}
+void accessTest(const std::string &id, const std::string &testPath, int accessType) {
+ int oppositeAccessType = getOppositeAccessType(accessType);
+
+ if (accessType != 0) {
+ accessCheck(id, testPath, accessType, ALLOW);
+ }
+ if (oppositeAccessType != 0) {
+ static const std::vector<int> singleAccessTypes = {R_OK, W_OK, X_OK};
+ for (auto singleAccessType : singleAccessTypes) {
+ if (oppositeAccessType & singleAccessType) {
+ accessCheck(id, testPath, singleAccessType, DENY);
+ }
+ }
+ }
+}
+
void runAccessTest(const std::string &label, uid_t uid, gid_t gid,
const std::string &testPath, int accessType) {
auto fun = [&](){
- int oppositeAccessType = getOppositeAccessType(accessType);
ScopedProcessLabel spl(label, false);
RUNNER_ASSERT_ERRNO_MSG(0 == drop_root_privileges(uid, gid),
"drop_root_privileges failed.");
- if (accessType != 0)
- accessCheck(label, testPath, accessType, 0);
- if (oppositeAccessType != 0) {
- std::vector<int> singleAccessTypes = {R_OK, W_OK, X_OK};
- for (auto singleAccessType : singleAccessTypes)
- if (oppositeAccessType & singleAccessType)
- accessCheck(label, testPath, singleAccessType, -1);
- }
+ accessTest(label, testPath, accessType);
};
runInChildParentWait(fun);
void runAccessTest(const AppInstallHelper &app, const std::string &testPath, int accessType) {
auto fun = [&](){
- int oppositeAccessType = getOppositeAccessType(accessType);
Api::setProcessLabel(app.getAppId());
RUNNER_ASSERT_ERRNO_MSG(0 == drop_root_privileges(app.getUID(), app.getGID()),
"drop_root_privileges failed.");
- if (accessType != 0)
- accessCheck(app.getAppId(), testPath, accessType, 0);
- if (oppositeAccessType != 0) {
- std::vector<int> singleAccessTypes = {R_OK, W_OK, X_OK};
- for (auto singleAccessType : singleAccessTypes)
- if (oppositeAccessType & singleAccessType)
- accessCheck(app.getAppId(), testPath, singleAccessType, -1);
- }
+ accessTest(app.getAppId(), testPath, accessType);
};
runInChildParentWait(fun);
return std::count_if(privs.begin(), privs.end(), isPrivilegePrivacy);
}
+int setLauncherSecurityAttributes(uid_t uid, gid_t gid)
+{
+ // Add launcher capabilities (cap_dac_override, cap_setgid, cap_sys_admin, cap_mac_admin),
+ // launcher is user process, we must drop root privileges (cap_setgid, cap_setuid are needed).
+ // By default, the permitted capability set is cleared when credentials change is made
+ // (if a process drops a capability from its permitted set, it can never reacquire that capability),
+ // setting the "keep capabilities" flag prevents it from being cleared.
+ // Effective capability set is always cleared when credential change is made, we need to add them again.
+
+ setCaps("cap_dac_override+ep cap_setgid+ep cap_sys_admin+ep cap_mac_admin+ep cap_setuid+ep");
+ int ret = prctl(PR_SET_KEEPCAPS, 1, 0, 0);
+ if (ret != 0)
+ return ret;
+
+ ret = drop_root_privileges(uid, gid);
+ if (ret != 0)
+ return ret;
+
+ setCaps("cap_dac_override+ep cap_setgid+ep cap_sys_admin+ep cap_mac_admin+ep");
+ return ret;
+}
+int setLauncherSecurityAttributes(TemporaryTestUser &user)
+{
+ return setLauncherSecurityAttributes(user.getUid(), user.getGid());
+}
+
/*
- * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2016-2019 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
void sm_app_has_privileges(const AppInstallHelper &app,
const std::vector<std::string> &privileges,
int result);
-void check_app_after_install(const std::string &app_id, const std::string &pkg_id);
+void check_app_after_install(const std::string &app_id, const std::string &pkg_id,
+ bool isHybrid = false);
void check_app_after_install(const std::string &app_id, const std::string &pkg_id,
const privileges_t &allowed_privs,
const privileges_t &denied_privs,
bool isHybrid = false);
void check_path(const std::string &path, const std::string &label,
bool transmute = true, bool execute = false);
-void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id);
void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id,
- const privileges_t &privileges, bool isHybrid = false);
-
+ bool isHybrid = false, bool removePkg = false);
+void check_app_after_uninstall(const std::string &app_id, const std::string &pkg_id,
+ const privileges_t &privileges, bool isHybrid = false,
+ bool removePkg = false);
std::string access_opposite(std::string &access);
void check_exact_smack_accesses(const std::string &subject,
const std::string &object,
CapsSetsUniquePtr setCaps(const char *cap_string);
+void accessTest(const std::string &id, const std::string &testPath, int accessType);
void runAccessTest(const std::string &label, uid_t uid, gid_t gid,
const std::string &testPath, int accessType);
void runAccessTest(const AppInstallHelper &app, const std::string &testPath, int accessType);
bool isPrivilegePrivacy(const std::string &priv);
int countPrivacyPrivileges(const PrivilegeVector &privs);
int countPrivacyPrivileges(const std::vector<std::string> &privs);
+
+int setLauncherSecurityAttributes(uid_t uid, gid_t gid);
+int setLauncherSecurityAttributes(TemporaryTestUser &user);
--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file template_parser.cpp
+ * @author Alicja Kluczek <a.kluczek@samsung.com>
+ * @brief Parsing function for smack rules templates
+ */
+#include "template_parser.h"
+#include <fstream>
+
+std::vector<AccessRequest> parseSmackRulesFile(const std::string &path)
+{
+ std::vector<AccessRequest> rules;
+ std::ifstream rulesFile(path);
+ std::string object, subject, access;
+ while (rulesFile >> subject >> object >> access) {
+ rules.emplace_back(std::move(subject), std::move(object), std::move(access));
+ }
+ return rules;
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/*
+ * @file template_parser.h
+ * @author Alicja Kluczek <a.kluczek@samsung.com>
+ * @brief Parsing function for smack rules templates
+ */
+#include <vector>
+#include <string>
+
+struct AccessRequest {
+ AccessRequest(std::string sub, std::string obj, std::string acc)
+ : subject(std::move(sub)),
+ object(std::move(obj)),
+ access(std::move(acc))
+ {}
+ std::string subject;
+ std::string object;
+ std::string access;
+};
+
+std::vector<AccessRequest> parseSmackRulesFile(const std::string &path);
+
check_path(privateDir, generatePathRWLabel(pkgId));
check_path(privateRODir, generatePathROLabel(pkgId), false);
check_path(publicRODir, getPublicPathLabel());
- check_path(sharedRODir, generatePathSharedROLabel(pkgId));
+ check_path(sharedRODir, getSharedROPathLabel());
}
RUNNER_TEST(security_manager_02_app_install_uninstall_full)
check_path(app.getPrivateDir(), generatePathRWLabel(app.getPkgId()));
check_path(app.getPrivateRODir(), generatePathROLabel(app.getPkgId()), false);
check_path(app.getPublicDir(), getPublicPathLabel());
- check_path(app.getSharedRODir(), generatePathSharedROLabel(app.getPkgId()));
+ check_path(app.getSharedRODir(), getSharedROPathLabel());
}
check_app_after_uninstall(app.getAppId(), app.getPkgId(), app.getPrivilegesNames());
install(users[0], pkgId[0], appId[0], version[0], author[1], hybrid[0], SECURITY_MANAGER_ERROR_INPUT_PARAM);
}
+RUNNER_TEST(security_manager_09a_install_many_apps_in_single_request)
+{
+ const std::string pkgId = "sm_test_09a_pkg_id_0";
+ const std::vector<std::string> appIds = {"sm_test_09a_app_id_0", "sm_test_09a_app_id_1", "sm_test_09a_app_id_2"};
+
+ {
+ ScopedInstaller appsInstall(appIds, pkgId);
+ // Installing many applications in single request
+ for (const auto &appId : appIds) {
+ check_app_after_install(appId, pkgId);
+ }
+ }
+
+ for (const auto &appId : appIds) {
+ check_app_after_uninstall(appId, pkgId);
+ }
+}
+
+RUNNER_TEST(security_manager_09b_install_many_apps_in_single_request_duplicated_ids)
+{
+ const std::string pkgId = "sm_test_09b_pkg_id_0";
+ const std::string appId = "sm_test_09b_app_id_0";
+
+ {
+ ScopedInstaller appsInstall({appId, appId}, pkgId);
+ check_app_after_install(appId, pkgId);
+ }
+
+ check_app_after_uninstall(appId, pkgId);
+}
+
+RUNNER_TEST(security_manager_09c_update_many_apps_in_single_request_hybrid_package)
+{
+ const std::vector<std::string> appIds = {"sm_test_09c_app_id_0", "sm_test_09c_app_id_1", "sm_test_09c_app_id_2"};
+ const std::string pkgId = "sm_test_09c_pkg_id_0";
+
+ {
+ ScopedInstaller appsInstall(appIds, pkgId);
+ // Package is not hybrid, every app has same policy.
+ for (const auto &appId : appIds) {
+ check_app_after_install(appId, pkgId);
+ }
+
+ // Updating package -- changing set of apps in package and setting hybrid mode
+ InstallRequest updateRequest;
+ updateRequest.setPkgId(pkgId);
+ updateRequest.setAppId(appIds[0]);
+ updateRequest.nextApp();
+ updateRequest.setAppId(appIds[1]);
+ updateRequest.setHybrid();
+
+ Api::update(updateRequest);
+ // Package became hybrid, so every app has its own Smack label
+ check_app_after_install(appIds[0], pkgId, true);
+ check_app_after_install(appIds[1], pkgId, true);
+ // Package became hybrid properly,
+ // so app not included in updated version of package was uninstalled.
+ check_app_after_uninstall(appIds[2], pkgId);
+ }
+
+ for (const auto &appId : appIds) {
+ check_app_after_uninstall(appId, pkgId, true, true);
+ }
+}
+
+RUNNER_TEST(security_manager_09d_uninstall_app_from_hybrid_package)
+{
+ const std::vector<std::string> appIds = {"sm_test_09d_app_id_0", "sm_test_09d_app_id_1", "sm_test_09d_app_id_2"};
+ const std::string pkgId = "sm_test_09d_pkg_id_0";
+ {
+ ScopedInstaller appsInstall(appIds, pkgId);
+
+ InstallRequest updateRequest;
+ updateRequest.setPkgId(pkgId);
+ for (unsigned int i = 0; i < appIds.size(); i++) {
+ if (i > 0) {
+ updateRequest.nextApp();
+ }
+ updateRequest.setAppId(appIds[i]);
+ }
+ updateRequest.setHybrid();
+ Api::update(updateRequest);
+
+ InstallRequest uninstRequest;
+ uninstRequest.setPkgId(pkgId);
+ uninstRequest.setAppId(appIds[0]);
+ Api::uninstall(uninstRequest);
+
+ check_app_after_uninstall(appIds[0], pkgId, true);
+ }
+}
+
RUNNER_CHILD_TEST(security_manager_10_app_has_privilege)
{
const std::vector<std::string> allowedPrivs = {
/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2016-2020 Samsung Electronics Co., Ltd. All rights reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* limitations under the License.
*/
+#include <poll.h>
#include <sys/smack.h>
#include <sys/capability.h>
#include <sys/prctl.h>
+#include <sys/eventfd.h>
+#include <cmath>
#include <thread>
#include <string>
#include <memory>
std::thread thread;
};
-int setLauncherSecurityAttributes(TemporaryTestUser &user)
-{
- // Add launcher capabilities (cap_dac_override, cap_setgid, cap_sys_admin, cap_mac_admin),
- // launcher is user process, we must drop root privileges (cap_setgid, cap_setuid are needed).
- // By default, the permitted capability set is cleared when credentials change is made
- // (if a process drops a capability from its permitted set, it can never reacquire that capability),
- // setting the "keep capabilities" flag prevents it from being cleared.
- // Effective capability set is always cleared when credential change is made, we need to add them again.
-
- setCaps("cap_dac_override+ep cap_setgid+ep cap_sys_admin+ep cap_mac_admin+ep cap_setuid+ep");
- int ret = prctl(PR_SET_KEEPCAPS, 1, 0, 0);
- if (ret != 0)
- return ret;
-
- ret = drop_root_privileges(user.getUid(), user.getGid());
- if (ret != 0)
- return ret;
-
- setCaps("cap_dac_override+ep cap_setgid+ep cap_sys_admin+ep cap_mac_admin+ep");
- return ret;
-}
-
ino_t getFileInode(const std::string &path)
{
struct stat st;
if (pid == 0) {
{
RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(tmpUser) == 0, "launcher failed");
-
+ Api::prepareAppCandidate();
ThreadWrapper threads[THREADS];
for (size_t i = 0; i < THREADS; i++)
}
}
+RUNNER_CHILD_TEST(security_manager_101_create_namespace_test_n)
+{
+ TemporaryTestUser tmpUser(APP_TEST_USER, GUM_USERTYPE_NORMAL, false);
+ tmpUser.create();
+
+ AppInstallHelper app("app100_n", tmpUser.getUid());
+ ScopedInstaller appInstall(app);
+ const std::string expectedLabel = app.generateAppLabel();
+
+ pid_t pid = fork();
+ RUNNER_ASSERT_ERRNO_MSG(pid >= 0, "Fork failed");
+ if (pid == 0) {
+ {
+ RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(tmpUser) == 0, "launcher failed");
+ ThreadWrapper threads[THREADS];
+
+ for (size_t i = 0; i < THREADS; i++)
+ threads[i].run(i, expectedLabel);
+
+ Api::prepareAppCandidate(SECURITY_MANAGER_ERROR_INPUT_PARAM);
+ }
+ RUNNER_ASSERT_MSG(!thread_errors.empty(), std::endl << thread_errors);
+ exit(0);
+ } else {
+ waitPid(pid);
+ }
+}
+
RUNNER_CHILD_TEST(security_manager_101_create_namespace_test)
{
TemporaryTestUser tmpUser(APP_TEST_USER, GUM_USERTYPE_NORMAL, false);
if (pid == 0) {
synchPipe.claimParentEp();
RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(tmpUser) == 0, "launcher failed");
-
+ Api::prepareAppCandidate();
Api::prepareApp(app.getAppId().c_str());
synchPipe.post();
synchPipe.wait();
if (pid == 0) {
synchPipe.claimParentEp();
RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(tmpUser) == 0, "launcher failed");
-
+ Api::prepareAppCandidate();
Api::prepareApp(app.getAppId().c_str());
synchPipe.post();
synchPipe.wait();
if (pid == 0) {
synchPipe.claimParentEp();
RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(tmpUser) == 0, "launcher failed");
-
+ Api::prepareAppCandidate();
Api::prepareApp(app.getAppId().c_str());
synchPipe.post();
synchPipe.wait();
Api::cleanupApp(app.getAppId().c_str(), tmpUser.getUid(), pid);
}
}
+
+namespace {
+class Timestamp {
+ uint64_t _;
+ explicit Timestamp(uint64_t ts) : _(ts) {}
+public:
+ Timestamp operator-(const Timestamp &other) const {
+ RUNNER_ASSERT(_ > other._);
+ return Timestamp(_ - other._);
+ }
+ Timestamp operator+(const Timestamp &other) const {
+ return Timestamp(_ + other._);
+ }
+ bool operator<(const Timestamp &other) const {
+ return _ < other._;
+ }
+ Timestamp() = default;
+ static Timestamp future(uint64_t ns) {
+ timespec ts;
+ const auto res = clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
+ RUNNER_ASSERT_ERRNO(!res);
+ return Timestamp(ts.tv_sec * 1000000000ULL + ts.tv_nsec + ns);
+ }
+ static Timestamp now() {
+ return future(0);
+ }
+ template <size_t nLowDigitsToSkip = 3>
+ static void report(Timestamp *ts, size_t n) {
+ std::sort(ts, ts+n);
+ uint64_t sum = 0, mn = -1, mx = 0;
+ long double qsum = 0;
+ for (size_t i = 0; i < n; i++) {
+ const auto t = ts[i]._;
+ sum += t;
+ qsum += decltype(qsum)(t) * t;
+ mn = std::min(mn, t);
+ mx = std::max(mx, t);
+ }
+ uint64_t avg = sum / n;
+ auto qstddev = qsum/n - decltype(qsum)(avg)*avg;
+ const auto out = [](const char *desc, uint64_t t) {
+ char raw[20];
+ char s[20 + 20/3 + 1];
+ size_t j = 0, i = 0;
+ do
+ raw[j++] = '0' + t % 10ULL;
+ while (t /= 10ULL);
+ for (;;) {
+ s[i++] = raw[--j];
+ if (j <= nLowDigitsToSkip)
+ break;
+ if (!(j % 3))
+ s[i++] = ' ';
+ }
+ s[i] = '\0';
+ std::cerr << desc << s;
+ };
+ out("min ", mn);
+ out(" max ", mx);
+ out(" avg ", avg);
+ out(" median ", ts[n/2]._);
+ out(" stddev ", std::floor(std::sqrt(qstddev)));
+ std::cerr << '\n';
+ }
+};
+
+template <class T, size_t N>
+constexpr size_t arraySize(T (&)[N]) { return N; }
+} // namespace
+
+RUNNER_TEST(security_manager_200_prepare_app_perf)
+{
+ constexpr int8_t nThreads = 32;
+ constexpr int8_t nConcurrentAppsSamples[] = { 0 /* 1 app w/ nThreads */, 1, 2, 4, 8, 16, 32 };
+ constexpr uint64_t minTotalBenchTime = 60 * 1000ULL*1000*1000; // 60s
+
+ TemporaryTestUser tmpUser(APP_TEST_USER, GUM_USERTYPE_NORMAL, false);
+ tmpUser.create();
+
+ struct App {
+ AppInstallHelper hlp;
+ pid_t pid;
+ };
+
+ std::vector<Timestamp> candidate, prepare, everything;
+
+ std::vector<App> apps;
+ std::vector<ScopedInstaller> appInstalls;
+
+ constexpr auto nAppsMax = nConcurrentAppsSamples[arraySize(nConcurrentAppsSamples) - 1] ?: 1;
+ apps.reserve(nAppsMax);
+ appInstalls.reserve(nAppsMax);
+
+ const auto uid = tmpUser.getUid();
+ for (int i = 0; i < nAppsMax; i++) {
+ apps.emplace_back(App{AppInstallHelper("app200_" + std::to_string(i), uid), 0});
+ auto &hlp = apps.back().hlp;
+ for (const auto &p : { EXTERNAL_STORAGE_PRIVILEGE, MEDIA_STORAGE_PRIVILEGE,
+ std::string("http://tizen.org/privilege/camera"),
+ std::string("http://tizen.org/privilege/internet") })
+ hlp.addPrivilege(p);
+ hlp.createSharedRODir();
+ appInstalls.emplace_back(ScopedInstaller(hlp));
+ }
+
+ for (const auto nConcurrentAppsDesc : nConcurrentAppsSamples) {
+ const auto nConcurrentApps = nConcurrentAppsDesc ?: 1;
+ const auto timeout = Timestamp::future(minTotalBenchTime / arraySize(nConcurrentAppsSamples));
+ do {
+ SynchronizationPipe synchPipe;
+ auto exitEvFd = eventfd(0, 0);
+ RUNNER_ASSERT(exitEvFd >= 0);
+
+ for (int i = 0; i < nConcurrentApps; i++) {
+ auto &app = apps[i];
+ const auto pid = fork();
+ RUNNER_ASSERT_ERRNO_MSG(pid >= 0, "Fork failed");
+ if (pid)
+ app.pid = pid;
+ else {
+ synchPipe.claimChildEp();
+ RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(tmpUser) == 0, "launcher failed");
+
+ const auto appId = app.hlp.getAppId();
+
+ synchPipe.post(); // declare readiness to start measuring
+ synchPipe.pollForWait(); // wait for parent to signal all kids simultaneously
+
+ const auto candBeg = Timestamp::now();
+ Api::prepareAppCandidate();
+ const auto candEnd = Timestamp::now();
+
+ if (!nConcurrentAppsDesc) {
+ for (int i = 0; i < nThreads; i++)
+ std::thread([]{ for (;;) usleep(1000); }).detach();
+ }
+
+ const auto prepBeg = Timestamp::now();
+ Api::prepareApp(appId);
+ const auto prepEnd = Timestamp::now();
+
+ const Timestamp ts[2] = { candEnd-candBeg, prepEnd-prepBeg };
+ synchPipe.post(ts, sizeof ts); // post measurement payload
+
+ // stay idle until all kids are done to simulate idle apps and reduce benchmark noise
+ pollfd fds[1];
+ fds->fd = exitEvFd;
+ fds->events = POLLIN;
+ auto ret = TEMP_FAILURE_RETRY(poll(fds, 1, -1));
+ RUNNER_ASSERT_ERRNO(ret > 0);
+
+ exit(0);
+ }
+ }
+ synchPipe.claimParentEp();
+
+ for (int i = 0; i < nConcurrentApps; i++) // wait for all kids to be ready to start measurement
+ synchPipe.wait();
+ synchPipe.post(); // signal all kids to start measuring
+
+ for (int i = 0; i < nConcurrentApps; i++) {
+ Timestamp ts[2];
+ synchPipe.wait(ts, sizeof ts);
+ candidate.emplace_back(ts[0]);
+ prepare.emplace_back(ts[1]);
+ everything.emplace_back(ts[0] + ts[1]);
+ }
+
+ RUNNER_ASSERT(!eventfd_write(exitEvFd, 1)); // signal all kids to exit now
+
+ for (int i = 0; i < nConcurrentApps; i++) {
+ const auto &app = apps[i];
+ waitPid(app.pid);
+ Api::cleanupApp(app.hlp.getAppId(), uid, app.pid);
+ }
+ } while (Timestamp::now() < timeout);
+
+ if (!nConcurrentAppsDesc)
+ std::cerr << "additionalThreads " << int(nThreads) << ' ';
+ std::cerr << "nConcurrentApps " << int(nConcurrentApps) << " samples " << candidate.size() << '\n';
+ std::cerr << " prepareAppCandidate [us]: ";
+ Timestamp::report(candidate.data(), candidate.size());
+ std::cerr << " prepareApp [us]: ";
+ Timestamp::report(prepare.data(), prepare.size());
+ std::cerr << " prepareAppCandidate + prepareApp [us]: ";
+ Timestamp::report(everything.data(), everything.size());
+ candidate.clear();
+ prepare.clear();
+ everything.clear();
+ }
+}
/*
- * Copyright (c) 2016 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2016-2019 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
*/
#include <cstdint>
#include <fcntl.h>
+#include <functional>
#include <unordered_map>
#include <string>
#include <sys/smack.h>
namespace {
const uid_t OWNER_UID = 5001;
+const uid_t OWNER_GID = 100;
const std::vector<std::string> versions = {
"2.4",
RUNNER_TEST_GROUP_INIT(SECURITY_MANAGER_SHARED_RO)
+static void runAccessTest(uid_t uid, gid_t gid, const std::string &appId,
+ std::function<void(void)> f)
+{
+ pid_t pid = fork();
+
+ RUNNER_ASSERT_ERRNO_MSG(pid >= 0, "Fork failed");
+ if (pid == 0) {
+ setLauncherSecurityAttributes(uid, gid);
+ Api::prepareAppCandidate();
+ Api::prepareApp(appId.c_str());
+ f();
+ exit(0);
+ } else {
+
+ waitPid(pid);
+ Api::cleanupApp(appId.c_str(), uid, pid);
+ }
+}
+
/**
* Check whether owner app have access to own sharedRO dir
*/
app.createSharedRODir();
ScopedInstaller sharedROPkgApp(app);
- runAccessTest(app, app.getSharedRODir(), R_OK|W_OK|X_OK);
+ runAccessTest(OWNER_UID, OWNER_GID, app.getAppId(), [&]() {
+ accessTest(app.getAppId(), app.getSharedRODir(), R_OK|W_OK|X_OK);
+ });
}
}
+RUNNER_CHILD_TEST(security_manager_7x_test)
+{
+ AppInstallHelper ownerApp("owner_7x", OWNER_UID);
+ ownerApp.createSharedRODir();
+ ScopedInstaller ownerAppInstall(ownerApp);
+
+ AppInstallHelper otherApp("other_7x", OWNER_UID);
+ otherApp.createSharedRODir();
+ ScopedInstaller otherAppInstall(otherApp);
+
+ runAccessTest(OWNER_UID, OWNER_GID, ownerApp.getAppId(), [&]() {
+ accessTest(ownerApp.getAppId(), ownerApp.getSharedRODir(), R_OK | W_OK | X_OK);
+ accessTest(ownerApp.getAppId(), otherApp.getSharedRODir(), R_OK | X_OK);
+ exit(0);
+ });
+}
+
/**
* Check whether app without shared RO path has access to shared RO dir and
* no access to private directories of application from different package between
AppInstallHelper nonSharedApp("sm_test_77_nonshared", OWNER_UID, version.second);
ScopedInstaller nonSharedAppInstall(nonSharedApp);
- runAccessTest(sharedApp, sharedApp.getSharedRODir(), R_OK|W_OK|X_OK);
- runAccessTest(nonSharedApp, sharedApp.getPrivateDir(), 0);
- runAccessTest(nonSharedApp, sharedApp.getSharedRODir(), R_OK|X_OK);
+ runAccessTest(OWNER_UID, OWNER_GID, sharedApp.getAppId(), [&]() {
+ accessTest(sharedApp.getAppId(), sharedApp.getSharedRODir(), R_OK|W_OK|X_OK);
+ });
+
+ runAccessTest(OWNER_UID, OWNER_GID, nonSharedApp.getAppId(), [&]() {
+ accessTest(nonSharedApp.getAppId(), sharedApp.getPrivateDir(), 0);
+ accessTest(nonSharedApp.getAppId(), sharedApp.getSharedRODir(), R_OK|X_OK);
+ });
}
}
sharedApp2.createPrivateDir();
ScopedInstaller sharedApp2Install(sharedApp2);
- runAccessTest(sharedApp2, sharedApp1.getSharedRODir(), R_OK|X_OK);
- runAccessTest(sharedApp1, sharedApp2.getSharedRODir(), R_OK|X_OK);
- runAccessTest(sharedApp1, sharedApp1.getSharedRODir(), R_OK|W_OK|X_OK);
- runAccessTest(sharedApp2, sharedApp2.getSharedRODir(), R_OK|W_OK|X_OK);
- runAccessTest(sharedApp2, sharedApp1.getPrivateDir(), 0);
- runAccessTest(sharedApp1, sharedApp2.getPrivateDir(), 0);
+ runAccessTest(OWNER_UID, OWNER_GID, sharedApp1.getAppId(), [&]() {
+ accessTest(sharedApp1.getAppId(), sharedApp2.getSharedRODir(), R_OK|X_OK);
+ accessTest(sharedApp1.getAppId(), sharedApp1.getSharedRODir(), R_OK|W_OK|X_OK);
+ accessTest(sharedApp1.getAppId(), sharedApp2.getPrivateDir(), 0);
+ });
+
+ runAccessTest(OWNER_UID, OWNER_GID, sharedApp2.getAppId(), [&]() {
+ accessTest(sharedApp2.getAppId(), sharedApp1.getSharedRODir(), R_OK|X_OK);
+ accessTest(sharedApp2.getAppId(), sharedApp2.getSharedRODir(), R_OK|W_OK|X_OK);
+ accessTest(sharedApp2.getAppId(), sharedApp1.getPrivateDir(), 0);
+ });
}
}
sharedApp2.createSharedRODir();
ScopedInstaller sharedAppInstall2(sharedApp2);
- runAccessTest(sharedApp2, sharedApp1.getSharedRODir(), R_OK|W_OK|X_OK);
- runAccessTest(sharedApp1, sharedApp2.getSharedRODir(), R_OK|W_OK|X_OK);
- };
+ runAccessTest(OWNER_UID, OWNER_GID, sharedApp1.getAppId(), [&]() {
+ accessTest(sharedApp1.getAppId(), sharedApp2.getSharedRODir(), R_OK|W_OK|X_OK);
+ });
+ runAccessTest(OWNER_UID, OWNER_GID, sharedApp2.getAppId(), [&]() {
+ accessTest(sharedApp2.getAppId(), sharedApp1.getSharedRODir(), R_OK|W_OK|X_OK);
+ });
+ }
}
/**
AppInstallHelper nonSharedApp("sm_test_79b_shared2", sharedPkgName, OWNER_UID, version);
ScopedInstaller nonSharedAppInstall(nonSharedApp);
- runAccessTest(nonSharedApp, sharedApp.getSharedRODir(), R_OK|W_OK|X_OK);
+ runAccessTest(OWNER_UID, OWNER_GID, nonSharedApp.getAppId(), [&]() {
+ accessTest(nonSharedApp.getAppId(), sharedApp.getSharedRODir(), R_OK|W_OK|X_OK);
+ });
};
}
AppInstallHelper nonSharedApp("sm_test_80_nonshared", sharedPkgName, OWNER_UID, version);
ScopedInstaller nonSharedAppInstall(nonSharedApp);
- runAccessTest(sharedApp2, sharedApp1.getPrivateDir(1), R_OK|W_OK|X_OK);
- runAccessTest(sharedApp1, sharedApp2.getPrivateDir(2), R_OK|W_OK|X_OK);
- runAccessTest(nonSharedApp, sharedApp1.getPrivateDir(1), R_OK|W_OK|X_OK);
- runAccessTest(nonSharedApp, sharedApp2.getPrivateDir(2), R_OK|W_OK|X_OK);
+ runAccessTest(OWNER_UID, OWNER_GID, sharedApp1.getAppId(), [&]() {
+ accessTest(sharedApp1.getAppId(), sharedApp2.getPrivateDir(2), R_OK|W_OK|X_OK);
+ });
+ runAccessTest(OWNER_UID, OWNER_GID, sharedApp2.getAppId(), [&]() {
+ accessTest(sharedApp2.getAppId(), sharedApp1.getPrivateDir(1), R_OK|W_OK|X_OK);
+ });
+
+ runAccessTest(OWNER_UID, OWNER_GID, nonSharedApp.getAppId(), [&]() {
+ accessTest(nonSharedApp.getAppId(), sharedApp1.getPrivateDir(1), R_OK|W_OK|X_OK);
+ accessTest(nonSharedApp.getAppId(), sharedApp2.getPrivateDir(2), R_OK|W_OK|X_OK);
+ });
sharedAppInstall1.uninstallApp();
- runAccessTest(nonSharedApp, sharedApp2.getPrivateDir(2), R_OK|W_OK|X_OK);
+ runAccessTest(OWNER_UID, OWNER_GID, nonSharedApp.getAppId(), [&]() {
+ accessTest(nonSharedApp.getAppId(), sharedApp2.getPrivateDir(2), R_OK|W_OK|X_OK);
+ });
}
}
sharedRORequest.setUid(sharedApp2.getUID());
Api::registerPaths(sharedRORequest);
- runAccessTest(sharedApp, sharedApp.getSharedRODir(), R_OK|W_OK|X_OK);
- runAccessTest(sharedApp, sharedApp.getPrivateDir(), R_OK|W_OK|X_OK);
-
- runAccessTest(sharedApp2, sharedApp2.getSharedRODir(), R_OK|W_OK|X_OK);
- runAccessTest(sharedApp2, sharedApp.getSharedRODir(), R_OK|X_OK);
- runAccessTest(sharedApp2, sharedApp.getPrivateDir(), 0);
-
- runAccessTest(nonSharedApp, sharedApp.getSharedRODir(), R_OK|X_OK);
- runAccessTest(nonSharedApp, sharedApp2.getSharedRODir(), R_OK|X_OK);
- runAccessTest(nonSharedApp, sharedApp.getPrivateDir(), 0);
+ runAccessTest(OWNER_UID, OWNER_GID, sharedApp.getAppId(), [&]() {
+ accessTest(sharedApp.getAppId(), sharedApp.getSharedRODir(), R_OK|W_OK|X_OK);
+ accessTest(sharedApp.getAppId(), sharedApp.getPrivateDir(), R_OK|W_OK|X_OK);
+ });
+
+ runAccessTest(OWNER_UID, OWNER_GID, sharedApp2.getAppId(), [&]() {
+ accessTest(sharedApp2.getAppId(), sharedApp2.getSharedRODir(), R_OK|W_OK|X_OK);
+ accessTest(sharedApp2.getAppId(), sharedApp.getSharedRODir(), R_OK|X_OK);
+ accessTest(sharedApp2.getAppId(), sharedApp.getPrivateDir(), 0);
+ });
+
+ runAccessTest(OWNER_UID, OWNER_GID, nonSharedApp.getAppId(), [&]() {
+ accessTest(nonSharedApp.getAppId(), sharedApp.getSharedRODir(), R_OK|X_OK);
+ accessTest(nonSharedApp.getAppId(), sharedApp2.getSharedRODir(), R_OK|X_OK);
+ accessTest(nonSharedApp.getAppId(), sharedApp.getPrivateDir(), 0);
+ });
}
}
ScopedInstaller nonSharedAppInstall(nonSharedApp);
sharedAppInstall1.uninstallApp();
+ sharedApp1.removePaths();
- runAccessTest(nonSharedApp, sharedApp1.getSharedRODir(), 0);
- runAccessTest(sharedApp2, sharedApp1.getSharedRODir(), 0);
+ runAccessTest(OWNER_UID, OWNER_GID, nonSharedApp.getAppId(), [&]() {
+ accessTest(nonSharedApp.getAppId(), sharedApp1.getSharedRODir(), 0);
+ accessTest(nonSharedApp.getAppId(), sharedApp2.getSharedRODir(), R_OK|X_OK);
+ });
- runAccessTest(nonSharedApp, sharedApp2.getSharedRODir(), R_OK|X_OK);
- runAccessTest(sharedApp2, sharedApp2.getSharedRODir(), R_OK|W_OK|X_OK);
+ runAccessTest(OWNER_UID, OWNER_GID, sharedApp2.getAppId(), [&]() {
+ accessTest(sharedApp2.getAppId(), sharedApp1.getSharedRODir(), 0);
+ accessTest(sharedApp2.getAppId(), sharedApp2.getSharedRODir(), R_OK|W_OK|X_OK);
+ });
}
}
sharedAppInstall1.uninstallApp();
- runAccessTest(nonSharedApp, sharedApp2.getSharedRODir(2), R_OK|X_OK);
- runAccessTest(sharedApp2, sharedApp2.getSharedRODir(2), R_OK|W_OK|X_OK);
+ runAccessTest(OWNER_UID, OWNER_GID, nonSharedApp.getAppId(), [&]() {
+ accessTest(nonSharedApp.getAppId(), sharedApp2.getSharedRODir(2), R_OK|X_OK);
+ });
+
+ runAccessTest(OWNER_UID, OWNER_GID, sharedApp2.getAppId(), [&]() {
+ accessTest(sharedApp2.getAppId(), sharedApp2.getSharedRODir(2), R_OK|W_OK|X_OK);
+ });
}
}
/*
- * Copyright (c) 2016-2017 Samsung Electronics Co., Ltd All Rights Reserved
+ * Copyright (c) 2016-2019 Samsung Electronics Co., Ltd All Rights Reserved
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
check_path(app.getPrivateDir(), generatePathRWLabel(app.getPkgId()));
check_path(app.getPrivateRODir(), generatePathROLabel(app.getPkgId()), false);
check_path(app.getPublicDir(), getPublicPathLabel());
- check_path(app.getSharedRODir(), generatePathSharedROLabel(app.getPkgId()));
+ check_path(app.getSharedRODir(), getSharedROPathLabel());
}
RUNNER_TEST(security_manager_67_path_req_shared_ro_3_0)
preq.addPath(app.getSharedRODir(), SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO);
Api::registerPaths(preq);
- check_path(app.getSharedRODir(), generatePathSharedROLabel(app.getPkgId()));
+ check_path(app.getSharedRODir(), getSharedROPathLabel());
}
RUNNER_TEST(security_manager_68_path_req_shared_ro_2_X)
preq.addPath(app.getSharedRODir(), SECURITY_MANAGER_PATH_OWNER_RW_OTHER_RO);
Api::registerPaths(preq);
- check_path(app.getSharedRODir(), generatePathSharedROLabel(app.getPkgId()));
+ check_path(app.getSharedRODir(), getSharedROPathLabel());
}
RUNNER_TEST(security_manager_69_path_req_trusted_rw_no_author)