• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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