1d9f0492fSopenharmony_ci/* 2d9f0492fSopenharmony_ci * Copyright (c) 2022-2024 Huawei Device Co., Ltd. 3d9f0492fSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4d9f0492fSopenharmony_ci * you may not use this file except in compliance with the License. 5d9f0492fSopenharmony_ci * You may obtain a copy of the License at 6d9f0492fSopenharmony_ci * 7d9f0492fSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8d9f0492fSopenharmony_ci * 9d9f0492fSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10d9f0492fSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11d9f0492fSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12d9f0492fSopenharmony_ci * See the License for the specific language governing permissions and 13d9f0492fSopenharmony_ci * limitations under the License. 14d9f0492fSopenharmony_ci */ 15d9f0492fSopenharmony_ci#include "selinux_adp.h" 16d9f0492fSopenharmony_ci 17d9f0492fSopenharmony_ci#include <errno.h> 18d9f0492fSopenharmony_ci 19d9f0492fSopenharmony_ci#include "init_error.h" 20d9f0492fSopenharmony_ci#include "init_hook.h" 21d9f0492fSopenharmony_ci#include "init_module_engine.h" 22d9f0492fSopenharmony_ci#include "plugin_adapter.h" 23d9f0492fSopenharmony_ci#include "securec.h" 24d9f0492fSopenharmony_ci 25d9f0492fSopenharmony_ci#include <policycoreutils.h> 26d9f0492fSopenharmony_ci#include <selinux/label.h> 27d9f0492fSopenharmony_ci#include <selinux/restorecon.h> 28d9f0492fSopenharmony_ci 29d9f0492fSopenharmony_cienum { 30d9f0492fSopenharmony_ci CMD_LOAD_POLICY = 0, 31d9f0492fSopenharmony_ci CMD_SET_SERVICE_CONTEXTS = 1, 32d9f0492fSopenharmony_ci CMD_SET_SOCKET_CONTEXTS = 2, 33d9f0492fSopenharmony_ci CMD_RESTORE_INDEX = 3, 34d9f0492fSopenharmony_ci CMD_RESTORE_INDEX_FORCE = 4, 35d9f0492fSopenharmony_ci CMD_RESTORE_INDEX_SKIP = 5, 36d9f0492fSopenharmony_ci}; 37d9f0492fSopenharmony_ci 38d9f0492fSopenharmony_ciextern char *__progname; 39d9f0492fSopenharmony_ci 40d9f0492fSopenharmony_cistatic int LoadSelinuxPolicy(int id, const char *name, int argc, const char **argv) 41d9f0492fSopenharmony_ci{ 42d9f0492fSopenharmony_ci int ret; 43d9f0492fSopenharmony_ci char processContext[MAX_SECON_LEN]; 44d9f0492fSopenharmony_ci 45d9f0492fSopenharmony_ci UNUSED(id); 46d9f0492fSopenharmony_ci UNUSED(name); 47d9f0492fSopenharmony_ci UNUSED(argc); 48d9f0492fSopenharmony_ci UNUSED(argv); 49d9f0492fSopenharmony_ci PLUGIN_LOGI("LoadSelinuxPolicy "); 50d9f0492fSopenharmony_ci // load selinux policy and context 51d9f0492fSopenharmony_ci if (LoadPolicy() < 0) { 52d9f0492fSopenharmony_ci PLUGIN_LOGE("main, load_policy failed."); 53d9f0492fSopenharmony_ci } else { 54d9f0492fSopenharmony_ci PLUGIN_LOGI("main, load_policy success."); 55d9f0492fSopenharmony_ci } 56d9f0492fSopenharmony_ci 57d9f0492fSopenharmony_ci ret = snprintf_s(processContext, sizeof(processContext), sizeof(processContext) - 1, "u:r:%s:s0", __progname); 58d9f0492fSopenharmony_ci if (ret == -1) { 59d9f0492fSopenharmony_ci setcon("u:r:init:s0"); 60d9f0492fSopenharmony_ci } else { 61d9f0492fSopenharmony_ci setcon(processContext); 62d9f0492fSopenharmony_ci } 63d9f0492fSopenharmony_ci (void)RestoreconRecurse("/dev"); 64d9f0492fSopenharmony_ci return 0; 65d9f0492fSopenharmony_ci} 66d9f0492fSopenharmony_ci 67d9f0492fSopenharmony_cistatic int SetServiceContent(int id, const char *name, int argc, const char **argv) 68d9f0492fSopenharmony_ci{ 69d9f0492fSopenharmony_ci PLUGIN_CHECK(name != NULL && argc >= 1 && argv != NULL, return -1, "Invalid parameter"); 70d9f0492fSopenharmony_ci ServiceExtData *data = GetServiceExtData(argv[0], HOOK_ID_SELINUX); 71d9f0492fSopenharmony_ci char *label = "u:r:limit_domain:s0"; 72d9f0492fSopenharmony_ci if (data != NULL) { 73d9f0492fSopenharmony_ci label = (char *)data->data; 74d9f0492fSopenharmony_ci } else { 75d9f0492fSopenharmony_ci PLUGIN_LOGE("Please set secon field in service %s's cfg file, limit_domain will be blocked", argv[0]); 76d9f0492fSopenharmony_ci } 77d9f0492fSopenharmony_ci 78d9f0492fSopenharmony_ci if (setexeccon(label) < 0) { 79d9f0492fSopenharmony_ci PLUGIN_LOGE("Service error %d %s, failed to set secon %s.", errno, argv[0], label); 80d9f0492fSopenharmony_ci#ifndef STARTUP_INIT_TEST 81d9f0492fSopenharmony_ci _exit(INIT_EEXEC_CONTENT); 82d9f0492fSopenharmony_ci#endif 83d9f0492fSopenharmony_ci } else { 84d9f0492fSopenharmony_ci PLUGIN_LOGV("Service info %s, set secon %s.", argv[0], label); 85d9f0492fSopenharmony_ci } 86d9f0492fSopenharmony_ci return 0; 87d9f0492fSopenharmony_ci} 88d9f0492fSopenharmony_ci 89d9f0492fSopenharmony_cistatic int SetSockCreateCon(int id, const char *name, int argc, const char **argv) 90d9f0492fSopenharmony_ci{ 91d9f0492fSopenharmony_ci PLUGIN_CHECK(name != NULL, return -1, "Invalid parameter"); 92d9f0492fSopenharmony_ci if (argc == 0) { 93d9f0492fSopenharmony_ci setsockcreatecon(NULL); 94d9f0492fSopenharmony_ci return 0; 95d9f0492fSopenharmony_ci } 96d9f0492fSopenharmony_ci PLUGIN_CHECK(argc >= 1 && argv != NULL, return -1, "Invalid parameter"); 97d9f0492fSopenharmony_ci ServiceExtData *data = GetServiceExtData(argv[0], HOOK_ID_SELINUX); 98d9f0492fSopenharmony_ci if (data != NULL) { 99d9f0492fSopenharmony_ci if (setsockcreatecon((char *)data->data) < 0) { 100d9f0492fSopenharmony_ci PLUGIN_LOGE("failed to set socket context %s's secon (%s).", argv[0], (char *)data->data); 101d9f0492fSopenharmony_ci#ifndef STARTUP_INIT_TEST 102d9f0492fSopenharmony_ci _exit(PROCESS_EXIT_CODE); 103d9f0492fSopenharmony_ci#endif 104d9f0492fSopenharmony_ci } 105d9f0492fSopenharmony_ci } 106d9f0492fSopenharmony_ci 107d9f0492fSopenharmony_ci return 0; 108d9f0492fSopenharmony_ci} 109d9f0492fSopenharmony_ci 110d9f0492fSopenharmony_cistatic int RestoreContentRecurse(int id, const char *name, int argc, const char **argv) 111d9f0492fSopenharmony_ci{ 112d9f0492fSopenharmony_ci PLUGIN_CHECK(name != NULL && argc >= 1 && argv != NULL, return -1, "Invalid parameter"); 113d9f0492fSopenharmony_ci PLUGIN_LOGV("RestoreContentRecurse path %s", argv[0]); 114d9f0492fSopenharmony_ci if (RestoreconRecurse(argv[0]) && errno != 0) { 115d9f0492fSopenharmony_ci PLUGIN_LOGE("restoreContentRecurse failed for '%s', err %d.", argv[0], errno); 116d9f0492fSopenharmony_ci } 117d9f0492fSopenharmony_ci return 0; 118d9f0492fSopenharmony_ci} 119d9f0492fSopenharmony_ci 120d9f0492fSopenharmony_cistatic int RestoreContentRecurseForce(int id, const char *name, int argc, const char **argv) 121d9f0492fSopenharmony_ci{ 122d9f0492fSopenharmony_ci PLUGIN_CHECK(name != NULL && argc >= 1 && argv != NULL, return -1, "Invalid parameter"); 123d9f0492fSopenharmony_ci PLUGIN_LOGV("RestoreContentRecurseForce path %s", argv[0]); 124d9f0492fSopenharmony_ci if (RestoreconRecurseForce(argv[0]) && errno != 0) { 125d9f0492fSopenharmony_ci PLUGIN_LOGE("RestoreContentRecurseForce failed for '%s', err %d.", argv[0], errno); 126d9f0492fSopenharmony_ci } 127d9f0492fSopenharmony_ci return 0; 128d9f0492fSopenharmony_ci} 129d9f0492fSopenharmony_ci 130d9f0492fSopenharmony_cistatic int RestoreContentRecurseSkipElx(int id, const char *name, int argc, const char **argv) 131d9f0492fSopenharmony_ci{ 132d9f0492fSopenharmony_ci PLUGIN_CHECK(name != NULL && argc >= 1 && argv != NULL, return -1, "Invalid parameter"); 133d9f0492fSopenharmony_ci PLUGIN_LOGV("RestoreContentRecurseSkipElx path %s", argv[0]); 134d9f0492fSopenharmony_ci if (RestoreconCommon(argv[0], SELINUX_RESTORECON_REALPATH | 135d9f0492fSopenharmony_ci SELINUX_RESTORECON_RECURSE | SELINUX_RESTORECON_SKIPELX, 1) && errno != 0) { 136d9f0492fSopenharmony_ci PLUGIN_LOGE("RestoreContentRecurseSkipElx failed for '%s', err %d.", argv[0], errno); 137d9f0492fSopenharmony_ci } 138d9f0492fSopenharmony_ci return 0; 139d9f0492fSopenharmony_ci} 140d9f0492fSopenharmony_ci 141d9f0492fSopenharmony_cistatic int32_t g_selinuxAdpCmdIds[CMD_RESTORE_INDEX_SKIP + 1] = {0}; // 6 cmd count 142d9f0492fSopenharmony_cistatic void SelinuxAdpInit(void) 143d9f0492fSopenharmony_ci{ 144d9f0492fSopenharmony_ci g_selinuxAdpCmdIds[CMD_LOAD_POLICY] = AddCmdExecutor("loadSelinuxPolicy", LoadSelinuxPolicy); 145d9f0492fSopenharmony_ci g_selinuxAdpCmdIds[CMD_SET_SERVICE_CONTEXTS] = AddCmdExecutor("setServiceContent", SetServiceContent); 146d9f0492fSopenharmony_ci g_selinuxAdpCmdIds[CMD_SET_SOCKET_CONTEXTS] = AddCmdExecutor("setSockCreateCon", SetSockCreateCon); 147d9f0492fSopenharmony_ci g_selinuxAdpCmdIds[CMD_RESTORE_INDEX] = AddCmdExecutor("restoreContentRecurse", RestoreContentRecurse); 148d9f0492fSopenharmony_ci g_selinuxAdpCmdIds[CMD_RESTORE_INDEX_FORCE] = 149d9f0492fSopenharmony_ci AddCmdExecutor("restoreContentRecurseForce", RestoreContentRecurseForce); 150d9f0492fSopenharmony_ci g_selinuxAdpCmdIds[CMD_RESTORE_INDEX_SKIP] = 151d9f0492fSopenharmony_ci AddCmdExecutor("restoreContentRecurseSkipElx", RestoreContentRecurseSkipElx); 152d9f0492fSopenharmony_ci} 153d9f0492fSopenharmony_ci 154d9f0492fSopenharmony_cistatic void SelinuxAdpExit(void) 155d9f0492fSopenharmony_ci{ 156d9f0492fSopenharmony_ci if (g_selinuxAdpCmdIds[CMD_LOAD_POLICY] != -1) { 157d9f0492fSopenharmony_ci RemoveCmdExecutor("loadSelinuxPolicy", g_selinuxAdpCmdIds[CMD_LOAD_POLICY]); 158d9f0492fSopenharmony_ci } 159d9f0492fSopenharmony_ci if (g_selinuxAdpCmdIds[CMD_SET_SERVICE_CONTEXTS] != -1) { 160d9f0492fSopenharmony_ci RemoveCmdExecutor("setServiceContent", g_selinuxAdpCmdIds[CMD_SET_SERVICE_CONTEXTS]); 161d9f0492fSopenharmony_ci } 162d9f0492fSopenharmony_ci if (g_selinuxAdpCmdIds[CMD_SET_SOCKET_CONTEXTS] != -1) { 163d9f0492fSopenharmony_ci RemoveCmdExecutor("setSockCreateCon", g_selinuxAdpCmdIds[CMD_SET_SOCKET_CONTEXTS]); 164d9f0492fSopenharmony_ci } 165d9f0492fSopenharmony_ci if (g_selinuxAdpCmdIds[CMD_RESTORE_INDEX] != -1) { 166d9f0492fSopenharmony_ci RemoveCmdExecutor("restoreContentRecurse", g_selinuxAdpCmdIds[CMD_RESTORE_INDEX]); 167d9f0492fSopenharmony_ci } 168d9f0492fSopenharmony_ci if (g_selinuxAdpCmdIds[CMD_RESTORE_INDEX_FORCE] != -1) { 169d9f0492fSopenharmony_ci RemoveCmdExecutor("restoreContentRecurseForce", g_selinuxAdpCmdIds[CMD_RESTORE_INDEX_FORCE]); 170d9f0492fSopenharmony_ci } 171d9f0492fSopenharmony_ci if (g_selinuxAdpCmdIds[CMD_RESTORE_INDEX_SKIP] != -1) { 172d9f0492fSopenharmony_ci RemoveCmdExecutor("restoreContentRecurseSkipElx", g_selinuxAdpCmdIds[CMD_RESTORE_INDEX_SKIP]); 173d9f0492fSopenharmony_ci } 174d9f0492fSopenharmony_ci} 175d9f0492fSopenharmony_ci 176d9f0492fSopenharmony_ciMODULE_CONSTRUCTOR(void) 177d9f0492fSopenharmony_ci{ 178d9f0492fSopenharmony_ci PLUGIN_LOGI("Selinux adapter plug-in init now ..."); 179d9f0492fSopenharmony_ci SelinuxAdpInit(); 180d9f0492fSopenharmony_ci} 181d9f0492fSopenharmony_ci 182d9f0492fSopenharmony_ciMODULE_DESTRUCTOR(void) 183d9f0492fSopenharmony_ci{ 184d9f0492fSopenharmony_ci if (getpid() != 1) { 185d9f0492fSopenharmony_ci return; 186d9f0492fSopenharmony_ci } 187d9f0492fSopenharmony_ci PLUGIN_LOGI("Selinux adapter plug-in exit now ..."); 188d9f0492fSopenharmony_ci SelinuxAdpExit(); 189d9f0492fSopenharmony_ci} 190