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
NotifyServiceChange(Service * service,int status)41 void NotifyServiceChange(Service *service, int status)
42 {
43 INIT_LOGV("Notify service %s change from %d to %d", service->name, service->status, status);
44 service->status = status;
45 INIT_CHECK(status != SERVICE_IDLE, return);
46 char paramName[PARAM_NAME_LEN_MAX] = { 0 };
47 int ret = snprintf_s(paramName, sizeof(paramName), sizeof(paramName) - 1,
48 "%s.%s", STARTUP_SERVICE_CTL, service->name);
49 INIT_ERROR_CHECK(ret > 0, return, "Failed to format service name %s.", service->name);
50 char statusStr[MAX_INT_LEN] = {0};
51 ret = snprintf_s(statusStr, sizeof(statusStr), sizeof(statusStr) - 1, "%d", status);
52 INIT_ERROR_CHECK(ret > 0, return, "Failed to format service status %s.", service->name);
53 SystemWriteParam(paramName, statusStr);
54
55 // write pid
56 ret = snprintf_s(paramName, sizeof(paramName), sizeof(paramName) - 1,
57 "%s.%s.pid", STARTUP_SERVICE_CTL, service->name);
58 INIT_ERROR_CHECK(ret > 0, return, "Failed to format service pid name %s.", service->name);
59 ret = snprintf_s(statusStr, sizeof(statusStr), sizeof(statusStr) - 1,
60 "%d", (service->pid == -1) ? 0 : service->pid);
61 INIT_ERROR_CHECK(ret > 0, return, "Failed to format service pid %s.", service->name);
62 SystemWriteParam(paramName, statusStr);
63 }
64
IsForbidden(const char * fieldStr)65 int IsForbidden(const char *fieldStr)
66 {
67 UNUSED(fieldStr);
68 return 0;
69 }
70
SetImportantValue(Service * service,const char * attrName,int value,int flag)71 int SetImportantValue(Service *service, const char *attrName, int value, int flag)
72 {
73 UNUSED(attrName);
74 UNUSED(flag);
75 INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "Set service attr failed! null ptr.");
76 if (value >= MIN_IMPORTANT_LEVEL && value <= MAX_IMPORTANT_LEVEL) { // -20~19
77 service->attribute |= SERVICE_ATTR_IMPORTANT;
78 service->importance = value;
79 } else {
80 INIT_LOGE("Importance level = %d, is not between -20 and 19, error", value);
81 return SERVICE_FAILURE;
82 }
83 return SERVICE_SUCCESS;
84 }
85
ServiceExec(const Service * service)86 int ServiceExec(const Service *service)
87 {
88 INIT_ERROR_CHECK(service != NULL && service->pathArgs.count > 0,
89 return SERVICE_FAILURE, "Exec service failed! null ptr.");
90 if (service->importance != 0) {
91 INIT_ERROR_CHECK(setpriority(PRIO_PROCESS, 0, service->importance) == 0, _exit(0x7f),
92 "setpriority failed for %s, importance = %d, err=%d", service->name, service->importance, errno);
93 }
94 OpenHidebug(service->name);
95 if (service->extraArgs.argv != NULL && service->extraArgs.count > 0) {
96 INIT_CHECK_ONLY_ELOG(execv(service->extraArgs.argv[0], service->extraArgs.argv) == 0,
97 "service %s execv failed! err %d.", service->name, errno);
98 } else {
99 INIT_CHECK_ONLY_ELOG(execv(service->pathArgs.argv[0], service->pathArgs.argv) == 0,
100 "service %s execv failed! err %d.", service->name, errno);
101 }
102 return SERVICE_SUCCESS;
103 }
104
SetAccessToken(const Service * service)105 int SetAccessToken(const Service *service)
106 {
107 INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "service is null");
108 int ret = SetSelfTokenID(service->tokenId);
109 if (ret != 0) {
110 INIT_LOGV("Set service %s token id %lld failed.", service->name, service->tokenId);
111 return SERVICE_FAILURE;
112 }
113 return SERVICE_SUCCESS;
114 }
115
GetAccessToken(void)116 void GetAccessToken(void)
117 {
118 InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL);
119 while (node != NULL) {
120 Service *service = node->data.service;
121 if (service != NULL) {
122 if (service->capsArgs.count == 0) {
123 service->capsArgs.argv = NULL;
124 }
125 const char *apl = "system_basic";
126 if (service->apl != NULL) {
127 apl = service->apl;
128 }
129 NativeTokenInfoParams nativeTokenInfoParams = {
130 service->capsArgs.count,
131 service->permArgs.count,
132 service->permAclsArgs.count,
133 (const char **)service->capsArgs.argv,
134 (const char **)service->permArgs.argv,
135 (const char **)service->permAclsArgs.argv,
136 service->name,
137 apl,
138 };
139 uint64_t tokenId = GetAccessTokenId(&nativeTokenInfoParams);
140 INIT_CHECK_ONLY_ELOG(tokenId != 0,
141 "Get totken id %lld of service \' %s \' failed", tokenId, service->name);
142 service->tokenId = tokenId;
143 }
144 node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
145 }
146 }
147
IsEnableSandbox(void)148 void IsEnableSandbox(void)
149 {
150 char value[MAX_BUFFER_LEN] = {0};
151 unsigned int len = MAX_BUFFER_LEN;
152 if (SystemReadParam("const.sandbox", value, &len) == 0) {
153 if (strcmp(value, "enable") == 0) {
154 g_enableSandbox = true;
155 }
156 }
157 }
158
SetServiceEnterSandbox(const char * execPath,unsigned int attribute)159 void SetServiceEnterSandbox(const char *execPath, unsigned int attribute)
160 {
161 if (g_enableSandbox == false) {
162 return;
163 }
164 if ((attribute & SERVICE_ATTR_WITHOUT_SANDBOX) == SERVICE_ATTR_WITHOUT_SANDBOX) {
165 return;
166 }
167 INIT_ERROR_CHECK(execPath != NULL, return, "Service path is null.");
168 if (strncmp(execPath, "/system/bin/", strlen("/system/bin/")) == 0) {
169 INIT_INFO_CHECK(EnterSandbox("system") == 0, return,
170 "Service %s skip enter system sandbox.", execPath);
171 } else if (strncmp(execPath, "/vendor/bin/", strlen("/vendor/bin/")) == 0) {
172 INIT_INFO_CHECK(EnterSandbox("chipset") == 0, return,
173 "Service %s skip enter chipset sandbox.", execPath);
174 } else {
175 INIT_LOGI("Service %s does not enter sandbox", execPath);
176 }
177 return;
178 }
179