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