1d9f0492fSopenharmony_ci/* 2d9f0492fSopenharmony_ci * Copyright (c) 2020-2021 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 "init_service.h" 16d9f0492fSopenharmony_ci 17d9f0492fSopenharmony_ci#include <dlfcn.h> 18d9f0492fSopenharmony_ci#include <stdlib.h> 19d9f0492fSopenharmony_ci#include <string.h> 20d9f0492fSopenharmony_ci#include <sys/param.h> 21d9f0492fSopenharmony_ci#include <sys/resource.h> 22d9f0492fSopenharmony_ci#include <unistd.h> 23d9f0492fSopenharmony_ci 24d9f0492fSopenharmony_ci#include "init_group_manager.h" 25d9f0492fSopenharmony_ci#include "init.h" 26d9f0492fSopenharmony_ci#include "init_log.h" 27d9f0492fSopenharmony_ci#include "init_param.h" 28d9f0492fSopenharmony_ci#include "init_utils.h" 29d9f0492fSopenharmony_ci#include "securec.h" 30d9f0492fSopenharmony_ci#include "token_setproc.h" 31d9f0492fSopenharmony_ci#include "nativetoken_kit.h" 32d9f0492fSopenharmony_ci#include "sandbox.h" 33d9f0492fSopenharmony_ci#include "sandbox_namespace.h" 34d9f0492fSopenharmony_ci#include "service_control.h" 35d9f0492fSopenharmony_ci 36d9f0492fSopenharmony_ci#define MIN_IMPORTANT_LEVEL (-20) 37d9f0492fSopenharmony_ci#define MAX_IMPORTANT_LEVEL 19 38d9f0492fSopenharmony_ci 39d9f0492fSopenharmony_cistatic bool g_enableSandbox = false; 40d9f0492fSopenharmony_ci 41d9f0492fSopenharmony_cistatic void WriteOomScoreAdjToService(Service *service) 42d9f0492fSopenharmony_ci{ 43d9f0492fSopenharmony_ci if (service == NULL) { 44d9f0492fSopenharmony_ci return; 45d9f0492fSopenharmony_ci } 46d9f0492fSopenharmony_ci if (IsOnDemandService(service)) { 47d9f0492fSopenharmony_ci char pidAdjPath[30]; 48d9f0492fSopenharmony_ci const char* content = "-900"; 49d9f0492fSopenharmony_ci int len = sprintf_s(pidAdjPath, sizeof(pidAdjPath), "/proc/%d/oom_score_adj", service->pid); 50d9f0492fSopenharmony_ci if (len <= 0) { 51d9f0492fSopenharmony_ci INIT_LOGE("Service(%s): format pidAdjPath (pid:%d) failed.", service->name, service->pid); 52d9f0492fSopenharmony_ci return; 53d9f0492fSopenharmony_ci } 54d9f0492fSopenharmony_ci int fd = open(pidAdjPath, O_RDWR); 55d9f0492fSopenharmony_ci if (fd < 0) { 56d9f0492fSopenharmony_ci INIT_LOGE("Service(%s): open path %s failed.", service->name, pidAdjPath); 57d9f0492fSopenharmony_ci return; 58d9f0492fSopenharmony_ci } 59d9f0492fSopenharmony_ci int ret = write(fd, content, strlen(content)); 60d9f0492fSopenharmony_ci if (ret < 0) { 61d9f0492fSopenharmony_ci INIT_LOGE("Service(%s): write content(%s) to path(%s) failed.", service->name, content, pidAdjPath); 62d9f0492fSopenharmony_ci } 63d9f0492fSopenharmony_ci close(fd); 64d9f0492fSopenharmony_ci } 65d9f0492fSopenharmony_ci} 66d9f0492fSopenharmony_ci 67d9f0492fSopenharmony_civoid NotifyServiceChange(Service *service, int status) 68d9f0492fSopenharmony_ci{ 69d9f0492fSopenharmony_ci INIT_LOGV("Notify service %s change from %d to %d", service->name, service->status, status); 70d9f0492fSopenharmony_ci service->status = status; 71d9f0492fSopenharmony_ci INIT_CHECK(status != SERVICE_IDLE, return); 72d9f0492fSopenharmony_ci char paramName[PARAM_NAME_LEN_MAX] = { 0 }; 73d9f0492fSopenharmony_ci int ret = snprintf_s(paramName, sizeof(paramName), sizeof(paramName) - 1, 74d9f0492fSopenharmony_ci "%s.%s", STARTUP_SERVICE_CTL, service->name); 75d9f0492fSopenharmony_ci INIT_ERROR_CHECK(ret > 0, return, "Failed to format service name %s.", service->name); 76d9f0492fSopenharmony_ci char statusStr[MAX_INT_LEN] = {0}; 77d9f0492fSopenharmony_ci ret = snprintf_s(statusStr, sizeof(statusStr), sizeof(statusStr) - 1, "%d", status); 78d9f0492fSopenharmony_ci INIT_ERROR_CHECK(ret > 0, return, "Failed to format service status %s.", service->name); 79d9f0492fSopenharmony_ci SystemWriteParam(paramName, statusStr); 80d9f0492fSopenharmony_ci 81d9f0492fSopenharmony_ci // write pid 82d9f0492fSopenharmony_ci ret = snprintf_s(paramName, sizeof(paramName), sizeof(paramName) - 1, 83d9f0492fSopenharmony_ci "%s.%s.pid", STARTUP_SERVICE_CTL, service->name); 84d9f0492fSopenharmony_ci INIT_ERROR_CHECK(ret > 0, return, "Failed to format service pid name %s.", service->name); 85d9f0492fSopenharmony_ci ret = snprintf_s(statusStr, sizeof(statusStr), sizeof(statusStr) - 1, 86d9f0492fSopenharmony_ci "%d", (service->pid == -1) ? 0 : service->pid); 87d9f0492fSopenharmony_ci INIT_ERROR_CHECK(ret > 0, return, "Failed to format service pid %s.", service->name); 88d9f0492fSopenharmony_ci if (status == SERVICE_STARTED) { 89d9f0492fSopenharmony_ci WriteOomScoreAdjToService(service); 90d9f0492fSopenharmony_ci } 91d9f0492fSopenharmony_ci SystemWriteParam(paramName, statusStr); 92d9f0492fSopenharmony_ci} 93d9f0492fSopenharmony_ci 94d9f0492fSopenharmony_ciint IsForbidden(const char *fieldStr) 95d9f0492fSopenharmony_ci{ 96d9f0492fSopenharmony_ci UNUSED(fieldStr); 97d9f0492fSopenharmony_ci return 0; 98d9f0492fSopenharmony_ci} 99d9f0492fSopenharmony_ci 100d9f0492fSopenharmony_ciint SetImportantValue(Service *service, const char *attrName, int value, int flag) 101d9f0492fSopenharmony_ci{ 102d9f0492fSopenharmony_ci UNUSED(attrName); 103d9f0492fSopenharmony_ci UNUSED(flag); 104d9f0492fSopenharmony_ci INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "Set service attr failed! null ptr."); 105d9f0492fSopenharmony_ci if (value >= MIN_IMPORTANT_LEVEL && value <= MAX_IMPORTANT_LEVEL) { // -20~19 106d9f0492fSopenharmony_ci service->attribute |= SERVICE_ATTR_IMPORTANT; 107d9f0492fSopenharmony_ci service->importance = value; 108d9f0492fSopenharmony_ci } else { 109d9f0492fSopenharmony_ci INIT_LOGE("Importance level = %d, is not between -20 and 19, error", value); 110d9f0492fSopenharmony_ci return SERVICE_FAILURE; 111d9f0492fSopenharmony_ci } 112d9f0492fSopenharmony_ci return SERVICE_SUCCESS; 113d9f0492fSopenharmony_ci} 114d9f0492fSopenharmony_ci 115d9f0492fSopenharmony_ciint ServiceExec(Service *service, const ServiceArgs *pathArgs) 116d9f0492fSopenharmony_ci{ 117d9f0492fSopenharmony_ci INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "Exec service failed! null ptr."); 118d9f0492fSopenharmony_ci INIT_LOGI("ServiceExec %s", service->name); 119d9f0492fSopenharmony_ci INIT_ERROR_CHECK(pathArgs != NULL && pathArgs->count > 0, 120d9f0492fSopenharmony_ci return SERVICE_FAILURE, "Exec service failed! null ptr."); 121d9f0492fSopenharmony_ci 122d9f0492fSopenharmony_ci if (service->importance != 0) { 123d9f0492fSopenharmony_ci INIT_ERROR_CHECK(setpriority(PRIO_PROCESS, 0, service->importance) == 0, 124d9f0492fSopenharmony_ci service->lastErrno = INIT_EPRIORITY; 125d9f0492fSopenharmony_ci return SERVICE_FAILURE, 126d9f0492fSopenharmony_ci "Service error %d %s, failed to set priority %d.", errno, service->name, service->importance); 127d9f0492fSopenharmony_ci } 128d9f0492fSopenharmony_ci OpenHidebug(service->name); 129d9f0492fSopenharmony_ci int isCritical = (service->attribute & SERVICE_ATTR_CRITICAL); 130d9f0492fSopenharmony_ci INIT_ERROR_CHECK(execv(pathArgs->argv[0], pathArgs->argv) == 0, 131d9f0492fSopenharmony_ci service->lastErrno = INIT_EEXEC; 132d9f0492fSopenharmony_ci return errno, "[startup_failed]failed to execv %d %d %s", isCritical, errno, service->name); 133d9f0492fSopenharmony_ci return SERVICE_SUCCESS; 134d9f0492fSopenharmony_ci} 135d9f0492fSopenharmony_ci 136d9f0492fSopenharmony_ciint SetAccessToken(const Service *service) 137d9f0492fSopenharmony_ci{ 138d9f0492fSopenharmony_ci INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "service is null"); 139d9f0492fSopenharmony_ci return SetSelfTokenID(service->tokenId); 140d9f0492fSopenharmony_ci} 141d9f0492fSopenharmony_ci 142d9f0492fSopenharmony_civoid GetAccessToken(void) 143d9f0492fSopenharmony_ci{ 144d9f0492fSopenharmony_ci InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL); 145d9f0492fSopenharmony_ci while (node != NULL) { 146d9f0492fSopenharmony_ci Service *service = node->data.service; 147d9f0492fSopenharmony_ci if (service != NULL) { 148d9f0492fSopenharmony_ci if (service->capsArgs.count == 0) { 149d9f0492fSopenharmony_ci service->capsArgs.argv = NULL; 150d9f0492fSopenharmony_ci } 151d9f0492fSopenharmony_ci const char *apl = "system_basic"; 152d9f0492fSopenharmony_ci if (service->apl != NULL) { 153d9f0492fSopenharmony_ci apl = service->apl; 154d9f0492fSopenharmony_ci } 155d9f0492fSopenharmony_ci NativeTokenInfoParams nativeTokenInfoParams = { 156d9f0492fSopenharmony_ci service->capsArgs.count, 157d9f0492fSopenharmony_ci service->permArgs.count, 158d9f0492fSopenharmony_ci service->permAclsArgs.count, 159d9f0492fSopenharmony_ci (const char **)service->capsArgs.argv, 160d9f0492fSopenharmony_ci (const char **)service->permArgs.argv, 161d9f0492fSopenharmony_ci (const char **)service->permAclsArgs.argv, 162d9f0492fSopenharmony_ci service->name, 163d9f0492fSopenharmony_ci apl, 164d9f0492fSopenharmony_ci }; 165d9f0492fSopenharmony_ci uint64_t tokenId = GetAccessTokenId(&nativeTokenInfoParams); 166d9f0492fSopenharmony_ci INIT_CHECK_ONLY_ELOG(tokenId != 0, 167d9f0492fSopenharmony_ci "gettotkenid failed, service \' %s \'", service->name); 168d9f0492fSopenharmony_ci service->tokenId = tokenId; 169d9f0492fSopenharmony_ci } 170d9f0492fSopenharmony_ci node = GetNextGroupNode(NODE_TYPE_SERVICES, node); 171d9f0492fSopenharmony_ci } 172d9f0492fSopenharmony_ci} 173d9f0492fSopenharmony_ci 174d9f0492fSopenharmony_civoid IsEnableSandbox(void) 175d9f0492fSopenharmony_ci{ 176d9f0492fSopenharmony_ci char value[MAX_BUFFER_LEN] = {0}; 177d9f0492fSopenharmony_ci unsigned int len = MAX_BUFFER_LEN; 178d9f0492fSopenharmony_ci if (SystemReadParam("const.sandbox", value, &len) == 0) { 179d9f0492fSopenharmony_ci if (strcmp(value, "enable") == 0) { 180d9f0492fSopenharmony_ci g_enableSandbox = true; 181d9f0492fSopenharmony_ci } 182d9f0492fSopenharmony_ci } 183d9f0492fSopenharmony_ci} 184d9f0492fSopenharmony_ci 185d9f0492fSopenharmony_ciint SetServiceEnterSandbox(const Service *service, const char *execPath) 186d9f0492fSopenharmony_ci{ 187d9f0492fSopenharmony_ci if ((service->attribute & SERVICE_ATTR_WITHOUT_SANDBOX) == SERVICE_ATTR_WITHOUT_SANDBOX) { 188d9f0492fSopenharmony_ci return 0; 189d9f0492fSopenharmony_ci } 190d9f0492fSopenharmony_ci if (g_enableSandbox == false) { 191d9f0492fSopenharmony_ci return 0; 192d9f0492fSopenharmony_ci } 193d9f0492fSopenharmony_ci INIT_ERROR_CHECK(execPath != NULL, return INIT_EPARAMETER, "Service path is null."); 194d9f0492fSopenharmony_ci int ret = 0; 195d9f0492fSopenharmony_ci if (strncmp(execPath, "/system/bin/", strlen("/system/bin/")) == 0) { 196d9f0492fSopenharmony_ci ret = EnterSandbox("system"); 197d9f0492fSopenharmony_ci } else if (strncmp(execPath, "/vendor/bin/", strlen("/vendor/bin/")) == 0) { 198d9f0492fSopenharmony_ci ret = EnterSandbox("chipset"); 199d9f0492fSopenharmony_ci } 200d9f0492fSopenharmony_ci return ret; 201d9f0492fSopenharmony_ci} 202