/****************************************************************************** * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. * iSulad licensed under the Mulan PSL v1. * You can use this software according to the terms and conditions of the Mulan PSL v1. * You may obtain a copy of Mulan PSL v1 at: * http://license.coscl.org.cn/MulanPSL * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR * PURPOSE. * See the Mulan PSL v1 for more details. * Author: wujing * Create: 2020-02-14 * Description: provide selinux label unit test ******************************************************************************/ #include "selinux_label.h" #include #include #include #include #include #include #include #include #include #include "namespace_mock.h" #include "utils.h" using namespace std; class SELinuxLabelUnitTest : public testing::Test { protected: void SetUp() override { selinux_state_init(); } void TearDown() override { std::cout << "selinux_state is the resident memory of the daemon." << " The process exits and the memory is automatically released." << std::endl; } }; TEST_F(SELinuxLabelUnitTest, test_init_label_normal) { const char *disable_label[] = { "disable" }; const char *user_label[] = { "user:fakeuser" }; const char *role_label[] = { "role:fakerole" }; const char *type_label[] = { "type:faketype" }; const char *level_label[] = { "level:s0:c1,c2" }; const char *full_label[] = { "user:fakeuser", "level:s0:c1,c2", "type:faketype", "role:fakerole" }; std::vector> normal { std::make_tuple(disable_label, 1, 0, "", ""), std::make_tuple(user_label, 1, 0, "fakeuser:system_r:container_t:s0", "fakeuser:object_r:container_file_t:s0"), std::make_tuple(role_label, 1, 0, "system_u:fakerole:container_t:s0", "system_u:object_r:container_file_t:s0"), std::make_tuple(type_label, 1, 0, "system_u:system_r:faketype:s0", "system_u:object_r:container_file_t:s0"), std::make_tuple(level_label, 1, 0, "system_u:system_r:container_t:s0:c1,c2", "system_u:object_r:container_file_t:s0:c1,c2"), std::make_tuple(full_label, 4, 0, "fakeuser:fakerole:faketype:s0:c1,c2", "fakeuser:object_r:container_file_t:s0:c1,c2"), std::make_tuple(nullptr, 0, 0, "system_u:system_r:container_t:s0", "system_u:object_r:container_file_t:s0"), }; if (!is_selinux_enabled()) { SUCCEED() << "WARNING: The current machine does not support SELinux"; return; } for (const auto &elem : normal) { char *process_label = nullptr; char *mount_label = nullptr; ASSERT_EQ(init_label(std::get<0>(elem), std::get<1>(elem), &process_label, &mount_label), std::get<2>(elem)); if (!std::get<3>(elem).empty()) { std::string processLabel { process_label }; processLabel.resize(std::get<3>(elem).size()); ASSERT_STREQ(processLabel.c_str(), std::get<3>(elem).c_str()); free(process_label); } else { ASSERT_STREQ(process_label, nullptr); } if (!std::get<4>(elem).empty()) { std::string mountLabel { mount_label }; mountLabel.resize(std::get<4>(elem).size()); ASSERT_STREQ(mountLabel.c_str(), std::get<4>(elem).c_str()); free(mount_label); } else { ASSERT_STREQ(mount_label, nullptr); } } } TEST_F(SELinuxLabelUnitTest, test_init_label_abnormal) { const char *invalid_key_label[] = { "xxx" }; const char *invalid_value_label[] = { "user:" }; std::vector> normal { std::make_tuple(invalid_key_label, 1, -1, "", ""), std::make_tuple(invalid_value_label, 1, -1, "", ""), }; if (!is_selinux_enabled()) { SUCCEED() << "WARNING: The current machine does not support SELinux"; return; } for (const auto &elem : normal) { char *process_label = nullptr; char *mount_label = nullptr; ASSERT_EQ(init_label(std::get<0>(elem), std::get<1>(elem), &process_label, &mount_label), std::get<2>(elem)); ASSERT_STREQ(process_label, nullptr); ASSERT_STREQ(mount_label, nullptr); } } TEST(SELinuxLabelUnitTestWithoutMock, test_dup_security_opt) { const char *label = "system_u:object_r:container_file_t:s0"; char **dst = nullptr; size_t len; ASSERT_EQ(dup_security_opt(label, &dst, &len), 0); ASSERT_EQ(len, 4); ASSERT_STREQ(dst[0], "user:system_u"); ASSERT_STREQ(dst[1], "role:object_r"); ASSERT_STREQ(dst[2], "type:container_file_t"); ASSERT_STREQ(dst[3], "level:s0"); util_free_array(dst); dst = nullptr; len = 0; ASSERT_EQ(dup_security_opt(nullptr, &dst, &len), 0); ASSERT_EQ(dst, nullptr); } class SELinuxRelabelUnitTest : public testing::Test { protected: void SetUp() override { CreateTestedObjects(); } void TearDown() override { ClearTestedObjects(); } private: void CreateTestedObjects() { struct stat st; if (lstat(m_testDir.c_str(), &st) < 0) { (void)mkdir(m_testDir.c_str(), S_IRUSR | S_IWUSR | S_IXUSR | S_IRWXG | S_IRWXO); } ofstream osm; osm.open(m_testFile); osm << "SELinux unit test"; osm.close(); } void ClearTestedObjects() { remove(m_testFile.c_str()); rmdir(m_testDir.c_str()); } protected: std::string m_testDir { "./test_dir" }; std::string m_testFile { m_testDir + "/file" }; }; TEST_F(SELinuxRelabelUnitTest, test_relabel_normal) { std::vector> normal { std::make_tuple("system_u:object_r:container_file_t:s0:c100,c200", false, 0, "system_u:object_r:container_file_t:s0:c100,c200"), std::make_tuple("system_u:object_r:container_file_t:s0:c300,c300", false, 0, "system_u:object_r:container_file_t:s0:c300"), std::make_tuple("system_u:object_r:container_file_t:s0:c100,c200", true, 0, "system_u:object_r:container_file_t:s0"), std::make_tuple("system_u:object_r:container_file_t:s0:c300,c300", true, 0, "system_u:object_r:container_file_t:s0"), }; if (!is_selinux_enabled()) { SUCCEED() << "WARNING: The current machine does not support SELinux"; return; } for (const auto &elem : normal) { char *context = nullptr; ASSERT_EQ(relabel(m_testDir.c_str(), std::get<0>(elem).c_str(), std::get<1>(elem)), std::get<2>(elem)); ASSERT_GE(lgetfilecon(m_testFile.c_str(), &context), 0); ASSERT_STREQ(context, std::get<3>(elem).c_str()); freecon(context); } } TEST_F(SELinuxRelabelUnitTest, test_relabel_abnormal) { std::vector> abnormal { // exclude path test std::make_tuple("/", "system_u:object_r:root_t:s0", true, -1), std::make_tuple("/usr", "system_u:object_r:usr_t:s0", true, -1), std::make_tuple("/etc", "system_u:object_r:etc_t:s0", true, -1), std::make_tuple("/tmp", "system_u:object_r:tmp_t:s0", true, -1), std::make_tuple("/home", "system_u:object_r:home_root_t:s0", true, -1), std::make_tuple("/run", "system_u:object_r:var_run_t:s0", true, -1), std::make_tuple("/var", "system_u:object_r:var_t:s0", true, -1), std::make_tuple("/root", "system_u:object_r:admin_home_t:s0", true, -1), // bad prefix test std::make_tuple("/usr/xxx", "system_u:object_r:usr_t:s0", true, -1), }; if (!is_selinux_enabled()) { SUCCEED() << "WARNING: The current machine does not support SELinux"; return; } for (const auto &elem : abnormal) { ASSERT_EQ(relabel(std::get<0>(elem).c_str(), std::get<1>(elem).c_str(), std::get<2>(elem)), std::get<3>(elem)); } } TEST_F(SELinuxRelabelUnitTest, test_get_disable_security_opt) { char **labels = nullptr; size_t labels_len; ASSERT_EQ(get_disable_security_opt(&labels, &labels_len), 0); ASSERT_EQ(labels_len, 1); ASSERT_NE(labels[0], "label=disable"); util_free_array(labels); }