1 /*
2 * Copyright (c) 2022 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
16 #include <errno.h>
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <unistd.h>
20
21 #include "control_fd.h"
22 #include "init_service.h"
23 #include "init_service_manager.h"
24 #include "init_modulemgr.h"
25 #include "init_utils.h"
26 #include "init_log.h"
27 #include "init_group_manager.h"
28 #include "init_param.h"
29 #include "hookmgr.h"
30 #include "bootstage.h"
31
DumpServiceArgs(const char * info,const ServiceArgs * args)32 static void DumpServiceArgs(const char *info, const ServiceArgs *args)
33 {
34 printf("\tservice %s count %d \n", info, args->count);
35 for (int j = 0; j < args->count; j++) {
36 if (args->argv[j] != NULL) {
37 printf("\t\tinfo [%d] %s \n", j, args->argv[j]);
38 }
39 }
40 }
41
DumpServiceJobs(const Service * service)42 static void DumpServiceJobs(const Service *service)
43 {
44 printf("\tservice job info \n");
45 if (service->serviceJobs.jobsName[JOB_ON_BOOT] != NULL) {
46 printf("\t\tservice boot job %s \n", service->serviceJobs.jobsName[JOB_ON_BOOT]);
47 }
48 if (service->serviceJobs.jobsName[JOB_ON_START] != NULL) {
49 printf("\t\tservice start job %s \n", service->serviceJobs.jobsName[JOB_ON_START]);
50 }
51 if (service->serviceJobs.jobsName[JOB_ON_STOP] != NULL) {
52 printf("\t\tservice stop job %s \n", service->serviceJobs.jobsName[JOB_ON_STOP]);
53 }
54 if (service->serviceJobs.jobsName[JOB_ON_RESTART] != NULL) {
55 printf("\t\tservice restart job %s \n", service->serviceJobs.jobsName[JOB_ON_RESTART]);
56 }
57 }
58
DumpServiceSocket(const Service * service)59 static void DumpServiceSocket(const Service *service)
60 {
61 printf("\tservice socket info \n");
62 ServiceSocket *sockopt = service->socketCfg;
63 while (sockopt != NULL) {
64 printf("\t\tsocket name: %s \n", sockopt->name);
65 printf("\t\tsocket type: %u \n", sockopt->type);
66 printf("\t\tsocket uid: %u \n", sockopt->uid);
67 printf("\t\tsocket gid: %u \n", sockopt->gid);
68 sockopt = sockopt->next;
69 }
70 }
71
DumpServiceHookExecute(const char * name,const char * info)72 void DumpServiceHookExecute(const char *name, const char *info)
73 {
74 SERVICE_INFO_CTX context;
75 context.serviceName = name;
76 context.reserved = info;
77 (void)HookMgrExecute(GetBootStageHookMgr(), INIT_SERVICE_DUMP, (void *)(&context), NULL);
78 }
79
DumpOneService(const Service * service)80 static void DumpOneService(const Service *service)
81 {
82 const InitArgInfo startModeMap[] = {
83 {"condition", START_MODE_CONDITION},
84 {"boot", START_MODE_BOOT},
85 {"normal", START_MODE_NORMAL}
86 };
87
88 const static char *serviceStatusMap[] = {
89 "created", "starting", "running", "ready",
90 "stopping", "stopped", "suspended", "freezed", "disabled", "critical"
91 };
92
93 printf("\tservice name: [%s] \n", service->name);
94 printf("\tservice pid: [%d] \n", service->pid);
95 printf("\tservice crashCnt: [%d] \n", service->crashCnt);
96 printf("\tservice attribute: [%u] \n", service->attribute);
97 printf("\tservice importance: [%d] \n", service->importance);
98 printf("\tservice startMode: [%s] \n", startModeMap[service->startMode].name);
99 printf("\tservice status: [%s] \n", serviceStatusMap[service->status]);
100 printf("\tservice perms uID [%u] \n", service->servPerm.uID);
101 DumpServiceArgs("path arg", &service->pathArgs);
102 DumpServiceArgs("writepid file", &service->writePidArgs);
103 DumpServiceJobs(service);
104 DumpServiceSocket(service);
105
106 printf("\tservice perms groupId %d \n", service->servPerm.gIDCnt);
107 for (int i = 0; i < service->servPerm.gIDCnt; i++) {
108 printf("\t\tservice perms groupId %u \n", service->servPerm.gIDArray[i]);
109 }
110 printf("\tservice perms capability %u \n", service->servPerm.capsCnt);
111 for (int i = 0; i < (int)service->servPerm.capsCnt; i++) {
112 printf("\t\tservice perms capability %u \n", service->servPerm.caps[i]);
113 }
114
115 DumpServiceHookExecute(service->name, NULL);
116 }
117
PrintBootEventHead(const char * cmd)118 static void PrintBootEventHead(const char *cmd)
119 {
120 if (strcmp(cmd, "bootevent") == 0) {
121 printf("\t%-20.20s\t%-50s\t%-20.20s\t%-20.20s\n",
122 "service-name", "bootevent-name", "fork", "ready");
123 }
124 return;
125 }
126
DumpAllExtData(const char * cmd)127 static void DumpAllExtData(const char *cmd)
128 {
129 PrintBootEventHead(cmd);
130 InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL);
131 while (node != NULL) {
132 if (node->data.service == NULL) {
133 node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
134 continue;
135 }
136 DumpServiceHookExecute(node->name, cmd);
137 node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
138 }
139 }
140
DumpAllServices(void)141 static void DumpAllServices(void)
142 {
143 printf("Ready to dump all services: \n");
144 InitGroupNode *node = GetNextGroupNode(NODE_TYPE_SERVICES, NULL);
145 while (node != NULL) {
146 if (node->data.service == NULL) {
147 node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
148 continue;
149 }
150 Service *service = node->data.service;
151 DumpOneService(service);
152 node = GetNextGroupNode(NODE_TYPE_SERVICES, node);
153 }
154 printf("Dump all services finished \n");
155 }
156
ProcessSandboxControlFd(uint16_t type,const char * serviceCmd)157 static void ProcessSandboxControlFd(uint16_t type, const char *serviceCmd)
158 {
159 if ((type != ACTION_SANDBOX) || (serviceCmd == NULL)) {
160 INIT_LOGE("Invalid parameter");
161 return;
162 }
163 Service *service = GetServiceByName(serviceCmd);
164 if (service == NULL) {
165 INIT_LOGE("Failed get service %s", serviceCmd);
166 return;
167 }
168 EnterServiceSandbox(service);
169 return;
170 }
171
ProcessDumpServiceControlFd(uint16_t type,const char * serviceCmd)172 static void ProcessDumpServiceControlFd(uint16_t type, const char *serviceCmd)
173 {
174 if ((type != ACTION_DUMP) || (serviceCmd == NULL)) {
175 return;
176 }
177 char *cmd = strrchr(serviceCmd, '#');
178 if (cmd != NULL) {
179 cmd[0] = '\0';
180 cmd++;
181 }
182
183 if (strcmp(serviceCmd, "all") == 0) {
184 if (cmd != NULL) {
185 DumpAllExtData(cmd);
186 } else {
187 DumpAllServices();
188 }
189 return;
190 }
191 if (strcmp(serviceCmd, "parameter_service") == 0) {
192 if (cmd != NULL && strcmp(cmd, "trigger") == 0) {
193 SystemDumpTriggers(0, printf);
194 }
195 return;
196 }
197 Service *service = GetServiceByName(serviceCmd);
198 if (service != NULL) {
199 if (cmd != NULL) {
200 PrintBootEventHead(cmd);
201 DumpServiceHookExecute(serviceCmd, cmd);
202 } else {
203 DumpOneService(service);
204 }
205 }
206 return;
207 }
208
ProcessModuleMgrControlFd(uint16_t type,const char * serviceCmd)209 static void ProcessModuleMgrControlFd(uint16_t type, const char *serviceCmd)
210 {
211 if ((type != ACTION_MODULEMGR) || (serviceCmd == NULL)) {
212 return;
213 }
214 INIT_LOGE("ProcessModuleMgrControlFd argc [%s] \n", serviceCmd);
215 if (strcmp(serviceCmd, "list") == 0) {
216 InitModuleMgrDump();
217 return;
218 }
219 }
220
ProcessParamShellControlFd(uint16_t type,const char * serviceCmd)221 static void ProcessParamShellControlFd(uint16_t type, const char *serviceCmd)
222 {
223 if ((type != ACTION_PARAM_SHELL) || (serviceCmd == NULL)) {
224 return;
225 }
226 (void)setuid(2000); // 2000 shell group
227 (void)setgid(2000); // 2000 shell group
228 char *args[] = {(char *)serviceCmd, NULL};
229 int ret = execv(args[0], args);
230 if (ret < 0) {
231 INIT_LOGE("error on exec %d \n", errno);
232 exit(-1);
233 }
234 exit(0);
235 }
236
ProcessControlFd(uint16_t type,const char * serviceCmd,const void * context)237 void ProcessControlFd(uint16_t type, const char *serviceCmd, const void *context)
238 {
239 if ((type >= ACTION_MAX) || (serviceCmd == NULL)) {
240 return;
241 }
242 switch (type) {
243 case ACTION_SANDBOX :
244 ProcessSandboxControlFd(type, serviceCmd);
245 break;
246 case ACTION_DUMP :
247 ProcessDumpServiceControlFd(type, serviceCmd);
248 break;
249 case ACTION_PARAM_SHELL :
250 ProcessParamShellControlFd(type, serviceCmd);
251 break;
252 case ACTION_MODULEMGR :
253 ProcessModuleMgrControlFd(type, serviceCmd);
254 break;
255 default :
256 INIT_LOGW("Unknown control fd type.");
257 break;
258 }
259 }
260
InitControlFd(void)261 void InitControlFd(void)
262 {
263 CmdServiceInit(INIT_CONTROL_FD_SOCKET_PATH, ProcessControlFd);
264 return;
265 }
266