Add tests for permissible file repair 42/299442/3
authorFilip Skrzeczkowski <f.skrzeczkow@samsung.com>
Thu, 28 Sep 2023 11:25:42 +0000 (13:25 +0200)
committerFilip Skrzeczkowski <f.skrzeczkow@samsung.com>
Wed, 11 Oct 2023 13:00:14 +0000 (15:00 +0200)
The client library repair is tested via the client-label-monitor while
the service repair is tested by invoking app installs and uninstalls.
Both global and local permissible files are tested

Change-Id: Ib926f649d41e38cf7f0c34212db71a854fe156f8

src/security-manager-tests/CMakeLists.txt
src/security-manager-tests/test_cases_permissible_file_repair.cpp [new file with mode: 0644]

index 703d034f63c7bf5043b79fc4855f361e5dc5ead5..2864353a1013b9a0451bac05d423141839fa5dc5 100644 (file)
@@ -53,6 +53,7 @@ SET(SEC_MGR_SOURCES
     ${PROJECT_SOURCE_DIR}/src/security-manager-tests/test_cases_dyntransition.cpp
     ${PROJECT_SOURCE_DIR}/src/security-manager-tests/test_cases_nss.cpp
     ${PROJECT_SOURCE_DIR}/src/security-manager-tests/test_cases_paths.cpp
+    ${PROJECT_SOURCE_DIR}/src/security-manager-tests/test_cases_permissible_file_repair.cpp
     ${PROJECT_SOURCE_DIR}/src/security-manager-tests/test_cases_privacy_manager.cpp
     ${PROJECT_SOURCE_DIR}/src/security-manager-tests/test_cases_private_sharing.cpp
     ${PROJECT_SOURCE_DIR}/src/security-manager-tests/test_cases_public_sharing.cpp
diff --git a/src/security-manager-tests/test_cases_permissible_file_repair.cpp b/src/security-manager-tests/test_cases_permissible_file_repair.cpp
new file mode 100644 (file)
index 0000000..0dc3010
--- /dev/null
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2023 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 <fstream>
+#include <poll.h>
+#include <string>
+#include <sys/prctl.h>
+#include <sys/smack.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <app_install_helper.h>
+#include <dpl/test/test_runner.h>
+#include <label_generator.h>
+#include <memory.h>
+#include <message_pipe.h>
+#include <scoped_installer.h>
+#include <sm_api.h>
+#include <sm_commons.h>
+#include <sm_label_monitor.h>
+#include <synchronization_pipe.h>
+#include <temp_test_user.h>
+#include <tests_common.h>
+
+using namespace SecurityManagerTest;
+
+static const char*   localStateInstallDir = "/opt/var/security-manager";
+static const char*   appsLabelsFile = "apps-labels";
+static const char*   globalPermissibleFile = "/opt/var/security-manager/apps-labels";
+static const char*   hashMarker = "-SHA-1";
+static const int     hashMarkerLength = strlen(hashMarker);
+static constexpr int hashLength = 40;
+
+static std::string getPermissibleFileLocation(uid_t uid)
+{
+    return std::string(localStateInstallDir) + "/" + std::to_string(uid)
+        + "/" + appsLabelsFile;
+}
+
+static void writeToPermissibleFile(const std::string &path)
+{
+    std::string content = "some text\n";
+    std::string hash(hashLength, 'g');
+
+    std::ofstream os(path);
+    RUNNER_ASSERT_ERRNO_MSG(os.is_open(), "open file");
+    os << hashMarker << " " << hash << "\n" << content;
+}
+
+static void corruptFile()
+{
+    writeToPermissibleFile(globalPermissibleFile);
+}
+
+static void corruptFile(uid_t uid)
+{
+    auto path = getPermissibleFileLocation(uid);
+    writeToPermissibleFile(path);
+}
+
+static void clientMonitorProcess(const TemporaryTestUser &testUser)
+{
+    pid_t pid = fork();
+    RUNNER_ASSERT_ERRNO_MSG(pid >= 0, "Fork failed");
+    if (pid != 0) { //parent process
+        waitPid(pid);
+    } else { //child process
+        setCaps("cap_mac_admin+ep cap_setuid+ep cap_setgid+ep");
+        RUNNER_ASSERT_ERRNO_MSG(prctl(PR_SET_KEEPCAPS, 1, 0, 0) == 0, "prctl keeping caps failed");
+
+        RUNNER_ASSERT_ERRNO_MSG(drop_root_privileges(testUser.getUid(), testUser.getGid()) == 0,
+                                "drop_root_privileges failed");
+
+        setCaps("cap_mac_admin+ep");
+        LabelMonitor monitor;
+
+        Api::labelsProcess(monitor);
+        setCaps("cap_mac_admin-eip");
+    }
+}
+
+RUNNER_TEST_GROUP_INIT(SECURITY_MANAGER_PERMISSIBLE_FILE_REPAIR)
+
+RUNNER_CHILD_TEST(security_manager_121a_repair_permissible_file_daemon_global)
+{
+    AppInstallHelper appGlobal("sm_test_121a_global");
+    appGlobal.setInstallType(SM_APP_INSTALL_GLOBAL);
+    {
+        // Check for both install and uninstall
+        corruptFile();
+        ScopedInstaller appLocalInstall(appGlobal);
+        corruptFile();
+    }
+}
+
+RUNNER_CHILD_TEST(security_manager_121b_repair_permissible_file_daemon_local)
+{
+    TemporaryTestUser testUser("sm_test_121b_user_name", GUM_USERTYPE_NORMAL, false);
+    testUser.create();
+    uid_t uid = testUser.getUid();
+
+    AppInstallHelper appLocal("sm_test_121b_local", uid);
+    appLocal.setInstallType(SM_APP_INSTALL_LOCAL);
+    {
+        // Check for both install and uninstall
+        corruptFile(uid);
+        ScopedInstaller appLocalInstall(appLocal);
+        corruptFile(uid);
+    }
+}
+
+RUNNER_CHILD_TEST(security_manager_122a_repair_permissible_file_client_global)
+{
+    TemporaryTestUser testUser("sm_test_122a_user_name", GUM_USERTYPE_NORMAL, false);
+    testUser.create();
+
+    corruptFile();
+
+    clientMonitorProcess(testUser);
+}
+
+RUNNER_CHILD_TEST(security_manager_122b_repair_permissible_file_client_local)
+{
+    TemporaryTestUser testUser("sm_test_122b_user_name", GUM_USERTYPE_NORMAL, false);
+    testUser.create();
+
+    corruptFile(testUser.getUid());
+
+    clientMonitorProcess(testUser);
+}
+
+RUNNER_CHILD_TEST(security_manager_122c_repair_permissible_file_client_both)
+{
+    TemporaryTestUser testUser("sm_test_122c_user_name", GUM_USERTYPE_NORMAL, false);
+    testUser.create();
+
+    corruptFile();
+    corruptFile(testUser.getUid());
+
+    clientMonitorProcess(testUser);
+}
\ No newline at end of file