diff --git a/services/src/init_cmds.c b/services/src/init_cmds.c index 04732110d..fe13d7170 100644 --- a/services/src/init_cmds.c +++ b/services/src/init_cmds.c @@ -122,92 +122,88 @@ inline int GetParamValue(const char *symValue, char *paramValue, unsigned int pa } #endif -struct CmdArgs* GetCmd(const char *cmdContent, const char *delim, int argsCount) +static struct CmdArgs *CopyCmd(struct CmdArgs *args, const char *cmd, size_t allocSize) +{ + if (cmd == NULL) { + return NULL; + } + + ctx->argv[ctx->argc] = calloc(sizeof(char), allocSize); + INIT_CHECK(ctx->argv[ctx->argc] != NULL, FreeCmd(ctx); + return NULL); + INIT_CHECK(GetParamValue(cmd, ctx->argv[ctx->argc], allocSize) == 0, FreeCmd(ctx); + return NULL); + ctx->argc += 1; + ctx->argv[ctx->argc] = NULL; + return ctx; +} + +#define SKIP_SPACES(p) \ + do { \ + while (isspace(*(p))) { \ + (p)++; \ + } \ + } while (0) + +struct CmdArgs *GetCmd(const char *cmdContent, const char *delim, int argsCount) { INIT_CHECK_RETURN_VALUE(cmdContent != NULL, NULL); struct CmdArgs *ctx = (struct CmdArgs *)malloc(sizeof(struct CmdArgs)); INIT_CHECK_RETURN_VALUE(ctx != NULL, NULL); - if (argsCount > SPACES_CNT_IN_CMD_MAX) { - INIT_LOGW("Too much arguments for command, max number is %d", SPACES_CNT_IN_CMD_MAX); - argsCount = SPACES_CNT_IN_CMD_MAX; - } ctx->argv = (char**)malloc(sizeof(char*) * (size_t)argsCount + 1); INIT_CHECK(ctx->argv != NULL, FreeCmd(ctx); return NULL); - char tmpCmd[MAX_BUFFER]; + char tmpCmd[MAX_BUFFER] = {0}; size_t cmdLength = strlen(cmdContent); if (cmdLength > MAX_BUFFER - 1) { - INIT_LOGE("command line is too larget, should not bigger than %d. ignore...\n", MAX_BUFFER); FreeCmd(ctx); return NULL; } INIT_CHECK(strncpy_s(tmpCmd, MAX_BUFFER - 1, cmdContent, cmdLength) == EOK, FreeCmd(ctx); return NULL); - tmpCmd[strlen(cmdContent)] = '\0'; char *p = tmpCmd; - INIT_CHECK_RETURN_VALUE(p != NULL, NULL); char *token = NULL; size_t allocSize = 0; // Skip lead whitespaces - while (isspace(*p)) { - p++; - } + SKIP_SPACES(p); ctx->argc = 0; token = strstr(p, delim); if (token == NULL) { // No whitespaces // Make surce there is enough memory to store parameter value allocSize = (size_t)(cmdLength + MAX_PARAM_VALUE_LEN + 1); - ctx->argv[ctx->argc] = calloc(sizeof(char), allocSize); - INIT_CHECK(ctx->argv[ctx->argc] != NULL, FreeCmd(ctx); - return NULL); - INIT_CHECK(GetParamValue(p, ctx->argv[ctx->argc], allocSize) == 0, FreeCmd(ctx); - return NULL); - ctx->argc += 1; - ctx->argv[ctx->argc] = NULL; - return ctx; + return CopyCmd(ctx, p, allocSize); } - int index = ctx->argc; while (token != NULL) { // Too more arguments, treat rest of data as one argument - if (index == (argsCount - 1)) { + if (ctx->argc == (argsCount - 1)) { break; } *token = '\0'; // replace it with '\0'; allocSize = (size_t)((token - p) + MAX_PARAM_VALUE_LEN + 1); - ctx->argv[index] = calloc(sizeof(char), allocSize); - INIT_CHECK(ctx->argv[index] != NULL, FreeCmd(ctx); - return NULL); - INIT_CHECK(GetParamValue(p, ctx->argv[index], allocSize) == 0, - FreeCmd(ctx); - return NULL); + ctx = CopyCmd(ctx, p, allocSize); + INIT_CHECK_RETURN_VALUE(ctx != NULL, return NULL); p = token + 1; // skip '\0' // Skip lead whitespaces - while (isspace(*p)) { - p++; - } - index++; + SKIP_SPACES(p) + ctx->argc++; token = strstr(p, delim); } - ctx->argc = index; if (p < tmpCmd + cmdLength) { // no more white space or encounter max argument count size_t restSize = tmpCmd + cmdLength - p; allocSize = restSize + MAX_PARAM_VALUE_LEN + 1; - ctx->argv[index] = calloc(sizeof(char), allocSize); - INIT_CHECK(ctx->argv[index] != NULL, FreeCmd(ctx); return NULL); - INIT_CHECK(GetParamValue(p, ctx->argv[index], allocSize) == 0, - FreeCmd(ctx); return NULL); - ctx->argc = index + 1; + ctx = CopyCmd(ctx, p, allocSize); + INIT_CHECK_RETURN_VALUE(ctx != NULL, return NULL); } - ctx->argv[ctx->argc] = NULL; + ctx->argv[++ctx->argc] = NULL; return ctx; } @@ -473,6 +469,10 @@ static void DoChown(const char *cmdContent, int maxArg) uid_t owner = DecodeUid(ctx->argv[0]); gid_t group = DecodeUid(ctx->argv[1]); + if (owner == (uid_t) -1 || group == (uid_t)-1) { + INIT_LOGE("Change path owner with invalid user/group"); + return; + } const int pathPos = 2; if (chown(ctx->argv[pathPos], owner, group) != 0) { @@ -542,7 +542,10 @@ static void DoMkDir(const char *cmdContent, int maxArg) } } if (rc < 0) { - INIT_LOGE("Run command mkdir failed"); + INIT_LOGE("Run command mkdir failed, unlink path"); + if (unlink(ctx->argv[0]) < 0) { + INIT_LOGE("Failed unlink %s errno %d ", ctx->argv[0], errno); + } } } while (0); diff --git a/services/src/init_service.c b/services/src/init_service.c index a9d74a5a0..8cbe56dc2 100644 --- a/services/src/init_service.c +++ b/services/src/init_service.c @@ -148,6 +148,30 @@ static void OpenConsole(void) return; } +static void WriteServicePid(Service *service, pid_t pid) +{ + char pidString[MAX_PID_STRING_LENGTH]; + INIT_ERROR_CHECK(snprintf_s(pidString, MAX_PID_STRING_LENGTH, MAX_PID_STRING_LENGTH - 1, "%d", pid) >= 0, + _exit(0x7f), "Build pid string failed"); + + for (int i = 0; i < MAX_WRITEPID_FILES; i++) { + if (service->writepidFiles[i] == NULL) { + break; + } + char *realPath = realpath(service->writepidFiles[i], NULL); + if (realPath == NULL) { + continue; + } + free(realPath); + realPath = NULL; + FILE *fd = fopen(realPath, "wb"); + INIT_ERROR_CHECK(fd != NULL, continue, "Open file %s failed, err = %d", service->writepidFiles[i], errno); + INIT_CHECK_ONLY_ELOG(fwrite(pidString, 1, strlen(pidString), fd) == strlen(pidString), + "write pid %s to file %s failed, err = %d", pidString, service->writepidFiles[i], errno); + fclose(fd); + } +} + int ServiceStart(Service *service) { INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "start service failed! null ptr."); @@ -161,38 +185,17 @@ int ServiceStart(Service *service) service->attribute &= (~(SERVICE_ATTR_NEED_RESTART | SERVICE_ATTR_NEED_STOP)); INIT_ERROR_CHECK(stat(service->pathArgs[0], &pathStat) == 0, service->attribute |= SERVICE_ATTR_INVALID; return SERVICE_FAILURE, "start service %s invalid, please check %s.", service->name, service->pathArgs[0]); - int pid = fork(); + pid_t pid = fork(); if (pid == 0) { if (service->socketCfg != NULL) { // start socket service - INIT_LOGI("Create socket "); - INIT_ERROR_CHECK(DoCreateSocket(service->socketCfg) >= 0, _exit(0x7f), "DoCreateSocket failed. "); + INIT_ERROR_CHECK(DoCreateSocket(service->socketCfg) >= 0, _exit(0x7f), "Create Socket failed. "); } if (service->attribute & SERVICE_ATTR_CONSOLE) { OpenConsole(); } INIT_ERROR_CHECK(SetPerms(service) == SERVICE_SUCCESS, _exit(0x7f), "service %s exit! set perms failed! err %d.", service->name, errno); - char pidString[MAX_PID_STRING_LENGTH]; - pid_t childPid = getpid(); - INIT_ERROR_CHECK(snprintf_s(pidString, MAX_PID_STRING_LENGTH, MAX_PID_STRING_LENGTH - 1, "%d", childPid) >= 0, - _exit(0x7f), "start service writepid sprintf failed."); - for (int i = 0; i < MAX_WRITEPID_FILES; i++) { - if (service->writepidFiles[i] == NULL) { - continue; - } - char *realPath = realpath(service->writepidFiles[i], NULL); - if (realPath == NULL) { - continue; - } - FILE *fd = fopen(realPath, "wb"); - free(realPath); - realPath = NULL; - INIT_ERROR_CHECK(fd != NULL, continue, "writepidFiles %s invalid.", service->writepidFiles[i]); - INIT_CHECK_ONLY_ELOG(fwrite(pidString, 1, strlen(pidString), fd) == strlen(pidString), - "writepid error.file:%s pid:%s", service->writepidFiles[i], pidString); - fclose(fd); - INIT_LOGI("writepid filename=%s, childPid=%s, ok", service->writepidFiles[i], pidString); - } + WriteServicePid(service, getpid()); INIT_LOGI("service->name is %s ", service->name); #ifndef OHOS_LITE if (service->importance != 0) {