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
39 static bool g_enableSandbox = false;
40
WriteOomScoreAdjToService(Service * service)41 static 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
NotifyServiceChange(Service * service,int status)67 void 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
IsForbidden(const char * fieldStr)94 int IsForbidden(const char *fieldStr)
95 {
96 UNUSED(fieldStr);
97 return 0;
98 }
99
SetImportantValue(Service * service,const char * attrName,int value,int flag)100 int 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
ServiceExec(Service * service,const ServiceArgs * pathArgs)115 int 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
SetAccessToken(const Service * service)136 int SetAccessToken(const Service *service)
137 {
138 INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "service is null");
139 return SetSelfTokenID(service->tokenId);
140 }
141
GetAccessToken(void)142 void 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
IsEnableSandbox(void)174 void 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
SetServiceEnterSandbox(const Service * service,const char * execPath)185 int 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