security-manager
security-privilege-manager
key-manager
+ libcap
+ libacl
REQUIRED
)
${PROJECT_SOURCE_DIR}/src/common/scoped_process_label.cpp
${PROJECT_SOURCE_DIR}/src/common/ckm_helpers.cpp
${PROJECT_SOURCE_DIR}/src/common/dac.cpp
+ ${PROJECT_SOURCE_DIR}/src/common/sm_commons.cpp
+ ${PROJECT_SOURCE_DIR}/src/common/scoped_app_launcher.cpp
)
#system and local includes
--- /dev/null
+/*
+ * Copyright (c) 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.
+ * 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.
+ */
+
+#include <scoped_app_launcher.h>
+#include <sm_api.h>
+#include <sm_commons.h>
+#include <tests_common.h>
+#include <dpl/test/safe_cleanup.h>
+
+using namespace SecurityManagerTest;
+
+ScopedAppLauncher::ScopedAppLauncher(const AppInstallHelper& app,
+ const std::function<void(void)>& runInAppContext)
+ : m_uid(app.getUID()),
+ m_gid(app.getGID()),
+ m_appId(app.getAppId())
+{
+ launch(runInAppContext);
+}
+
+ScopedAppLauncher::ScopedAppLauncher(const AppInstallHelper &app, const TemporaryTestUser &user,
+ const std::function<void(void)> &runInAppContext)
+
+ : m_uid(user.getUid()),
+ m_gid(user.getGid()),
+ m_appId(app.getAppId())
+{
+
+ launch(runInAppContext);
+}
+
+void ScopedAppLauncher::launch(const std::function<void(void)> &runInAppContext)
+{
+ m_pid = runInChild([&] {
+ m_syncPipe.claimChildEp();
+
+ RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(m_uid, m_gid) == 0,
+ "launcher failed");
+ Api::prepareAppCandidate();
+ Api::prepareApp(m_appId);
+ m_syncPipe.post();
+ runInAppContext();
+ m_syncPipe.wait();
+ });
+
+ m_syncPipe.claimParentEp();
+ m_syncPipe.wait();
+}
+
+ScopedAppLauncher::~ScopedAppLauncher()
+{
+ SafeCleanup::run([this]{
+ m_syncPipe.post();
+ waitPid(m_pid);
+ });
+
+ // Cleanup app even if everything else fails
+ SafeCleanup::run([this]{
+ Api::cleanupApp(m_appId, m_uid, m_pid);
+ });
+}
--- /dev/null
+/*
+ * Copyright (c) 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.
+ * 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.
+ */
+#pragma once
+
+#include <functional>
+
+#include <app_install_helper.h>
+#include <synchronization_pipe.h>
+#include <temp_test_user.h>
+
+class ScopedAppLauncher final {
+public:
+ explicit ScopedAppLauncher(const AppInstallHelper& app,
+ const std::function<void(void)>& runInAppContext = []{});
+ ScopedAppLauncher(const AppInstallHelper& app, const TemporaryTestUser& user,
+ const std::function<void(void)>& runInAppContext = []{});
+ ~ScopedAppLauncher();
+
+ ScopedAppLauncher(const ScopedAppLauncher&) = delete;
+ ScopedAppLauncher& operator=(const ScopedAppLauncher&) = delete;
+
+private:
+ void launch(const std::function<void(void)>& runInAppContext);
+ SynchronizationPipe m_syncPipe;
+ pid_t m_pid;
+ const uid_t m_uid;
+ const gid_t m_gid;
+ const std::string m_appId;
+};
--- /dev/null
+/*
+ * 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.
+ * 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.
+ */
+
+#include <cstring>
+#include <fcntl.h>
+#include <ftw.h>
+#include <string>
+#include <sys/capability.h>
+#include <sys/prctl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <cstdlib>
+
+#include <unistd.h>
+#include <utility>
+#include <vector>
+#include <unordered_map>
+
+#include <security-manager-types.h>
+#include <app-runtime.h>
+#include <privilege_info.h>
+#include <scoped_process_label.h>
+
+#include <dpl/test/test_runner.h>
+#include <memory.h>
+#include <sm_api.h>
+#include <sm_commons.h>
+
+#include <tests_common.h>
+#include "tzplatform.h"
+#include <temp_test_user.h>
+
+#include "dac.h"
+
+using namespace SecurityManagerTest;
+
+namespace {
+inline constexpr int ALLOW = 0;
+inline constexpr int DENY = -1;
+
+const std::vector<std::string> SM_SYSTEM_LABELS = {"System", "System::Privileged", "User"};
+
+int getOppositeAccessType(int accessType) noexcept {
+ return accessType ^ (R_OK | W_OK | X_OK);
+}
+
+const std::unordered_map<int, const char* const> accessTypeToString {
+ std::make_pair(0, "F_OK"),
+ std::make_pair(1, "X_OK"),
+ std::make_pair(2, "W_OK"),
+ std::make_pair(3, "W_OK|X_OK"),
+ std::make_pair(4, "R_OK"),
+ std::make_pair(5, "R_OK|X_OK"),
+ std::make_pair(6, "R_OK|W_OK"),
+ std::make_pair(7, "R_OK|W_OK|X_OK")
+};
+
+// Common DB/nftw checks
+
+// nftw doesn't allow passing user data to functions. Work around by using global variable
+Access nftw_expected_access;
+bool nftw_expected_transmute;
+bool nftw_expected_exec;
+
+int nftw_check_sm_access(const char *fpath,
+ const struct stat *sb,
+ int /*typeflag*/,
+ struct FTW* /*ftwbuf*/)
+{
+ if (smack_check()) {
+ int result;
+ CStringPtr labelPtr;
+ char* label = nullptr;
+
+ /* ACCESS */
+ result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
+ RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
+ labelPtr.reset(label);
+ RUNNER_ASSERT_MSG(label != nullptr, "ACCESS label on " << fpath << " is not set");
+ RUNNER_ASSERT_MSG(nftw_expected_access.label == label, "ACCESS label on " << fpath << " is incorrect"
+ " (should be '" << nftw_expected_access.label << "' and is '" << label << "')");
+
+ /* EXEC */
+ result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
+ RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
+ labelPtr.reset(label);
+
+ if (S_ISREG(sb->st_mode) && (sb->st_mode & S_IXUSR) && nftw_expected_exec) {
+ RUNNER_ASSERT_MSG(label != nullptr, "EXEC label on " << fpath << " is not set");
+ RUNNER_ASSERT_MSG(nftw_expected_access.label == label, "Incorrect EXEC label on executable file " << fpath);
+ } else
+ RUNNER_ASSERT_MSG(label == nullptr, "EXEC label on " << fpath << " is set");
+
+
+ /* TRANSMUTE */
+ result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
+ RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
+ labelPtr.reset(label);
+
+ if (S_ISDIR(sb->st_mode) && nftw_expected_transmute) {
+ RUNNER_ASSERT_MSG(label != nullptr, "TRANSMUTE label on " << fpath << " is not set at all");
+ RUNNER_ASSERT_MSG(strcmp(label, "TRUE") == 0,
+ "TRANSMUTE label on " << fpath << " is not set properly: '" << label << "'");
+ } else {
+ RUNNER_ASSERT_MSG(label == nullptr, "TRANSMUTE label on " << fpath << " is set");
+ }
+ }
+
+ if (nftw_expected_access.dac.has_value())
+ CheckDac(fpath, *nftw_expected_access.dac);
+
+ return 0;
+}
+
+} // namespace
+
+int nftw_remove_labels(const char *fpath, const struct stat* /*sb*/,
+ int /*typeflag*/, struct FTW* /*ftwbuf*/)
+{
+#if SMACK_ENABLED
+ smack_lsetlabel(fpath, nullptr, SMACK_LABEL_ACCESS);
+ smack_lsetlabel(fpath, nullptr, SMACK_LABEL_EXEC);
+ smack_lsetlabel(fpath, nullptr, SMACK_LABEL_TRANSMUTE);
+#else
+ (void)fpath;
+#endif
+
+ return 0;
+}
+
+void check_path(const std::string &path, const Access &access, bool transmute, bool execute) {
+ nftw_expected_access = access;
+ nftw_expected_transmute = transmute;
+ nftw_expected_exec = execute;
+
+ // check labels
+ int result = nftw(path.c_str(), &nftw_check_sm_access, FTW_MAX_FDS, FTW_PHYS);
+ RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for " << path);
+}
+
+CapsSetsUniquePtr setCaps(const char *cap_string)
+{
+ CapsSetsUniquePtr caps(cap_init());
+ caps.reset(cap_from_text(cap_string));
+ RUNNER_ASSERT_MSG(caps, "can't convert capabilities from text");
+ int result = cap_set_proc(caps.get());
+ RUNNER_ASSERT_MSG(result == 0, "can't set capabilities. Result: " << result);
+ return caps;
+}
+
+void accessCheck(const std::string &id, const std::string &path, int accessType,
+ int expected)
+{
+ RUNNER_ASSERT_MSG(::access(path.c_str(), accessType) == expected,
+ "access from " << id << " to path " << path
+ << (expected == 0 ? " not granted" : " unnecessarily granted")
+ << " (" << accessTypeToString.at(accessType) << ")"
+ << " for UID " << getuid());
+}
+
+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 = [&](){
+ ScopedProcessLabel spl(label, false);
+ RUNNER_ASSERT_ERRNO_MSG(0 == drop_root_privileges(uid, gid),
+ "drop_root_privileges failed.");
+
+ accessTest(label, testPath, accessType);
+ };
+
+ runInChildParentWait(fun);
+}
+
+void runAccessTest(const AppInstallHelper &app, const std::string &testPath, int accessType) {
+ auto fun = [&](){
+ RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(app.getUID(), app.getGID()) == 0,
+ "launcher failed");
+ Api::prepareAppCandidate();
+ Api::prepareApp(app.getAppId());
+ accessTest(app.getAppId(), testPath, accessType);
+ };
+
+ auto pid = runInChildParentWait(fun);
+ Api::cleanupApp(app.getAppId(), app.getUID(), pid);
+}
+
+void runAccessTest(const AppInstallHelper &app, const std::string &testPath,
+ uid_t uid, gid_t gid, int accessType) {
+ auto fun = [&](){
+ RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(uid, gid) == 0,
+ "launcher failed");
+ Api::prepareAppCandidate();
+ Api::prepareApp(app.getAppId());
+ accessTest(app.getAppId(), testPath, accessType);
+ };
+
+ auto pid = runInChildParentWait(fun);
+ Api::cleanupApp(app.getAppId(), uid, pid);
+}
+
+void runSystemAccessTest(uid_t uid, gid_t gid, const std::string &testPath, int accessType) {
+ for (const auto &label : SM_SYSTEM_LABELS)
+ runAccessTest(label, uid, gid, testPath, accessType);
+}
+
+bool isAskuserDisabled() {
+ static bool isAskuserDisabled = false;
+ static bool isChecked = false;
+
+ if (isChecked)
+ return isAskuserDisabled;
+
+ std::string sysShare = TzPlatformConfig::getPath(TZ_SYS_SHARE);
+ std::string askDisableFile = sysShare + "/askuser_disable";
+
+ isAskuserDisabled = (access(askDisableFile.c_str(), F_OK) != -1);
+ isChecked = true;
+ return isAskuserDisabled;
+}
+
+bool isPrivilegePrivacy(const std::string &priv) {
+ return (1 == privilege_info_is_privacy(priv.c_str()));
+}
+
+int countPrivacyPrivileges(const PrivilegeVector &privs) {
+ return std::count_if(privs.begin(), privs.end(), isPrivilegePrivacy);
+}
+
+int countPrivacyPrivileges(const std::vector<std::string> &privs) {
+ 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;
+
+ if (smack_check())
+ setCaps("cap_dac_override+ep cap_setgid+ep cap_sys_admin+ep cap_mac_admin+ep");
+ else
+ setCaps("cap_dac_override+ep cap_setgid+ep cap_sys_admin+ep cap_mac_admin+ep cap_setuid+ep");
+
+ return ret;
+}
+int setLauncherSecurityAttributes(TemporaryTestUser &user)
+{
+ return setLauncherSecurityAttributes(user.getUid(), user.getGid());
+}
--- /dev/null
+/*
+ * 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.
+ * 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.
+ */
+
+#pragma once
+
+#include <ftw.h>
+#include <string>
+#include <sys/capability.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <vector>
+
+#include <app_install_helper.h>
+#include <memory.h>
+#include <temp_test_user.h>
+
+DEFINE_SMARTPTR(cap_free, _cap_struct, CapsSetsUniquePtr);
+
+const int FTW_MAX_FDS = 16;
+
+int nftw_remove_labels(const char *fpath, const struct stat* /*sb*/,
+ int /*typeflag*/, struct FTW* /*ftwbuf*/);
+void check_path(const std::string &path, const Access &access,
+ bool transmute = true, bool execute = false);
+
+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);
+void runAccessTest(const AppInstallHelper &app, const std::string &testPath,
+ uid_t uid, gid_t gid, int accessType);
+void runSystemAccessTest(uid_t uid, gid_t gid, const std::string &testPath, int accessType);
+
+bool isAskuserDisabled();
+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);
SET(NETHER_TESTS_SOURCES
${PROJECT_SOURCE_DIR}/src/nether-tests/nether_tests.cpp
- ${PROJECT_SOURCE_DIR}/src/security-manager-tests/common/sm_commons.cpp
${PROJECT_SOURCE_DIR}/src/security-manager-tests/common/policy_configuration.cpp
${PROJECT_SOURCE_DIR}/src/security-manager-tests/common/template_parser.cpp
${PROJECT_SOURCE_DIR}/src/cynara-tests/common/cynara_test_client.cpp
security-privilege-manager
libtzplatform-config
sqlite3
- libcap
dbus-1
libgum
- boost
- libacl)
+ boost)
SET(TARGET_SEC_MGR_TESTS "security-manager-tests")
${PROJECT_SOURCE_DIR}/src/security-manager-tests/test_cases_prepare_app.cpp
${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/security-manager-tests/common/scoped_app_launcher.cpp
${PROJECT_SOURCE_DIR}/src/security-manager-tests/common/app_install_helper_ext.cpp
${PROJECT_SOURCE_DIR}/src/cynara-tests/common/cynara_test_client.cpp
${PROJECT_SOURCE_DIR}/src/cynara-tests/common/cynara_test_admin.cpp
+++ /dev/null
-/*
- * Copyright (c) 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.
- * 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.
- */
-
-#include <scoped_app_launcher.h>
-#include <sm_api.h>
-#include <sm_commons.h>
-#include <tests_common.h>
-#include <dpl/test/safe_cleanup.h>
-
-using namespace SecurityManagerTest;
-
-ScopedAppLauncher::ScopedAppLauncher(const AppInstallHelper& app,
- const std::function<void(void)>& runInAppContext)
- : m_uid(app.getUID()),
- m_gid(app.getGID()),
- m_appId(app.getAppId())
-{
- launch(runInAppContext);
-}
-
-ScopedAppLauncher::ScopedAppLauncher(const AppInstallHelper &app, const TemporaryTestUser &user,
- const std::function<void(void)> &runInAppContext)
-
- : m_uid(user.getUid()),
- m_gid(user.getGid()),
- m_appId(app.getAppId())
-{
-
- launch(runInAppContext);
-}
-
-void ScopedAppLauncher::launch(const std::function<void(void)> &runInAppContext)
-{
- m_pid = runInChild([&] {
- m_syncPipe.claimChildEp();
-
- RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(m_uid, m_gid) == 0,
- "launcher failed");
- Api::prepareAppCandidate();
- Api::prepareApp(m_appId);
- m_syncPipe.post();
- runInAppContext();
- m_syncPipe.wait();
- });
-
- m_syncPipe.claimParentEp();
- m_syncPipe.wait();
-}
-
-ScopedAppLauncher::~ScopedAppLauncher()
-{
- SafeCleanup::run([this]{
- m_syncPipe.post();
- waitPid(m_pid);
- });
-
- // Cleanup app even if everything else fails
- SafeCleanup::run([this]{
- Api::cleanupApp(m_appId, m_uid, m_pid);
- });
-}
+++ /dev/null
-/*
- * Copyright (c) 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.
- * 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.
- */
-#pragma once
-
-#include <functional>
-
-#include <app_install_helper.h>
-#include <synchronization_pipe.h>
-#include <temp_test_user.h>
-
-class ScopedAppLauncher final {
-public:
- explicit ScopedAppLauncher(const AppInstallHelper& app,
- const std::function<void(void)>& runInAppContext = []{});
- ScopedAppLauncher(const AppInstallHelper& app, const TemporaryTestUser& user,
- const std::function<void(void)>& runInAppContext = []{});
- ~ScopedAppLauncher();
-
- ScopedAppLauncher(const ScopedAppLauncher&) = delete;
- ScopedAppLauncher& operator=(const ScopedAppLauncher&) = delete;
-
-private:
- void launch(const std::function<void(void)>& runInAppContext);
- SynchronizationPipe m_syncPipe;
- pid_t m_pid;
- const uid_t m_uid;
- const gid_t m_gid;
- const std::string m_appId;
-};
+++ /dev/null
-/*
- * 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.
- * 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.
- */
-
-#include <cstring>
-#include <fcntl.h>
-#include <ftw.h>
-#include <string>
-#include <sys/capability.h>
-#include <sys/prctl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <cstdlib>
-
-#include <unistd.h>
-#include <utility>
-#include <vector>
-#include <unordered_map>
-
-#include <security-manager-types.h>
-#include <app-runtime.h>
-#include <privilege_info.h>
-#include <scoped_process_label.h>
-
-#include <dpl/test/test_runner.h>
-#include <memory.h>
-#include <sm_api.h>
-#include <sm_commons.h>
-
-#include <tests_common.h>
-#include "tzplatform.h"
-#include <template_parser.h>
-#include <temp_test_user.h>
-
-#include "dac.h"
-
-using namespace SecurityManagerTest;
-
-namespace {
-inline constexpr int ALLOW = 0;
-inline constexpr int DENY = -1;
-
-const std::vector<std::string> SM_SYSTEM_LABELS = {"System", "System::Privileged", "User"};
-
-int getOppositeAccessType(int accessType) noexcept {
- return accessType ^ (R_OK | W_OK | X_OK);
-}
-
-const std::unordered_map<int, const char* const> accessTypeToString {
- std::make_pair(0, "F_OK"),
- std::make_pair(1, "X_OK"),
- std::make_pair(2, "W_OK"),
- std::make_pair(3, "W_OK|X_OK"),
- std::make_pair(4, "R_OK"),
- std::make_pair(5, "R_OK|X_OK"),
- std::make_pair(6, "R_OK|W_OK"),
- std::make_pair(7, "R_OK|W_OK|X_OK")
-};
-
-// Common DB/nftw checks
-
-// nftw doesn't allow passing user data to functions. Work around by using global variable
-Access nftw_expected_access;
-bool nftw_expected_transmute;
-bool nftw_expected_exec;
-
-int nftw_check_sm_access(const char *fpath,
- const struct stat *sb,
- int /*typeflag*/,
- struct FTW* /*ftwbuf*/)
-{
- if (smack_check()) {
- int result;
- CStringPtr labelPtr;
- char* label = nullptr;
-
- /* ACCESS */
- result = smack_lgetlabel(fpath, &label, SMACK_LABEL_ACCESS);
- RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
- labelPtr.reset(label);
- RUNNER_ASSERT_MSG(label != nullptr, "ACCESS label on " << fpath << " is not set");
- RUNNER_ASSERT_MSG(nftw_expected_access.label == label, "ACCESS label on " << fpath << " is incorrect"
- " (should be '" << nftw_expected_access.label << "' and is '" << label << "')");
-
- /* EXEC */
- result = smack_lgetlabel(fpath, &label, SMACK_LABEL_EXEC);
- RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
- labelPtr.reset(label);
-
- if (S_ISREG(sb->st_mode) && (sb->st_mode & S_IXUSR) && nftw_expected_exec) {
- RUNNER_ASSERT_MSG(label != nullptr, "EXEC label on " << fpath << " is not set");
- RUNNER_ASSERT_MSG(nftw_expected_access.label == label, "Incorrect EXEC label on executable file " << fpath);
- } else
- RUNNER_ASSERT_MSG(label == nullptr, "EXEC label on " << fpath << " is set");
-
-
- /* TRANSMUTE */
- result = smack_lgetlabel(fpath, &label, SMACK_LABEL_TRANSMUTE);
- RUNNER_ASSERT_MSG(result == 0, "Could not get label for the path");
- labelPtr.reset(label);
-
- if (S_ISDIR(sb->st_mode) && nftw_expected_transmute) {
- RUNNER_ASSERT_MSG(label != nullptr, "TRANSMUTE label on " << fpath << " is not set at all");
- RUNNER_ASSERT_MSG(strcmp(label, "TRUE") == 0,
- "TRANSMUTE label on " << fpath << " is not set properly: '" << label << "'");
- } else {
- RUNNER_ASSERT_MSG(label == nullptr, "TRANSMUTE label on " << fpath << " is set");
- }
- }
-
- if (nftw_expected_access.dac.has_value())
- CheckDac(fpath, *nftw_expected_access.dac);
-
- return 0;
-}
-
-} // namespace
-
-int nftw_remove_labels(const char *fpath, const struct stat* /*sb*/,
- int /*typeflag*/, struct FTW* /*ftwbuf*/)
-{
-#if SMACK_ENABLED
- smack_lsetlabel(fpath, nullptr, SMACK_LABEL_ACCESS);
- smack_lsetlabel(fpath, nullptr, SMACK_LABEL_EXEC);
- smack_lsetlabel(fpath, nullptr, SMACK_LABEL_TRANSMUTE);
-#else
- (void)fpath;
-#endif
-
- return 0;
-}
-
-void check_path(const std::string &path, const Access &access, bool transmute, bool execute) {
- nftw_expected_access = access;
- nftw_expected_transmute = transmute;
- nftw_expected_exec = execute;
-
- // check labels
- int result = nftw(path.c_str(), &nftw_check_sm_access, FTW_MAX_FDS, FTW_PHYS);
- RUNNER_ASSERT_MSG(result == 0, "Unable to check Smack labels for " << path);
-}
-
-CapsSetsUniquePtr setCaps(const char *cap_string)
-{
- CapsSetsUniquePtr caps(cap_init());
- caps.reset(cap_from_text(cap_string));
- RUNNER_ASSERT_MSG(caps, "can't convert capabilities from text");
- int result = cap_set_proc(caps.get());
- RUNNER_ASSERT_MSG(result == 0, "can't set capabilities. Result: " << result);
- return caps;
-}
-
-void accessCheck(const std::string &id, const std::string &path, int accessType,
- int expected)
-{
- RUNNER_ASSERT_MSG(::access(path.c_str(), accessType) == expected,
- "access from " << id << " to path " << path
- << (expected == 0 ? " not granted" : " unnecessarily granted")
- << " (" << accessTypeToString.at(accessType) << ")"
- << " for UID " << getuid());
-}
-
-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 = [&](){
- ScopedProcessLabel spl(label, false);
- RUNNER_ASSERT_ERRNO_MSG(0 == drop_root_privileges(uid, gid),
- "drop_root_privileges failed.");
-
- accessTest(label, testPath, accessType);
- };
-
- runInChildParentWait(fun);
-}
-
-void runAccessTest(const AppInstallHelper &app, const std::string &testPath, int accessType) {
- auto fun = [&](){
- RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(app.getUID(), app.getGID()) == 0,
- "launcher failed");
- Api::prepareAppCandidate();
- Api::prepareApp(app.getAppId());
- accessTest(app.getAppId(), testPath, accessType);
- };
-
- auto pid = runInChildParentWait(fun);
- Api::cleanupApp(app.getAppId(), app.getUID(), pid);
-}
-
-void runAccessTest(const AppInstallHelper &app, const std::string &testPath,
- uid_t uid, gid_t gid, int accessType) {
- auto fun = [&](){
- RUNNER_ASSERT_ERRNO_MSG(setLauncherSecurityAttributes(uid, gid) == 0,
- "launcher failed");
- Api::prepareAppCandidate();
- Api::prepareApp(app.getAppId());
- accessTest(app.getAppId(), testPath, accessType);
- };
-
- auto pid = runInChildParentWait(fun);
- Api::cleanupApp(app.getAppId(), uid, pid);
-}
-
-void runSystemAccessTest(uid_t uid, gid_t gid, const std::string &testPath, int accessType) {
- for (const auto &label : SM_SYSTEM_LABELS)
- runAccessTest(label, uid, gid, testPath, accessType);
-}
-
-bool isAskuserDisabled() {
- static bool isAskuserDisabled = false;
- static bool isChecked = false;
-
- if (isChecked)
- return isAskuserDisabled;
-
- std::string sysShare = TzPlatformConfig::getPath(TZ_SYS_SHARE);
- std::string askDisableFile = sysShare + "/askuser_disable";
-
- isAskuserDisabled = (access(askDisableFile.c_str(), F_OK) != -1);
- isChecked = true;
- return isAskuserDisabled;
-}
-
-bool isPrivilegePrivacy(const std::string &priv) {
- return (1 == privilege_info_is_privacy(priv.c_str()));
-}
-
-int countPrivacyPrivileges(const PrivilegeVector &privs) {
- return std::count_if(privs.begin(), privs.end(), isPrivilegePrivacy);
-}
-
-int countPrivacyPrivileges(const std::vector<std::string> &privs) {
- 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;
-
- if (smack_check())
- setCaps("cap_dac_override+ep cap_setgid+ep cap_sys_admin+ep cap_mac_admin+ep");
- else
- setCaps("cap_dac_override+ep cap_setgid+ep cap_sys_admin+ep cap_mac_admin+ep cap_setuid+ep");
-
- return ret;
-}
-int setLauncherSecurityAttributes(TemporaryTestUser &user)
-{
- return setLauncherSecurityAttributes(user.getUid(), user.getGid());
-}
+++ /dev/null
-/*
- * 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.
- * 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.
- */
-
-#pragma once
-
-#include <ftw.h>
-#include <string>
-#include <sys/capability.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <vector>
-
-#include <app_install_helper.h>
-#include <memory.h>
-#include <temp_test_user.h>
-
-DEFINE_SMARTPTR(cap_free, _cap_struct, CapsSetsUniquePtr);
-
-const int FTW_MAX_FDS = 16;
-
-int nftw_remove_labels(const char *fpath, const struct stat* /*sb*/,
- int /*typeflag*/, struct FTW* /*ftwbuf*/);
-void check_path(const std::string &path, const Access &access,
- bool transmute = true, bool execute = false);
-
-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);
-void runAccessTest(const AppInstallHelper &app, const std::string &testPath,
- uid_t uid, gid_t gid, int accessType);
-void runSystemAccessTest(uid_t uid, gid_t gid, const std::string &testPath, int accessType);
-
-bool isAskuserDisabled();
-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);
* limitations under the License.
*/
-#include "common/sm_commons.h"
+#include "sm_commons.h"
#include <ftw.h>
#include <string>
#include <sys/smack.h>