• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-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 #include <grp.h>
16 #include <pwd.h>
17 #include <sys/ioctl.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <sys/wait.h>
21 #include <termios.h>
22 
23 #include "begetctl.h"
24 #include "param_manager.h"
25 #include "param_security.h"
26 #include "shell_utils.h"
27 #include "init_param.h"
28 #include "beget_ext.h"
29 #ifdef PARAM_SUPPORT_SELINUX
30 #include <policycoreutils.h>
31 #include <selinux/selinux.h>
32 #include "selinux_parameter.h"
33 #endif // PARAM_SUPPORT_SELINUX
34 
35 #define MASK_LENGTH_MAX 4
36 pid_t g_shellPid = 0;
37 static struct termios g_terminalState;
38 char g_isSetTerminal = 0;
39 
demoExit(void)40 void demoExit(void)
41 {
42     BShellEnvDestory(GetShellHandle());
43     if (g_shellPid != 0) {
44 #ifndef STARTUP_INIT_TEST
45         kill(g_shellPid, SIGKILL);
46 #endif
47     }
48     BEGET_CHECK(g_isSetTerminal == 0, tcsetattr(0, TCSAFLUSH, &g_terminalState));
49 }
50 
51 #define CMD_PATH "/system/bin/paramshell"
52 #define SHELL_NAME "paramshell"
53 #ifndef TIOCSCTTY
54 #define TIOCSCTTY 0x540E
55 #endif
GetLocalBuffer(uint32_t * buffSize)56 static char *GetLocalBuffer(uint32_t *buffSize)
57 {
58     static char buffer[PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX] = {0};
59     BEGET_CHECK(buffSize == NULL, *buffSize = sizeof(buffer));
60     return buffer;
61 }
62 
GetRealParameter(BShellHandle shell,const char * name,char * buffer,uint32_t buffSize)63 static char *GetRealParameter(BShellHandle shell, const char *name, char *buffer, uint32_t buffSize)
64 {
65     BSH_CHECK(buffer != NULL && name != NULL, return NULL, "Invalid parameter");
66     const BShellParam *param = BShellEnvGetParam(shell, PARAM_REVERESD_NAME_CURR_PARAMETER);
67     const char *current = (param == NULL) ? "" : param->value.string;
68     int32_t realLen = 0;
69     int ret = 0;
70     if (name[0] == '.') { // relatively
71         if (strcmp(name, "..") == 0) {
72             char *tmp = strrchr(current, '.');
73             if (tmp != NULL) {
74                 realLen = tmp - current;
75                 ret = memcpy_s(buffer, buffSize, current, realLen);
76             } else {
77                 ret = memcpy_s(buffer, buffSize, "#", 1);
78                 realLen = 1;
79             }
80             BSH_CHECK(ret == 0, return NULL, "Failed to memcpy");
81         } else if (strcmp(name, ".") == 0) {
82             realLen = sprintf_s(buffer, buffSize, "%s", current);
83         } else {
84             realLen = sprintf_s(buffer, buffSize, "%s%s", current, name);
85         }
86     } else if (strlen(name) == 0) {
87         realLen = sprintf_s(buffer, buffSize, "%s", current);
88     } else {
89         realLen = sprintf_s(buffer, buffSize, "%s", name);
90     }
91     BSH_CHECK(realLen >= 0, return NULL, "Failed to format buffer");
92     buffer[realLen] = '\0';
93     BSH_LOGV("GetRealParameter current %s input %s real %s", current, name, buffer);
94     return buffer;
95 }
96 
SetParamShellPrompt(BShellHandle shell,const char * param)97 int SetParamShellPrompt(BShellHandle shell, const char *param)
98 {
99     uint32_t buffSize = 0;
100     char *buffer = GetLocalBuffer(&buffSize);
101     char *realParameter = GetRealParameter(shell, param, buffer, buffSize);
102     BSH_CHECK(realParameter != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
103     if (strlen(realParameter) == 0) {
104         BShellEnvOutputPrompt(shell, PARAM_SHELL_DEFAULT_PROMPT);
105         return -1;
106     }
107     // check parameter
108     int ret = SystemCheckParamExist(realParameter);
109     if (ret == PARAM_CODE_NOT_FOUND) {
110         BShellEnvOutput(shell, "Error: parameter \'%s\' not found\r\n", realParameter);
111         return -1;
112     } else if (ret != 0 && ret != PARAM_CODE_NODE_EXIST) {
113         BShellEnvOutput(shell, "Error: Forbid to enter parameters \'%s\'\r\n", realParameter);
114         return -1;
115     }
116     if (strcmp(realParameter, "#") == 0) {
117         ret = BShellEnvSetParam(shell, PARAM_REVERESD_NAME_CURR_PARAMETER,
118             "", PARAM_STRING, (void *)"");
119         BSH_CHECK(ret == 0, return BSH_SYSTEM_ERR, "Failed to set param value");
120         BShellEnvOutputPrompt(shell, PARAM_SHELL_DEFAULT_PROMPT);
121         return 0;
122     }
123     ret = BShellEnvSetParam(shell, PARAM_REVERESD_NAME_CURR_PARAMETER,
124         "", PARAM_STRING, (void *)realParameter);
125     BSH_CHECK(ret == 0, return BSH_SYSTEM_ERR, "Failed to set param value");
126     if (strcat_s(realParameter, buffSize, "#") != 0) {
127         BSH_CHECK(ret != 0, return BSH_SYSTEM_ERR, "Failed to cat prompt %s", realParameter);
128     }
129     BShellEnvOutputPrompt(shell, realParameter);
130     return 0;
131 }
132 
GetPermissionString(uint32_t mode,int shift,char * str,int size)133 static char *GetPermissionString(uint32_t mode, int shift, char *str, int size)
134 {
135     BEGET_CHECK(!(size < MASK_LENGTH_MAX), return str);
136     str[0] = '-';
137     str[1] = '-';
138     str[2] = '-'; // 2 watcher
139     str[3] = '\0'; // 3 end
140     if (mode & (DAC_READ >> shift)) {
141         str[0] = 'r';
142     }
143     if (mode & (DAC_WRITE >> shift)) {
144         str[1] = 'w';
145     }
146     if (mode & (DAC_WATCH >> shift)) {
147         str[2] = 'w'; // 2 watcher
148     }
149     return str;
150 }
151 
ShowParam(BShellHandle shell,const char * name,const char * value)152 static void ShowParam(BShellHandle shell, const char *name, const char *value)
153 {
154     ParamAuditData auditData = {};
155     int ret = GetParamSecurityAuditData(name, 0, &auditData);
156     BSH_CHECK(ret == 0, return, "Failed to get param security for %s", name);
157     BShellEnvOutput(shell, "Parameter information:\r\n");
158 #ifdef PARAM_SUPPORT_SELINUX
159     BShellEnvOutput(shell, "selinux  : %s \r\n", auditData.label);
160 #endif
161     char permissionStr[3][MASK_LENGTH_MAX] = {}; // 3 permission
162     struct passwd *user = getpwuid(auditData.dacData.uid);
163     struct group *group = getgrgid(auditData.dacData.gid);
164     if (user != NULL && group != NULL) {
165         BShellEnvOutput(shell, "    dac  : %s(%s) %s(%s) (%s) \r\n",
166             user->pw_name,
167             GetPermissionString(auditData.dacData.mode, 0, permissionStr[0], MASK_LENGTH_MAX),
168             group->gr_name,
169             GetPermissionString(auditData.dacData.mode,DAC_GROUP_START, permissionStr[1], MASK_LENGTH_MAX),
170              // 2 other
171             GetPermissionString(auditData.dacData.mode, DAC_OTHER_START, permissionStr[2], MASK_LENGTH_MAX));
172     }
173     if (strcmp("#", name) != 0) {
174         BShellEnvOutput(shell, "    name : %s\r\n", name);
175     }
176     if (value != NULL) {
177         BShellEnvOutput(shell, "    value: %s\r\n", value);
178     }
179 }
180 
ShowParamForCmdLs(ParamHandle handle,void * cookie)181 static void ShowParamForCmdLs(ParamHandle handle, void *cookie)
182 {
183     uint32_t buffSize = 0;
184     char *buffer = GetLocalBuffer(&buffSize);
185     if (buffSize < (PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX)) {
186         return;
187     }
188     char *value = buffer + PARAM_NAME_LEN_MAX;
189     (void)SystemGetParameterName(handle, buffer, PARAM_NAME_LEN_MAX);
190     uint32_t valueLen = buffSize - PARAM_NAME_LEN_MAX;
191     (void)SystemGetParameterValue(handle, value, &valueLen);
192     ShowParam((BShellHandle)cookie, buffer, value);
193 }
194 
BShellParamCmdLs(BShellHandle shell,int32_t argc,char * argv[])195 static int32_t BShellParamCmdLs(BShellHandle shell, int32_t argc, char *argv[])
196 {
197     BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
198     int all = 0;
199     char *input = NULL;
200     for (int32_t i = 1; i < argc; i++) {
201         if (strcmp(argv[i], "-r") == 0) {
202             all = 1;
203         } else if (input == NULL) {
204             input = argv[i];
205         }
206     }
207     uint32_t buffSize = 0;
208     char *buffer = GetLocalBuffer(&buffSize);
209     char *realParameter = GetRealParameter(shell, (input == NULL) ? "" : input, buffer, buffSize);
210     BSH_CHECK(realParameter != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
211     char *prefix = strdup((strlen(realParameter) == 0) ? "#" : realParameter);
212     BSH_LOGV("BShellParamCmdLs prefix %s", prefix);
213     int ret = 0;
214     if (all != 0) {
215         ret = SystemTraversalParameter(prefix, ShowParamForCmdLs, (void *)shell);
216         if (ret != 0) {
217             BShellEnvOutput(shell, "Error: Forbid to list parameters\r\n");
218         }
219     } else {
220         ret = SystemCheckParamExist(prefix);
221         if (ret == 0) {
222             ParamHandle handle;
223             ret = SystemFindParameter(prefix, &handle);
224             if (ret != 0) {
225                 BShellEnvOutput(shell, "Error: Forbid to list parameters\r\n");
226             } else {
227                 ShowParamForCmdLs(handle, (void *)shell);
228             }
229         } else if (ret == PARAM_CODE_NODE_EXIST) {
230             ShowParam(shell, prefix, NULL);
231         } else if (ret != PARAM_CODE_NOT_FOUND) {
232             BShellEnvOutput(shell, "Error: Forbid to list parameters\r\n");
233         } else {
234             BShellEnvOutput(shell, "Parameter %s not found\r\n", prefix);
235         }
236     }
237     free(prefix);
238     return 0;
239 }
240 
BShellParamCmdCat(BShellHandle shell,int32_t argc,char * argv[])241 static int32_t BShellParamCmdCat(BShellHandle shell, int32_t argc, char *argv[])
242 {
243     BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
244     BSH_CHECK(argc >= 1, return BSH_CMD_PARAM_INVALID, "Invalid shell env");
245     uint32_t buffSize = 0;
246     char *buffer = GetLocalBuffer(&buffSize);
247     char *realParameter = GetRealParameter(shell, argv[1], buffer, buffSize);
248     BSH_CHECK(realParameter != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
249     int ret = SystemGetParameter(realParameter, buffer, &buffSize);
250     BSH_CHECK(ret != 0, BShellEnvOutput(shell, "    %s\r\n", buffer));
251     return 0;
252 }
253 
BShellParamCmdCd(BShellHandle shell,int32_t argc,char * argv[])254 static int32_t BShellParamCmdCd(BShellHandle shell, int32_t argc, char *argv[])
255 {
256     BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
257     BSH_CHECK(argc >= 1, return BSH_CMD_PARAM_INVALID, "Invalid shell env");
258     SetParamShellPrompt(shell, argv[1]);
259     return 0;
260 }
261 
ShowParamForCmdGet(ParamHandle handle,void * cookie)262 static void ShowParamForCmdGet(ParamHandle handle, void *cookie)
263 {
264     uint32_t buffSize = 0;
265     char *buffer = GetLocalBuffer(&buffSize);
266     BSH_CHECK(!(buffSize < (PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX)), return);
267     char *value = buffer + PARAM_NAME_LEN_MAX;
268     (void)SystemGetParameterName(handle, buffer, PARAM_NAME_LEN_MAX);
269     uint32_t valueLen = buffSize - PARAM_NAME_LEN_MAX;
270     (void)SystemGetParameterValue(handle, value, &valueLen);
271     BShellEnvOutput((BShellHandle)cookie, "    %s = %s\r\n", buffer, value);
272 }
273 
BShellParamCmdGet(BShellHandle shell,int32_t argc,char * argv[])274 static int32_t BShellParamCmdGet(BShellHandle shell, int32_t argc, char *argv[])
275 {
276     BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
277     BSH_CHECK(argc >= 1, return BSH_CMD_PARAM_INVALID, "Invalid shell env");
278     int ret = 0;
279     uint32_t buffSize = 0;
280     char *buffer = GetLocalBuffer(&buffSize);
281     char *realParameter = GetRealParameter(shell, (argc == 1) ? "" : argv[1], buffer, buffSize);
282     if ((argc == 1) || (realParameter == NULL) ||
283         (strlen(realParameter) == 0) || (strcmp(realParameter, "#") == 0)) {
284         ret = SystemTraversalParameter(realParameter, ShowParamForCmdGet, (void *)shell);
285         if (ret != 0) {
286             BShellEnvOutput(shell, "Error: Forbid to get all parameters\r\n");
287         }
288         return 0;
289     }
290     char *key = strdup(realParameter);
291     ret = SystemGetParameter(key, buffer, &buffSize);
292     if (ret == 0) {
293         BShellEnvOutput(shell, "%s \n", buffer);
294     } else {
295         BShellEnvOutput(shell, "Get parameter \"%s\" fail\n", key);
296     }
297     free(key);
298     return 0;
299 }
300 
BShellParamCmdSet(BShellHandle shell,int32_t argc,char * argv[])301 static int32_t BShellParamCmdSet(BShellHandle shell, int32_t argc, char *argv[])
302 {
303     BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
304     if (argc < 3) { // 3 min param
305         char *helpArgs[] = {"param", NULL};
306         BShellCmdHelp(shell, 1, helpArgs);
307         return 0;
308     }
309     uint32_t buffSize = 0;
310     char *buffer = GetLocalBuffer(&buffSize);
311     char *realParameter = GetRealParameter(shell, argv[1], buffer, buffSize);
312     if ((realParameter == NULL) || (strlen(realParameter) == 0) || (strcmp(realParameter, "#") == 0)) {
313         BShellEnvOutput(shell, "Set parameter %s %s fail\n", argv[1], argv[2]); // 2 value param
314         return 0;
315     }
316     int ret = SystemSetParameter(realParameter, argv[2]); // 2 value param
317     if (ret == 0) {
318         BShellEnvOutput(shell, "Set parameter %s %s success\n", realParameter, argv[2]); // 2 value param
319     } else {
320         BShellEnvOutput(shell, "Set parameter %s %s fail\n", realParameter, argv[2]); // 2 value param
321     }
322     return 0;
323 }
324 
BShellParamCmdWait(BShellHandle shell,int32_t argc,char * argv[])325 static int32_t BShellParamCmdWait(BShellHandle shell, int32_t argc, char *argv[])
326 {
327     BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
328     if (argc < 2) { // 2 min param
329         char *helpArgs[] = {"param", NULL};
330         BShellCmdHelp(shell, 1, helpArgs);
331         return 0;
332     }
333     int32_t timeout = 30; // 30s
334     char *value = "*";
335     if (argc > 2) { // 2 value param
336         value = argv[2]; // 2 value param
337     }
338     if (argc > 3) { // 3 timeout param
339         timeout = atoi(argv[3]); // 3 timeout param
340     }
341     uint32_t buffSize = 0;
342     char *buffer = GetLocalBuffer(&buffSize);
343     char *realParameter = GetRealParameter(shell, argv[1], buffer, buffSize);
344     if ((realParameter == NULL) || (strlen(realParameter) == 0) || (strcmp(realParameter, "#") == 0)) {
345         BShellEnvOutput(shell, "Wait parameter %s fail\n", argv[1]);
346         return 0;
347     }
348 
349     int ret = SystemWaitParameter(realParameter, value, timeout);
350     if (ret == 0) {
351         BShellEnvOutput(shell, "Wait parameter %s success\n", argv[1]);
352     } else {
353         BShellEnvOutput(shell, "Wait parameter %s fail\n", argv[1]);
354     }
355     return 0;
356 }
357 
BShellParamCmdDump(BShellHandle shell,int32_t argc,char * argv[])358 static int32_t BShellParamCmdDump(BShellHandle shell, int32_t argc, char *argv[])
359 {
360     BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
361     if (argc >= 2 && strcmp(argv[1], "verbose") == 0) { // 2 min arg
362         SystemDumpParameters(1, printf);
363     } else {
364         SystemDumpParameters(0, printf);
365     }
366     return 0;
367 }
368 
BShellParamCmdPwd(BShellHandle shell,int32_t argc,char * argv[])369 static int32_t BShellParamCmdPwd(BShellHandle shell, int32_t argc, char *argv[])
370 {
371     uint32_t buffSize = 0;
372     char *buffer = GetLocalBuffer(&buffSize);
373     char *realParameter = GetRealParameter(shell, "", buffer, buffSize);
374     BShellEnvOutput(shell, "%s\r\n", realParameter);
375     return 0;
376 }
377 
BShellParamCmdShell(BShellHandle shell,int32_t argc,char * argv[])378 static int32_t BShellParamCmdShell(BShellHandle shell, int32_t argc, char *argv[])
379 {
380 #ifndef STARTUP_INIT_TEST
381     BSH_CHECK(shell != NULL, return BSH_INVALID_PARAM, "Invalid shell env");
382     BSH_LOGV("BShellParamCmdShell %d %s", argc, argv[1]);
383     int ret = 0;
384     if (argc > 1) {
385         ret = SystemCheckParamExist(argv[1]);
386         if (ret != 0) {
387             BShellEnvOutput(shell, "Error: parameter \'%s\' not found\r\n", argv[1]);
388             return -1;
389         }
390     }
391     if (tcgetattr(0, &g_terminalState)) {
392         return BSH_SYSTEM_ERR;
393     }
394     g_isSetTerminal = 1;
395     pid_t pid = fork();
396     if (pid == 0) {
397         setuid(2000); // 2000 shell group
398         setgid(2000); // 2000 shell group
399 #ifdef PARAM_SUPPORT_SELINUX
400         setcon("u:r:normal_hap_domain:s0");
401 #endif
402         if (argc >= 2) { // 2 min argc
403             char *args[] = {SHELL_NAME, argv[1], NULL};
404             ret = execv(CMD_PATH, args);
405         } else {
406             char *args[] = {SHELL_NAME, NULL};
407             ret = execv(CMD_PATH, args);
408         }
409         if (ret < 0) {
410             printf("error on exec %d \n", errno);
411             exit(0);
412         }
413         exit(0);
414     } else if (pid > 0) {
415         g_shellPid = pid;
416         int status = 0;
417         wait(&status);
418         tcsetattr(0, TCSAFLUSH, &g_terminalState);
419         g_isSetTerminal = 0;
420     }
421 #endif
422     return 0;
423 }
424 
BShellParamCmdRegForShell(BShellHandle shell)425 static int32_t BShellParamCmdRegForShell(BShellHandle shell)
426 {
427     const CmdInfo infos[] = {
428         {"ls", BShellParamCmdLs, "display system parameter", "ls [-r] [name]", NULL},
429         {"get", BShellParamCmdGet, "get system parameter", "get [name]", NULL},
430         {"set", BShellParamCmdSet, "set system parameter", "set name value", NULL},
431         {"wait", BShellParamCmdWait, "wait system parameter", "wait name [value] [timeout]", NULL},
432         {"dump", BShellParamCmdDump, "dump system parameter", "dump [verbose]", ""},
433         {"cd", BShellParamCmdCd, "change path of parameter", "cd name", NULL},
434         {"cat", BShellParamCmdCat, "display value of parameter", "cat name", NULL},
435         {"pwd", BShellParamCmdPwd, "display current parameter", "pwd", NULL},
436     };
437     for (size_t i = sizeof(infos) / sizeof(infos[0]); i > 0; i--) {
438         BShellEnvRegisterCmd(shell, &infos[i - 1]);
439     }
440     return 0;
441 }
442 
BShellParamCmdRegForIndepent(BShellHandle shell)443 static int32_t BShellParamCmdRegForIndepent(BShellHandle shell)
444 {
445     const CmdInfo infos[] = {
446         {"param", BShellParamCmdLs, "display system parameter", "param ls [-r] [name]", "param ls"},
447         {"param", BShellParamCmdGet, "get system parameter", "param get [name]", "param get"},
448         {"param", BShellParamCmdSet, "set system parameter", "param set name value", "param set"},
449         {"param", BShellParamCmdWait, "wait system parameter", "param wait name [value] [timeout]", "param wait"},
450         {"param", BShellParamCmdDump, "dump system parameter", "param dump [verbose]", "param dump"},
451         {"param", BShellParamCmdShell, "shell system parameter", "param shell [name]", "param shell"},
452     };
453     for (size_t i = sizeof(infos) / sizeof(infos[0]); i > 0; i--) {
454         BShellEnvRegisterCmd(shell, &infos[i - 1]);
455     }
456     return 0;
457 }
458 
BShellParamCmdRegister(BShellHandle shell,int execMode)459 int32_t BShellParamCmdRegister(BShellHandle shell, int execMode)
460 {
461     if (execMode) {
462         BShellParamCmdRegForShell(shell);
463     } else {
464         BShellParamCmdRegForIndepent(shell);
465     }
466     return 0;
467 }
468