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