mirror of
https://gitee.com/openharmony/startup_init
synced 2025-02-12 07:11:14 +00:00
Merge branch 'master' of gitee.com:openharmony/startup_init into 0821_mem
Signed-off-by: 钟柠 <zhongning5@huawei.com>
This commit is contained in:
commit
0096b689bf
@ -121,11 +121,13 @@ int DoFormat(const char *devPath, const char *fsType)
|
||||
} else if (strcmp(fsType, "f2fs") == 0) {
|
||||
#ifdef __MUSL__
|
||||
char *formatCmds[] = {
|
||||
"/bin/mkfs.f2fs", "-d1", "-O", "encrypt", "-O", "quota", "-O", "verity", (char *)devPath, NULL
|
||||
"/bin/mkfs.f2fs", "-d1", "-O", "encrypt", "-O", "quota", "-O", "verity", "-O", "project_quota,extra_attr",
|
||||
"-O", "sb_checksum", (char *)devPath, NULL
|
||||
};
|
||||
#else
|
||||
char *formatCmds[] = {
|
||||
"/bin/make_f2fs", "-d1", "-O", "encrypt", "-O", "quota", "-O", "verity", (char *)devPath, NULL
|
||||
"/bin/make_f2fs", "-d1", "-O", "encrypt", "-O", "quota", "-O", "verity", "-O", "project_quota,extra_attr",
|
||||
"-O", "sb_checksum", (char *)devPath, NULL
|
||||
};
|
||||
#endif
|
||||
int argc = ARRAY_LENGTH(formatCmds);
|
||||
|
69
services/include/init_error.h
Normal file
69
services/include/init_error.h
Normal file
@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2023 Huawei Device Co., Ltd.
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef INIT_ERROR_H
|
||||
#define INIT_ERROR_H
|
||||
|
||||
#include "beget_ext.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* Expand this list if necessary. */
|
||||
#define INIT_ERRNO_MAP(XX) \
|
||||
XX(EPARAMETER, "Invalid parameter") \
|
||||
XX(EFORMAT, "Format string fail") \
|
||||
XX(ECFG, "cfg error") \
|
||||
XX(EPATH, "Invalid path") \
|
||||
XX(EFORK, "Fork fail") \
|
||||
XX(ESANDBOX, "Create sandbox fail") \
|
||||
XX(EACCESSTOKEN, "Set access token fail") \
|
||||
XX(ESOCKET, "Create socket fail") \
|
||||
XX(EFILE, "Create file fail") \
|
||||
XX(ECONSOLE, "Open console fail") \
|
||||
XX(EHOLDER, "Publish holder fail") \
|
||||
XX(EBINDCORE, "Bind core fail") \
|
||||
XX(EKEEPCAP, "Set keep capability fail") \
|
||||
XX(EGIDSET, "Set gid fail") \
|
||||
XX(ESECCOMP, "Set SECCOMP fail") \
|
||||
XX(EUIDSET, "Set uid fail") \
|
||||
XX(ECAP, "Set capability fail") \
|
||||
XX(EWRITEPID, "Write pid fail") \
|
||||
XX(ECONTENT, "Set sub content fail") \
|
||||
XX(EPRIORITY, "Set priority fail") \
|
||||
XX(EEXEC_CONTENT, "Set exec content fail") \
|
||||
XX(EEXEC, "Exec fail")
|
||||
|
||||
typedef enum {
|
||||
INIT_OK,
|
||||
#define XX(code, _) INIT_ ## code,
|
||||
INIT_ERRNO_MAP(XX)
|
||||
#undef XX
|
||||
} InitErrno;
|
||||
|
||||
struct InitErrMap {
|
||||
int code;
|
||||
const char *info;
|
||||
} ;
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#endif // INIT_UTILS_H
|
@ -78,7 +78,7 @@ void FreeStringVector(char **vector, int count);
|
||||
int InUpdaterMode(void);
|
||||
int StringReplaceChr(char *strl, char oldChr, char newChr);
|
||||
|
||||
void OpenConsole(void);
|
||||
int OpenConsole(void);
|
||||
void TrimTail(char *str, char c);
|
||||
char *TrimHead(char *str, char c);
|
||||
|
||||
@ -87,7 +87,6 @@ INIT_LOCAL_API uint32_t IntervalTime(struct timespec *startTime, struct timespec
|
||||
INIT_LOCAL_API int StringToULL(const char *str, unsigned long long int *out);
|
||||
INIT_LOCAL_API int StringToLL(const char *str, long long int *out);
|
||||
void CloseStdio(void);
|
||||
void RedirectStdio(int fd);
|
||||
|
||||
int GetServiceGroupIdByPid(pid_t pid, gid_t *gids, uint32_t gidSize);
|
||||
int GetParameterFromCmdLine(const char *paramName, char *value, size_t valueLen);
|
||||
|
@ -22,6 +22,7 @@
|
||||
|
||||
#include "cJSON.h"
|
||||
#include "init_cmds.h"
|
||||
#include "init_error.h"
|
||||
#include "init_service_file.h"
|
||||
#include "init_service_socket.h"
|
||||
#include "list.h"
|
||||
@ -149,7 +150,6 @@ typedef struct Service_ {
|
||||
ServiceArgs permAclsArgs;
|
||||
Perms servPerm;
|
||||
ServiceArgs pathArgs;
|
||||
ServiceArgs extraArgs;
|
||||
ServiceArgs writePidArgs;
|
||||
CmdLines *restartArg;
|
||||
ServiceSocket *socketCfg;
|
||||
@ -161,12 +161,13 @@ typedef struct Service_ {
|
||||
cpu_set_t *cpuSet;
|
||||
struct ListNode extDataNode;
|
||||
ConfigContext context;
|
||||
InitErrno lastErrno;
|
||||
} Service;
|
||||
#pragma pack()
|
||||
|
||||
Service *GetServiceByPid(pid_t pid);
|
||||
Service *GetServiceByName(const char *servName);
|
||||
int ServiceStart(Service *service);
|
||||
int ServiceStart(Service *service, ServiceArgs *pathArgs);
|
||||
int ServiceStop(Service *service);
|
||||
void ServiceReap(Service *service);
|
||||
void ReapService(Service *service);
|
||||
@ -175,7 +176,7 @@ void NotifyServiceChange(Service *service, int status);
|
||||
int IsForbidden(const char *fieldStr);
|
||||
int SetImportantValue(Service *curServ, const char *attrName, int value, int flag);
|
||||
int InitServiceCaps(const cJSON *curArrItem, Service *curServ);
|
||||
int ServiceExec(const Service *service);
|
||||
int ServiceExec(Service *service, const ServiceArgs *pathArgs);
|
||||
void CloseServiceFds(Service *service, bool needFree);
|
||||
int UpdaterServiceFds(Service *service, int *fds, size_t fdCount);
|
||||
int SetAccessToken(const Service *service);
|
||||
@ -184,7 +185,10 @@ void ServiceStopTimer(Service *service);
|
||||
void ServiceStartTimer(Service *service, uint64_t timeout);
|
||||
void IsEnableSandbox(void);
|
||||
void EnterServiceSandbox(Service *service);
|
||||
void SetServiceEnterSandbox(const char *execPath, unsigned int attribute);
|
||||
int SetServiceEnterSandbox(const Service *service, const char *execPath);
|
||||
|
||||
int CreateServiceFile(Service *service);
|
||||
void CloseServiceFile(ServiceFile *fileOpt);
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
|
@ -41,9 +41,6 @@ typedef struct ServiceFile_ {
|
||||
char fileName[0];
|
||||
} ServiceFile;
|
||||
|
||||
void CreateServiceFile(ServiceFile *fileOpt);
|
||||
void CloseServiceFile(ServiceFile *fileOpt);
|
||||
|
||||
#ifdef __cplusplus
|
||||
#if __cplusplus
|
||||
}
|
||||
|
@ -134,21 +134,21 @@ static void ServiceHookExecute(const char *serviceName, const char *info, int st
|
||||
}
|
||||
#endif
|
||||
|
||||
static int ServiceCheck(const Service *service)
|
||||
static int ServiceSetGid(const Service *service)
|
||||
{
|
||||
if (service->servPerm.gIDCnt == 0) {
|
||||
// use uid as gid
|
||||
INIT_ERROR_CHECK(setgid(service->servPerm.uID) == 0, return SERVICE_FAILURE,
|
||||
"SetPerms, setgid for %s failed. %d", service->name, errno);
|
||||
"Service error %d %s, failed to set gid.", errno, service->name);
|
||||
}
|
||||
if (service->servPerm.gIDCnt > 0) {
|
||||
INIT_ERROR_CHECK(setgid(service->servPerm.gIDArray[0]) == 0, return SERVICE_FAILURE,
|
||||
"SetPerms, setgid for %s failed. %d", service->name, errno);
|
||||
"Service error %d %s, failed to set gid.", errno, service->name);
|
||||
}
|
||||
if (service->servPerm.gIDCnt > 1) {
|
||||
INIT_ERROR_CHECK(setgroups(service->servPerm.gIDCnt - 1, (const gid_t *)&service->servPerm.gIDArray[1]) == 0,
|
||||
return SERVICE_FAILURE,
|
||||
"SetPerms, setgroups failed. errno = %d, gIDCnt=%d", errno, service->servPerm.gIDCnt);
|
||||
"Service error %d %s, failed to set gid.", errno, service->name);
|
||||
}
|
||||
|
||||
return SERVICE_SUCCESS;
|
||||
@ -156,20 +156,23 @@ static int ServiceCheck(const Service *service)
|
||||
|
||||
static int SetPerms(const Service *service)
|
||||
{
|
||||
INIT_CHECK_RETURN_VALUE(KeepCapability() == 0, SERVICE_FAILURE);
|
||||
INIT_ERROR_CHECK(KeepCapability() == 0,
|
||||
return INIT_EKEEPCAP,
|
||||
"Service error %d %s, failed to set keep capability.", errno, service->name);
|
||||
|
||||
INIT_ERROR_CHECK(ServiceCheck(service) == SERVICE_SUCCESS, return SERVICE_FAILURE,
|
||||
"set seccomp policy failed for service %s", service->name);
|
||||
INIT_ERROR_CHECK(ServiceSetGid(service) == SERVICE_SUCCESS,
|
||||
return INIT_EGIDSET,
|
||||
"Service error %d %s, failed to set gid.", errno, service->name);
|
||||
|
||||
// set seccomp policy before setuid
|
||||
INIT_ERROR_CHECK(SetSystemSeccompPolicy(service) == SERVICE_SUCCESS, return SERVICE_FAILURE,
|
||||
"set seccomp policy failed for service %s", service->name);
|
||||
INIT_ERROR_CHECK(SetSystemSeccompPolicy(service) == SERVICE_SUCCESS,
|
||||
return INIT_ESECCOMP,
|
||||
"Service error %d %s, failed to set system seccomp policy.", errno, service->name);
|
||||
|
||||
if (service->servPerm.uID != 0) {
|
||||
if (setuid(service->servPerm.uID) != 0) {
|
||||
INIT_LOGE("setuid of service: %s failed, uid = %d", service->name, service->servPerm.uID);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
INIT_ERROR_CHECK(setuid(service->servPerm.uID) == 0,
|
||||
return INIT_EUIDSET,
|
||||
"Service error %d %s, failed to set uid.", errno, service->name);
|
||||
}
|
||||
|
||||
struct __user_cap_header_struct capHeader;
|
||||
@ -194,10 +197,15 @@ static int SetPerms(const Service *service)
|
||||
"capset failed for service: %s, error: %d", service->name, errno);
|
||||
for (unsigned int i = 0; i < service->servPerm.capsCnt; ++i) {
|
||||
if (service->servPerm.caps[i] == FULL_CAP) {
|
||||
return SetAllAmbientCapability();
|
||||
int ret = SetAllAmbientCapability();
|
||||
INIT_ERROR_CHECK(ret == 0,
|
||||
return INIT_ECAP,
|
||||
"Service error %d %s, failed to set ambient capability.", errno, service->name);
|
||||
return 0;
|
||||
}
|
||||
INIT_ERROR_CHECK(SetAmbientCapability(service->servPerm.caps[i]) == 0, return SERVICE_FAILURE,
|
||||
"SetAmbientCapability failed for service: %s", service->name);
|
||||
INIT_ERROR_CHECK(SetAmbientCapability(service->servPerm.caps[i]) == 0,
|
||||
return INIT_ECAP,
|
||||
"Service error %d %s, failed to set ambient capability.", errno, service->name);
|
||||
}
|
||||
#ifndef OHOS_LITE
|
||||
/*
|
||||
@ -260,30 +268,33 @@ void CloseServiceFds(Service *service, bool needFree)
|
||||
}
|
||||
}
|
||||
|
||||
static void PublishHoldFds(Service *service)
|
||||
static int PublishHoldFds(Service *service)
|
||||
{
|
||||
INIT_ERROR_CHECK(service != NULL, return, "Publish hold fds with invalid service");
|
||||
char fdBuffer[MAX_FD_HOLDER_BUFFER] = {};
|
||||
if (service->fdCount > 0 && service->fds != NULL) {
|
||||
size_t pos = 0;
|
||||
for (size_t i = 0; i < service->fdCount; i++) {
|
||||
int fd = dup(service->fds[i]);
|
||||
if (fd < 0) {
|
||||
INIT_LOGE("Duplicate file descriptors of Service \' %s \' failed. err = %d", service->name, errno);
|
||||
continue;
|
||||
}
|
||||
INIT_ERROR_CHECK(!(snprintf_s((char *)fdBuffer + pos, sizeof(fdBuffer) - pos, sizeof(fdBuffer) - 1,
|
||||
"%d ", fd) < 0), return, "snprintf_s failed err=%d", errno);
|
||||
pos = strlen(fdBuffer);
|
||||
}
|
||||
fdBuffer[pos - 1] = '\0'; // Remove last ' '
|
||||
INIT_LOGI("fd buffer: [%s]", fdBuffer);
|
||||
char envName[MAX_BUFFER_LEN] = {};
|
||||
INIT_ERROR_CHECK(!(snprintf_s(envName, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, ENV_FD_HOLD_PREFIX"%s",
|
||||
service->name) < 0), return, "snprintf_s failed err=%d", errno);
|
||||
INIT_CHECK_ONLY_ELOG(!(setenv(envName, fdBuffer, 1) < 0), "Failed to set env %s", envName);
|
||||
INIT_LOGI("File descriptors of Service \' %s \' published", service->name);
|
||||
INIT_ERROR_CHECK(service != NULL, return INIT_EPARAMETER, "Publish hold fds with invalid service");
|
||||
if (service->fdCount == 0 || service->fds == NULL) {
|
||||
return 0;
|
||||
}
|
||||
char fdBuffer[MAX_FD_HOLDER_BUFFER] = {};
|
||||
char envName[MAX_BUFFER_LEN] = {};
|
||||
int ret = snprintf_s(envName, MAX_BUFFER_LEN, MAX_BUFFER_LEN - 1, ENV_FD_HOLD_PREFIX"%s", service->name);
|
||||
INIT_ERROR_CHECK(ret >= 0, return INIT_EFORMAT,
|
||||
"Service error %d %s, failed to format string for publish", ret, service->name);
|
||||
|
||||
size_t pos = 0;
|
||||
for (size_t i = 0; i < service->fdCount; i++) {
|
||||
int fd = dup(service->fds[i]);
|
||||
if (fd < 0) {
|
||||
INIT_LOGW("Service warning %d %s, failed to dup fd for publish", errno, service->name);
|
||||
continue;
|
||||
}
|
||||
ret = snprintf_s((char *)fdBuffer + pos, sizeof(fdBuffer) - pos, sizeof(fdBuffer) - 1, "%d ", fd);
|
||||
INIT_ERROR_CHECK(ret >= 0, return INIT_EFORMAT,
|
||||
"Service error %d %s, failed to format fd for publish", ret, service->name);
|
||||
pos += ret;
|
||||
}
|
||||
fdBuffer[pos - 1] = '\0'; // Remove last ' '
|
||||
INIT_LOGI("Service %s publish fd [%s]", service->name, fdBuffer);
|
||||
return setenv(envName, fdBuffer, 1);
|
||||
}
|
||||
|
||||
static int BindCpuCore(Service *service)
|
||||
@ -315,45 +326,71 @@ static void ClearEnvironment(Service *service)
|
||||
return;
|
||||
}
|
||||
|
||||
static int InitServiceProperties(Service *service)
|
||||
static int InitServiceProperties(Service *service, const ServiceArgs *pathArgs)
|
||||
{
|
||||
INIT_ERROR_CHECK(service != NULL, return -1, "Invalid parameter.");
|
||||
SetServiceEnterSandbox(service->pathArgs.argv[0], service->attribute);
|
||||
INIT_CHECK_ONLY_ELOG(SetAccessToken(service) == SERVICE_SUCCESS,
|
||||
"Set service %s access token failed", service->name);
|
||||
int ret = SetServiceEnterSandbox(service, pathArgs->argv[0]);
|
||||
if (ret != 0) {
|
||||
INIT_LOGW("Service warning %d %s, failed to enter sandbox.", ret, service->name);
|
||||
service->lastErrno = INIT_ESANDBOX;
|
||||
}
|
||||
ret = SetAccessToken(service);
|
||||
if (ret != 0) {
|
||||
INIT_LOGW("Service warning %d %s, failed to set access token.", ret, service->name);
|
||||
service->lastErrno = INIT_EACCESSTOKEN;
|
||||
}
|
||||
|
||||
// deal start job
|
||||
if (service->serviceJobs.jobsName[JOB_ON_START] != NULL) {
|
||||
DoJobNow(service->serviceJobs.jobsName[JOB_ON_START]);
|
||||
}
|
||||
ClearEnvironment(service);
|
||||
if (!IsOnDemandService(service)) {
|
||||
INIT_ERROR_CHECK(CreateServiceSocket(service) >= 0, return -1,
|
||||
"service %s exit! create socket failed!", service->name);
|
||||
INIT_ERROR_CHECK(CreateServiceSocket(service) == 0,
|
||||
service->lastErrno = INIT_ESOCKET;
|
||||
return INIT_ESOCKET,
|
||||
"Service error %d %s, failed to create service socket.", errno, service->name);
|
||||
}
|
||||
INIT_ERROR_CHECK(CreateServiceFile(service) == 0,
|
||||
service->lastErrno = INIT_EFILE;
|
||||
return INIT_EFILE,
|
||||
"Service error %d %s, failed to create service file.", errno, service->name);
|
||||
|
||||
CreateServiceFile(service->fileCfg);
|
||||
if ((service->attribute & SERVICE_ATTR_CONSOLE)) {
|
||||
OpenConsole();
|
||||
INIT_ERROR_CHECK(OpenConsole() == 0,
|
||||
service->lastErrno = INIT_ECONSOLE;
|
||||
return INIT_ECONSOLE,
|
||||
"Service error %d %s, failed to open console.", errno, service->name);
|
||||
}
|
||||
|
||||
PublishHoldFds(service);
|
||||
INIT_ERROR_CHECK(PublishHoldFds(service) == 0,
|
||||
service->lastErrno = INIT_EHOLDER;
|
||||
return INIT_EHOLDER,
|
||||
"Service error %d %s, failed to publish fd", errno, service->name);
|
||||
|
||||
INIT_CHECK_ONLY_ELOG(BindCpuCore(service) == SERVICE_SUCCESS,
|
||||
"binding core number failed for service %s", service->name);
|
||||
"Service warning %d %s, failed to publish fd", errno, service->name);
|
||||
|
||||
// permissions
|
||||
INIT_ERROR_CHECK(SetPerms(service) == SERVICE_SUCCESS, return -1,
|
||||
"service %s exit! set perms failed! err %d.", service->name, errno);
|
||||
ret = SetPerms(service);
|
||||
INIT_ERROR_CHECK(ret == SERVICE_SUCCESS,
|
||||
service->lastErrno = ret;
|
||||
return ret,
|
||||
"Service error %d %s, failed to set permissions.", ret, service->name);
|
||||
|
||||
// write pid
|
||||
INIT_ERROR_CHECK(WritePid(service) == SERVICE_SUCCESS, return -1,
|
||||
"service %s exit! write pid failed!", service->name);
|
||||
INIT_ERROR_CHECK(WritePid(service) == SERVICE_SUCCESS,
|
||||
service->lastErrno = INIT_EWRITEPID;
|
||||
return INIT_EWRITEPID,
|
||||
"Service error %d %s, failed to write pid.", errno, service->name);
|
||||
|
||||
PluginExecCmdByName("setServiceContent", service->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void EnterServiceSandbox(Service *service)
|
||||
{
|
||||
INIT_ERROR_CHECK(InitServiceProperties(service) == 0, return, "Failed init service property");
|
||||
INIT_ERROR_CHECK(InitServiceProperties(service, &service->pathArgs) == 0, return, "Failed init service property");
|
||||
if (service->importance != 0) {
|
||||
if (setpriority(PRIO_PROCESS, 0, service->importance) != 0) {
|
||||
INIT_LOGE("setpriority failed for %s, importance = %d, err=%d",
|
||||
@ -390,12 +427,11 @@ static void AddUpdateList(ServiceArgs *args, char *updateList)
|
||||
free(argvOrig);
|
||||
}
|
||||
|
||||
void CheckModuleUpdate(ServiceArgs *args)
|
||||
static void CheckModuleUpdate(ServiceArgs *args)
|
||||
{
|
||||
INIT_LOGI("CheckModuleUpdate start");
|
||||
void *handle = dlopen("libmodule_update.z.so", RTLD_NOW);
|
||||
INIT_ERROR_CHECK(handle != NULL, return, "dlopen module update lib failed with error:%s", dlerror());
|
||||
INIT_LOGI("dlopen success");
|
||||
typedef char* (*ExtFunc)(int, char **);
|
||||
ExtFunc func = (ExtFunc)dlsym(handle, "CheckModuleUpdate");
|
||||
if (func == NULL) {
|
||||
@ -509,21 +545,23 @@ static int32_t WaitForDebugger(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
int ServiceStart(Service *service)
|
||||
int ServiceStart(Service *service, ServiceArgs *pathArgs)
|
||||
{
|
||||
INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "start service failed! null ptr.");
|
||||
INIT_ERROR_CHECK(service->pid <= 0, return SERVICE_SUCCESS, "Service %s already started", service->name);
|
||||
INIT_ERROR_CHECK(service->pathArgs.count > 0,
|
||||
INIT_ERROR_CHECK(service->pid <= 0, return SERVICE_SUCCESS, "Service info %s already started", service->name);
|
||||
INIT_ERROR_CHECK(pathArgs != NULL && pathArgs->count > 0,
|
||||
return SERVICE_FAILURE, "start service %s pathArgs is NULL.", service->name);
|
||||
|
||||
INIT_LOGI("Service info %s starting", service->name);
|
||||
if (service->attribute & SERVICE_ATTR_INVALID) {
|
||||
INIT_LOGE("start service %s invalid.", service->name);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
struct stat pathStat = { 0 };
|
||||
service->attribute &= (~(SERVICE_ATTR_NEED_RESTART | SERVICE_ATTR_NEED_STOP));
|
||||
if (stat(service->pathArgs.argv[0], &pathStat) != 0) {
|
||||
if (stat(pathArgs->argv[0], &pathStat) != 0) {
|
||||
service->attribute |= SERVICE_ATTR_INVALID;
|
||||
service->lastErrno = INIT_EPATH;
|
||||
INIT_LOGE("start service %s invalid, please check %s.", service->name, service->pathArgs.argv[0]);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
@ -536,18 +574,12 @@ int ServiceStart(Service *service)
|
||||
int pid = fork();
|
||||
if (pid == 0) {
|
||||
// set selinux label by context
|
||||
if (service->context.type != INIT_CONTEXT_MAIN) {
|
||||
SetSubInitContext(&service->context, service->name);
|
||||
if (service->context.type != INIT_CONTEXT_MAIN && SetSubInitContext(&service->context, service->name) != 0) {
|
||||
service->lastErrno = INIT_ECONTENT;
|
||||
}
|
||||
|
||||
if (service->attribute & SERVICE_ATTR_MODULE_UPDATE) {
|
||||
ServiceArgs* args = NULL;
|
||||
if (service->extraArgs.argv != NULL && service->extraArgs.count > 0) {
|
||||
args = &service->extraArgs;
|
||||
} else {
|
||||
args = &service->pathArgs;
|
||||
}
|
||||
CheckModuleUpdate(args);
|
||||
CheckModuleUpdate(pathArgs);
|
||||
}
|
||||
#ifdef IS_DEBUG_VERSION
|
||||
// only the image is debuggable and need debug, then wait for debugger
|
||||
@ -556,15 +588,18 @@ int ServiceStart(Service *service)
|
||||
}
|
||||
#endif
|
||||
// fail must exit sub process
|
||||
INIT_ERROR_CHECK(InitServiceProperties(service) == 0,
|
||||
_exit(PROCESS_EXIT_CODE), "Failed init service property");
|
||||
ServiceExec(service);
|
||||
_exit(PROCESS_EXIT_CODE);
|
||||
int ret = InitServiceProperties(service, pathArgs);
|
||||
INIT_ERROR_CHECK(ret == 0,
|
||||
_exit(service->lastErrno), "Service error %d %s, failed to set properties", ret, service->name);
|
||||
|
||||
(void)ServiceExec(service, pathArgs);
|
||||
_exit(service->lastErrno);
|
||||
} else if (pid < 0) {
|
||||
INIT_LOGE("start service %s fork failed!", service->name);
|
||||
INIT_LOGE("Service error %d %s, failed to fork.", errno, service->name);
|
||||
service->lastErrno = INIT_EFORK;
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
INIT_LOGI("Service %s(pid %d) started", service->name, pid);
|
||||
INIT_LOGI("Service info %s(pid %d) started", service->name, pid);
|
||||
service->pid = pid;
|
||||
NotifyServiceChange(service, SERVICE_STARTED);
|
||||
#ifndef OHOS_LITE
|
||||
@ -685,12 +720,12 @@ static void ServiceReapHookExecute(Service *service)
|
||||
void ServiceReap(Service *service)
|
||||
{
|
||||
INIT_CHECK(service != NULL, return);
|
||||
INIT_LOGI("Reap service %s, pid %d.", service->name, service->pid);
|
||||
INIT_LOGI("Service info %s reap pid %d.", service->name, service->pid);
|
||||
service->pid = -1;
|
||||
NotifyServiceChange(service, SERVICE_STOPPED);
|
||||
|
||||
if (service->attribute & SERVICE_ATTR_INVALID) {
|
||||
INIT_LOGE("Reap service %s invalid.", service->name);
|
||||
INIT_LOGE("Service error %s invalid service.", service->name);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -728,13 +763,12 @@ void ServiceReap(Service *service)
|
||||
}
|
||||
if (service->attribute & SERVICE_ATTR_CRITICAL) { // critical
|
||||
if (!CalculateCrashTime(service, service->crashTime, service->crashCount)) {
|
||||
INIT_LOGE("Critical service \" %s \" crashed %d times, rebooting system",
|
||||
service->name, service->crashCount);
|
||||
INIT_LOGE("Service error %s critical service crashed.", service->name, service->crashCount);
|
||||
ExecReboot("panic");
|
||||
}
|
||||
} else if (!(service->attribute & SERVICE_ATTR_NEED_RESTART)) {
|
||||
if (!CalculateCrashTime(service, service->crashTime, service->crashCount)) {
|
||||
INIT_LOGE("Service name=%s, crash %d times, no more start.", service->name, service->crashCount);
|
||||
INIT_LOGE("Service error %s crash %d times, no more start.", service->name, service->crashCount);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -745,7 +779,7 @@ void ServiceReap(Service *service)
|
||||
if (service->serviceJobs.jobsName[JOB_ON_RESTART] != NULL) {
|
||||
DoJobNow(service->serviceJobs.jobsName[JOB_ON_RESTART]);
|
||||
}
|
||||
ret = ServiceStart(service);
|
||||
ret = ServiceStart(service, &service->pathArgs);
|
||||
INIT_CHECK_ONLY_ELOG(ret == SERVICE_SUCCESS, "reap service %s start failed!", service->name);
|
||||
service->attribute &= (~SERVICE_ATTR_NEED_RESTART);
|
||||
}
|
||||
@ -839,7 +873,7 @@ static void ServiceTimerStartProcess(const TimerHandle handler, void *context)
|
||||
// Before start the service, stop service timer.
|
||||
// make sure it will not enter timer handler next time.
|
||||
ServiceStopTimer(service);
|
||||
int ret = ServiceStart(service);
|
||||
int ret = ServiceStart(service, &service->pathArgs);
|
||||
if (ret != SERVICE_SUCCESS) {
|
||||
INIT_LOGE("Start service \' %s \' in timer failed", service->name);
|
||||
}
|
||||
|
@ -53,11 +53,11 @@ int ParseInitCfg(const char *configFile, void *context)
|
||||
UNUSED(context);
|
||||
INIT_LOGV("Parse init configs from %s", configFile);
|
||||
char *fileBuf = ReadFileToBuf(configFile);
|
||||
INIT_ERROR_CHECK(fileBuf != NULL, return -1, "Failed to read file content %s", configFile);
|
||||
INIT_ERROR_CHECK(fileBuf != NULL, return -1, "Cfg error, %s not found", configFile);
|
||||
|
||||
cJSON *fileRoot = cJSON_Parse(fileBuf);
|
||||
INIT_ERROR_CHECK(fileRoot != NULL, free(fileBuf);
|
||||
return -1, "Failed to parse json file %s", configFile);
|
||||
return -1, "Cfg error, failed to parse json %s ", configFile);
|
||||
|
||||
ParseInitCfgContents(configFile, fileRoot);
|
||||
cJSON_Delete(fileRoot);
|
||||
|
@ -69,22 +69,26 @@ static int SetFileEnv(int fd, const char *pathName)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void CreateServiceFile(ServiceFile *fileOpt)
|
||||
int CreateServiceFile(Service *service)
|
||||
{
|
||||
INIT_CHECK(fileOpt != NULL, return);
|
||||
ServiceFile *tmpFile = fileOpt;
|
||||
INIT_CHECK(service != NULL, return INIT_EPARAMETER);
|
||||
ServiceFile *tmpFile = service->fileCfg;
|
||||
int ret = 0;
|
||||
while (tmpFile != NULL) {
|
||||
int fd = CreateFile(tmpFile);
|
||||
if (fd < 0) {
|
||||
INIT_LOGE("Failed Create File err=%d ", errno);
|
||||
ret++;
|
||||
INIT_LOGE("Service error %d %s, failed to create file", errno, service->name, tmpFile->fileName);
|
||||
tmpFile = tmpFile->next;
|
||||
continue;
|
||||
}
|
||||
int ret = SetFileEnv(fd, tmpFile->fileName);
|
||||
INIT_CHECK_ONLY_ELOG(ret >= 0, "Failed Set File Env");
|
||||
if (SetFileEnv(fd, tmpFile->fileName) != 0) {
|
||||
ret++;
|
||||
INIT_LOGE("Service error %d %s, failed to set env for file", errno, service->name, tmpFile->fileName);
|
||||
}
|
||||
tmpFile = tmpFile->next;
|
||||
}
|
||||
return;
|
||||
return ret > 0 ? INIT_EFILE : 0;
|
||||
}
|
||||
|
||||
void CloseServiceFile(ServiceFile *fileOpt)
|
||||
|
@ -101,6 +101,7 @@ Service *AddService(const char *name)
|
||||
service->cpuSet = NULL;
|
||||
service->pid = -1;
|
||||
service->context.type = INIT_CONTEXT_MAIN;
|
||||
service->lastErrno = INIT_OK;
|
||||
OH_ListInit(&service->extDataNode);
|
||||
g_serviceSpace.serviceCount++;
|
||||
INIT_LOGV("AddService %s", node->name);
|
||||
@ -266,7 +267,7 @@ static int GetGid(cJSON *json, gid_t *gid, Service *curServ)
|
||||
INIT_LOGW("Service %s with invalid gid configuration", curServ->name);
|
||||
*gid = -1; // Invalid gid, set as -1
|
||||
}
|
||||
INIT_ERROR_CHECK(*gid != (gid_t)(-1), return SERVICE_FAILURE, "Failed to get gid for %s", curServ->name);
|
||||
INIT_CHECK_RETURN_VALUE(*gid != (gid_t)(-1), SERVICE_FAILURE);
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
@ -286,14 +287,15 @@ static int GetServiceGids(const cJSON *curArrItem, Service *curServ)
|
||||
if (curServ->servPerm.gIDArray != NULL) {
|
||||
free(curServ->servPerm.gIDArray);
|
||||
}
|
||||
curServ->servPerm.gIDArray = (gid_t *)malloc(sizeof(gid_t) * gidCount);
|
||||
curServ->servPerm.gIDArray = (gid_t *)malloc(sizeof(gid_t) * (gidCount + 1));
|
||||
INIT_ERROR_CHECK(curServ->servPerm.gIDArray != NULL, return SERVICE_FAILURE, "Failed to malloc err=%d", errno);
|
||||
curServ->servPerm.gIDCnt = gidCount;
|
||||
|
||||
gid_t gid;
|
||||
if (!cJSON_IsArray(arrItem)) {
|
||||
int ret = GetGid(arrItem, &gid, curServ);
|
||||
INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE, "Parse service %s gid failed.", curServ->name);
|
||||
INIT_ERROR_CHECK(ret == 0, return SERVICE_FAILURE,
|
||||
"Service error %s, failed to get gid from %s.", curServ->name, cJSON_Print(arrItem));
|
||||
curServ->servPerm.gIDArray[0] = gid;
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
@ -302,11 +304,14 @@ static int GetServiceGids(const cJSON *curArrItem, Service *curServ)
|
||||
cJSON *item = cJSON_GetArrayItem(arrItem, i);
|
||||
int ret = GetGid(item, &gid, curServ);
|
||||
if (ret != 0) {
|
||||
INIT_LOGW("Parse service %s gid failed from item %s.", curServ->name, cJSON_Print(item));
|
||||
INIT_LOGW("Service warning %s, failed to get gid from %s.", curServ->name, cJSON_Print(item));
|
||||
continue;
|
||||
}
|
||||
curServ->servPerm.gIDArray[gidArrayIndex++] = gid;
|
||||
}
|
||||
if (gidArrayIndex == 0) {
|
||||
curServ->servPerm.gIDArray[gidArrayIndex++] = curServ->servPerm.uID;
|
||||
}
|
||||
curServ->servPerm.gIDCnt = gidArrayIndex;
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
@ -319,7 +324,7 @@ static int GetServiceAttr(const cJSON *curArrItem, Service *curServ, const char
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
INIT_ERROR_CHECK(cJSON_IsNumber(filedJ), return SERVICE_FAILURE,
|
||||
"%s is null or is not a number, service name is %s", attrName, curServ->name);
|
||||
"Service error %s is null or is not a number %s", curServ->name, attrName);
|
||||
curServ->attribute &= ~flag;
|
||||
int value = (int)cJSON_GetNumberValue(filedJ);
|
||||
if (processAttr == NULL) {
|
||||
@ -934,7 +939,7 @@ static void ProcessConsoleEvent(const WatcherHandle handler, int fd, uint32_t *e
|
||||
return;
|
||||
}
|
||||
|
||||
if (ServiceStart(service) != SERVICE_SUCCESS) {
|
||||
if (ServiceStart(service, &service->pathArgs) != SERVICE_SUCCESS) {
|
||||
INIT_LOGE("Start console service failed");
|
||||
}
|
||||
return;
|
||||
@ -1022,7 +1027,8 @@ void ParseAllServices(const cJSON *fileRoot, const ConfigContext *context)
|
||||
}
|
||||
int ret = ParseOneService(curItem, service);
|
||||
if (ret != SERVICE_SUCCESS) {
|
||||
ReleaseService(service);
|
||||
INIT_LOGE("Service error %s parse config error.", service->name, cJSON_Print(curItem));
|
||||
service->lastErrno = INIT_ECFG;
|
||||
continue;
|
||||
}
|
||||
ret = ParseServiceSocket(curItem, service);
|
||||
@ -1047,7 +1053,7 @@ void ParseAllServices(const cJSON *fileRoot, const ConfigContext *context)
|
||||
}
|
||||
}
|
||||
|
||||
static Service *GetServiceByExtServName(const char *fullServName)
|
||||
static Service *GetServiceByExtServName(const char *fullServName, ServiceArgs *extraArgs)
|
||||
{
|
||||
INIT_ERROR_CHECK(fullServName != NULL, return NULL, "Failed get parameters");
|
||||
Service *service = GetServiceByName(fullServName);
|
||||
@ -1058,47 +1064,51 @@ static Service *GetServiceByExtServName(const char *fullServName)
|
||||
char *dstPtr[MAX_PATH_ARGS_CNT] = {NULL};
|
||||
int returnCount = SplitString(tmpServName, "|", dstPtr, MAX_PATH_ARGS_CNT);
|
||||
if (returnCount == 0) {
|
||||
INIT_LOGE("Service error %s start service bt ext parameter .", fullServName);
|
||||
free(tmpServName);
|
||||
return NULL;
|
||||
}
|
||||
INIT_LOGI("Service info %s start service bt ext parameter %s.", dstPtr[0], fullServName);
|
||||
service = GetServiceByName(dstPtr[0]);
|
||||
if (service == NULL) {
|
||||
free(tmpServName);
|
||||
return NULL;
|
||||
}
|
||||
service->extraArgs.count = service->pathArgs.count + returnCount - 1;
|
||||
service->extraArgs.argv = (char **)calloc(service->extraArgs.count + 1, sizeof(char *));
|
||||
INIT_ERROR_CHECK(service->extraArgs.argv != NULL, free(tmpServName);
|
||||
extraArgs->count = service->pathArgs.count + returnCount - 1;
|
||||
extraArgs->argv = (char **)calloc(extraArgs->count + 1, sizeof(char *));
|
||||
INIT_ERROR_CHECK(extraArgs->argv != NULL, free(tmpServName);
|
||||
return NULL, "Failed calloc err=%d", errno);
|
||||
int argc;
|
||||
for (argc = 0; argc < (service->pathArgs.count - 1); argc++) {
|
||||
service->extraArgs.argv[argc] = strdup(service->pathArgs.argv[argc]);
|
||||
extraArgs->argv[argc] = strdup(service->pathArgs.argv[argc]);
|
||||
}
|
||||
int extArgc;
|
||||
for (extArgc = 0; extArgc < (returnCount - 1); extArgc++) {
|
||||
service->extraArgs.argv[extArgc + argc] = strdup(dstPtr[extArgc + 1]);
|
||||
extraArgs->argv[extArgc + argc] = strdup(dstPtr[extArgc + 1]);
|
||||
}
|
||||
service->extraArgs.argv[service->extraArgs.count] = NULL;
|
||||
extraArgs->argv[extraArgs->count] = NULL;
|
||||
free(tmpServName);
|
||||
return service;
|
||||
}
|
||||
|
||||
void StartServiceByName(const char *servName)
|
||||
{
|
||||
INIT_LOGI("Start service %s", servName);
|
||||
ServiceArgs extraArgs = { 0 };
|
||||
Service *service = GetServiceByName(servName);
|
||||
if (service == NULL) {
|
||||
service = GetServiceByExtServName(servName);
|
||||
service = GetServiceByExtServName(servName, &extraArgs);
|
||||
}
|
||||
INIT_ERROR_CHECK(service != NULL, return, "Cannot find service %s.", servName);
|
||||
|
||||
if (ServiceStart(service) != SERVICE_SUCCESS) {
|
||||
ServiceArgs *pathArgs = &service->pathArgs;
|
||||
if (extraArgs.count != 0) {
|
||||
pathArgs = &extraArgs;
|
||||
}
|
||||
if (ServiceStart(service, pathArgs) != SERVICE_SUCCESS) {
|
||||
INIT_LOGE("Service %s start failed!", servName);
|
||||
}
|
||||
// After starting, clear the extra parameters.
|
||||
FreeStringVector(service->extraArgs.argv, service->extraArgs.count);
|
||||
service->extraArgs.argv = NULL;
|
||||
service->extraArgs.count = 0;
|
||||
FreeStringVector(extraArgs.argv, extraArgs.count);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -178,7 +178,7 @@ static void ProcessWatchEvent_(const WatcherHandle watcherHandle, int fd, uint32
|
||||
}
|
||||
INIT_LOGI("Socket information detected, fd:%d service name:%s", fd, service->name);
|
||||
RemoveSocketWatcher(watcherHandle);
|
||||
if (ServiceStart(service) != SERVICE_SUCCESS) {
|
||||
if (ServiceStart(service, &service->pathArgs) != SERVICE_SUCCESS) {
|
||||
INIT_LOGE("Service %s start failed!", service->name);
|
||||
}
|
||||
}
|
||||
|
@ -62,11 +62,11 @@ int SetImportantValue(Service *service, const char *attrName, int value, int fla
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
int ServiceExec(const Service *service)
|
||||
int ServiceExec(Service *service, const ServiceArgs *pathArgs)
|
||||
{
|
||||
INIT_ERROR_CHECK(service != NULL && service->pathArgs.count > 0,
|
||||
INIT_ERROR_CHECK(pathArgs != NULL && pathArgs->count > 0,
|
||||
return SERVICE_FAILURE, "Exec service failed! null ptr.");
|
||||
if (execv(service->pathArgs.argv[0], service->pathArgs.argv) != 0) {
|
||||
if (execv(pathArgs->argv[0], pathArgs->argv) != 0) {
|
||||
INIT_LOGE("Service %s execv failed! err=%d.", service->name, errno);
|
||||
return errno;
|
||||
}
|
||||
@ -88,9 +88,9 @@ void IsEnableSandbox(void)
|
||||
return;
|
||||
}
|
||||
|
||||
void SetServiceEnterSandbox(const char *path, unsigned int attribute)
|
||||
int SetServiceEnterSandbox(const Service *service, const char *path)
|
||||
{
|
||||
UNUSED(path);
|
||||
UNUSED(attribute);
|
||||
return;
|
||||
UNUSED(service);
|
||||
return 0;
|
||||
}
|
||||
|
@ -309,7 +309,7 @@ INIT_STATIC void InitPostHook(const HOOK_INFO *hookInfo, void *executionContext,
|
||||
INIT_TIMING_STAT *stat = (INIT_TIMING_STAT *)executionContext;
|
||||
clock_gettime(CLOCK_MONOTONIC, &(stat->endTime));
|
||||
long long diff = InitDiffTime(stat);
|
||||
INIT_LOGI("Executing hook [%d:%d] cost [%lld]us, return %d.",
|
||||
INIT_LOGI("Executing hook [%d:%d] cost [%lld]us, result %d.",
|
||||
hookInfo->stage, hookInfo->prio, diff, executionRetVal);
|
||||
}
|
||||
|
||||
@ -407,7 +407,7 @@ void SystemConfig(void)
|
||||
InitParseGroupCfg();
|
||||
RegisterBootStateChange(BootStateChange);
|
||||
|
||||
INIT_LOGI("boot init finish.");
|
||||
INIT_LOGI("boot stage: init finish.");
|
||||
// load SELinux context and policy
|
||||
// Do not move position!
|
||||
PluginExecCmdByName("loadSelinuxPolicy", "");
|
||||
@ -426,7 +426,7 @@ void SystemConfig(void)
|
||||
HookMgrExecute(GetBootStageHookMgr(), INIT_PRE_CFG_LOAD, (void *)&timingStat, (void *)&options);
|
||||
ReadConfig();
|
||||
RecordInitBootEvent("init.ParseCfg");
|
||||
INIT_LOGI("boot parse config file done.");
|
||||
INIT_LOGI("boot stage: parse config file finish.");
|
||||
HookMgrExecute(GetBootStageHookMgr(), INIT_POST_CFG_LOAD, (void *)&timingStat, (void *)&options);
|
||||
|
||||
IsEnableSandbox();
|
||||
|
@ -61,6 +61,7 @@ static void DumpServiceSocket(const Service *service)
|
||||
printf("\tservice socket info \n");
|
||||
ServiceSocket *sockopt = service->socketCfg;
|
||||
while (sockopt != NULL) {
|
||||
printf("\t\tsocket fd: %d \n", sockopt->sockFd);
|
||||
printf("\t\tsocket name: %s \n", sockopt->name);
|
||||
printf("\t\tsocket type: %u \n", sockopt->type);
|
||||
printf("\t\tsocket uid: %u \n", sockopt->uid);
|
||||
@ -79,6 +80,14 @@ void DumpServiceHookExecute(const char *name, const char *info)
|
||||
|
||||
static void DumpOneService(const Service *service)
|
||||
{
|
||||
static const struct InitErrMap initErrMaps[] = {
|
||||
{INIT_OK, ""},
|
||||
#define XX(code, info) {INIT_ ## code, info},
|
||||
INIT_ERRNO_MAP(XX)
|
||||
#undef XX
|
||||
{INIT_OK, ""}
|
||||
};
|
||||
|
||||
const InitArgInfo startModeMap[] = {
|
||||
{"condition", START_MODE_CONDITION},
|
||||
{"boot", START_MODE_BOOT},
|
||||
@ -92,6 +101,11 @@ static void DumpOneService(const Service *service)
|
||||
|
||||
printf("\tservice name: [%s] \n", service->name);
|
||||
printf("\tservice pid: [%d] \n", service->pid);
|
||||
if (service->lastErrno < sizeof(initErrMaps)) {
|
||||
printf("\tservice last error: %s(%d) \n", initErrMaps[service->lastErrno].info, service->lastErrno);
|
||||
} else {
|
||||
printf("\tservice last error: %d \n", service->lastErrno);
|
||||
}
|
||||
printf("\tservice context : [%s] \n", (service->context.type == INIT_CONTEXT_CHIPSET) ? "chipset" : "system");
|
||||
printf("\tservice crashCnt: [%d] \n", service->crashCnt);
|
||||
printf("\tservice attribute: [%u] \n", service->attribute);
|
||||
@ -192,6 +206,8 @@ static void ProcessDumpServiceControlFd(uint16_t type, const char *serviceCmd)
|
||||
if (strcmp(serviceCmd, "parameter_service") == 0) {
|
||||
if (cmd != NULL && strcmp(cmd, "trigger") == 0) {
|
||||
SystemDumpTriggers(0, printf);
|
||||
} else {
|
||||
SystemDumpParameters(0, 0, printf);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
@ -83,34 +83,29 @@ int SetImportantValue(Service *service, const char *attrName, int value, int fla
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
int ServiceExec(const Service *service)
|
||||
int ServiceExec(Service *service, const ServiceArgs *pathArgs)
|
||||
{
|
||||
INIT_ERROR_CHECK(service != NULL && service->pathArgs.count > 0,
|
||||
INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "Exec service failed! null ptr.");
|
||||
INIT_ERROR_CHECK(pathArgs != NULL && pathArgs->count > 0,
|
||||
return SERVICE_FAILURE, "Exec service failed! null ptr.");
|
||||
|
||||
if (service->importance != 0) {
|
||||
INIT_ERROR_CHECK(setpriority(PRIO_PROCESS, 0, service->importance) == 0, _exit(0x7f),
|
||||
"setpriority failed for %s, importance = %d, err=%d", service->name, service->importance, errno);
|
||||
INIT_ERROR_CHECK(setpriority(PRIO_PROCESS, 0, service->importance) == 0,
|
||||
service->lastErrno = INIT_EPRIORITY;
|
||||
return SERVICE_FAILURE,
|
||||
"Service error %d %s, failed to set priority %d.", errno, service->name, service->importance);
|
||||
}
|
||||
OpenHidebug(service->name);
|
||||
if (service->extraArgs.argv != NULL && service->extraArgs.count > 0) {
|
||||
INIT_CHECK_ONLY_ELOG(execv(service->extraArgs.argv[0], service->extraArgs.argv) == 0,
|
||||
"service %s execv failed! err %d.", service->name, errno);
|
||||
} else {
|
||||
INIT_CHECK_ONLY_ELOG(execv(service->pathArgs.argv[0], service->pathArgs.argv) == 0,
|
||||
"service %s execv failed! err %d.", service->name, errno);
|
||||
}
|
||||
INIT_ERROR_CHECK(execv(pathArgs->argv[0], pathArgs->argv) == 0,
|
||||
service->lastErrno = INIT_EEXEC;
|
||||
return errno, "Service error %d %s, failed to execv.", errno, service->name);
|
||||
return SERVICE_SUCCESS;
|
||||
}
|
||||
|
||||
int SetAccessToken(const Service *service)
|
||||
{
|
||||
INIT_ERROR_CHECK(service != NULL, return SERVICE_FAILURE, "service is null");
|
||||
int ret = SetSelfTokenID(service->tokenId);
|
||||
if (ret != 0) {
|
||||
INIT_LOGV("Set service %s token id %lld failed.", service->name, service->tokenId);
|
||||
return SERVICE_FAILURE;
|
||||
}
|
||||
return SERVICE_SUCCESS;
|
||||
return SetSelfTokenID(service->tokenId);
|
||||
}
|
||||
|
||||
void GetAccessToken(void)
|
||||
@ -156,23 +151,20 @@ void IsEnableSandbox(void)
|
||||
}
|
||||
}
|
||||
|
||||
void SetServiceEnterSandbox(const char *execPath, unsigned int attribute)
|
||||
int SetServiceEnterSandbox(const Service *service, const char *execPath)
|
||||
{
|
||||
if ((service->attribute & SERVICE_ATTR_WITHOUT_SANDBOX) == SERVICE_ATTR_WITHOUT_SANDBOX) {
|
||||
return 0;
|
||||
}
|
||||
if (g_enableSandbox == false) {
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
if ((attribute & SERVICE_ATTR_WITHOUT_SANDBOX) == SERVICE_ATTR_WITHOUT_SANDBOX) {
|
||||
return;
|
||||
}
|
||||
INIT_ERROR_CHECK(execPath != NULL, return, "Service path is null.");
|
||||
INIT_ERROR_CHECK(execPath != NULL, return INIT_EPARAMETER, "Service path is null.");
|
||||
int ret = 0;
|
||||
if (strncmp(execPath, "/system/bin/", strlen("/system/bin/")) == 0) {
|
||||
INIT_INFO_CHECK(EnterSandbox("system") == 0, return,
|
||||
"Service %s skip enter system sandbox.", execPath);
|
||||
ret = EnterSandbox("system");
|
||||
} else if (strncmp(execPath, "/vendor/bin/", strlen("/vendor/bin/")) == 0) {
|
||||
INIT_INFO_CHECK(EnterSandbox("chipset") == 0, return,
|
||||
"Service %s skip enter chipset sandbox.", execPath);
|
||||
} else {
|
||||
INIT_LOGI("Service %s does not enter sandbox", execPath);
|
||||
ret = EnterSandbox("chipset");
|
||||
}
|
||||
return;
|
||||
return ret;
|
||||
}
|
||||
|
@ -26,36 +26,40 @@
|
||||
|
||||
static SignalHandle g_sigHandle = NULL;
|
||||
|
||||
static pid_t HandleSigChild(const struct signalfd_siginfo *siginfo)
|
||||
{
|
||||
int procStat = 0;
|
||||
pid_t sigPID = waitpid(-1, &procStat, WNOHANG);
|
||||
if (sigPID <= 0) {
|
||||
return sigPID;
|
||||
}
|
||||
Service* service = GetServiceByPid(sigPID);
|
||||
const char *serviceName = (service == NULL) ? "Unknown" : service->name;
|
||||
|
||||
// check child process exit status
|
||||
if (WIFSIGNALED(procStat)) {
|
||||
INIT_LOGE("Child process %s(pid %d) exit with signal : %d", serviceName, sigPID, WTERMSIG(procStat));
|
||||
} else if (WIFEXITED(procStat)) {
|
||||
INIT_LOGE("Child process %s(pid %d) exit with code : %d", serviceName, sigPID, WEXITSTATUS(procStat));
|
||||
if (service != NULL) {
|
||||
service->lastErrno = WEXITSTATUS(procStat);
|
||||
}
|
||||
}
|
||||
CmdServiceProcessDelClient(sigPID);
|
||||
StopSubInit(sigPID);
|
||||
INIT_LOGW("Service warning %s, SIGCHLD received, pid:%d uid:%d status:%d.",
|
||||
serviceName, sigPID, siginfo->ssi_uid, procStat);
|
||||
CheckWaitPid(sigPID);
|
||||
ServiceReap(service);
|
||||
return sigPID;
|
||||
}
|
||||
|
||||
INIT_STATIC void ProcessSignal(const struct signalfd_siginfo *siginfo)
|
||||
{
|
||||
switch (siginfo->ssi_signo) {
|
||||
case SIGCHLD: {
|
||||
pid_t sigPID;
|
||||
int procStat = 0;
|
||||
while (1) {
|
||||
sigPID = waitpid(-1, &procStat, WNOHANG);
|
||||
if (sigPID <= 0) {
|
||||
break;
|
||||
}
|
||||
Service* service = GetServiceByPid(sigPID);
|
||||
// check child process exit status
|
||||
if (WIFSIGNALED(procStat)) {
|
||||
INIT_LOGE("Child process %s(pid %d) exit with signal : %d",
|
||||
service == NULL ? "Unknown" : service->name, sigPID, WTERMSIG(procStat));
|
||||
} else if (WIFEXITED(procStat)) {
|
||||
INIT_LOGE("Child process %s(pid %d) exit with code : %d",
|
||||
service == NULL ? "Unknown" : service->name, sigPID, WEXITSTATUS(procStat));
|
||||
} else {
|
||||
INIT_LOGE("Child process %s(pid %d) exit with invalid status : %d",
|
||||
service == NULL ? "Unknown" : service->name, sigPID, procStat);
|
||||
}
|
||||
CmdServiceProcessDelClient(sigPID);
|
||||
StopSubInit(sigPID);
|
||||
INIT_LOGI("SigHandler, SIGCHLD received, Service:%s pid:%d uid:%d status:%d.",
|
||||
service == NULL ? "Unknown" : service->name,
|
||||
sigPID, siginfo->ssi_uid, procStat);
|
||||
CheckWaitPid(sigPID);
|
||||
ServiceReap(service);
|
||||
while (HandleSigChild(siginfo) > 0) {
|
||||
;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -21,6 +21,7 @@ ohos_shared_library("selinuxadp") {
|
||||
".",
|
||||
"..",
|
||||
"../init_hook",
|
||||
"//base/startup/init/services/include",
|
||||
"//base/startup/init/services/include/param",
|
||||
"//third_party/selinux/libselinux/include/",
|
||||
"//base/security/selinux_adapter/interfaces/policycoreutils/include/",
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "init_error.h"
|
||||
#include "init_hook.h"
|
||||
#include "init_module_engine.h"
|
||||
#include "plugin_adapter.h"
|
||||
@ -64,20 +65,21 @@ static int SetServiceContent(int id, const char *name, int argc, const char **ar
|
||||
{
|
||||
PLUGIN_CHECK(name != NULL && argc >= 1 && argv != NULL, return -1, "Invalid parameter");
|
||||
ServiceExtData *data = GetServiceExtData(argv[0], HOOK_ID_SELINUX);
|
||||
char *label = "u:r:limit_domain:s0";
|
||||
if (data != NULL) {
|
||||
if (setexeccon((char *)data->data) < 0) {
|
||||
PLUGIN_LOGE("failed to set service %s's secon (%s).", argv[0], (char *)data->data);
|
||||
#ifndef STARTUP_INIT_TEST
|
||||
_exit(PROCESS_EXIT_CODE);
|
||||
#endif
|
||||
} else {
|
||||
PLUGIN_LOGV("Set content %s to %s.", (char *)data->data, argv[0]);
|
||||
}
|
||||
label = (char *)data->data;
|
||||
} else {
|
||||
PLUGIN_CHECK(!(setexeccon("u:r:limit_domain:s0") < 0), _exit(PROCESS_EXIT_CODE),
|
||||
"failed to set service %s's secon (%s).", argv[0], "u:r:limit_domain:s0");
|
||||
PLUGIN_LOGE("Please set secon field in service %s's cfg file, limit_domain will be blocked", argv[0]);
|
||||
}
|
||||
|
||||
if (setexeccon(label) < 0) {
|
||||
PLUGIN_LOGE("Service error %d %s, failed to set secon %s.", errno, argv[0], label);
|
||||
#ifndef STARTUP_INIT_TEST
|
||||
_exit(INIT_EEXEC_CONTENT);
|
||||
#endif
|
||||
} else {
|
||||
PLUGIN_LOGV("Service info %s, set secon %s.", argv[0], label);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "param_utils.h"
|
||||
#include "param_base.h"
|
||||
|
||||
#define MAX_MEMBER_IN_GROUP 128
|
||||
#define MAX_BUF_SIZE 1024
|
||||
#define INVALID_MODE 0550
|
||||
#ifdef STARTUP_INIT_TEST
|
||||
@ -124,30 +125,76 @@ static int FreeLocalSecurityLabel(ParamSecurityLabel *srcLabel)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DacGetGroupMember(gid_t gid, uid_t *member, uint32_t *memberSize)
|
||||
{
|
||||
uint32_t inputLen = *memberSize;
|
||||
*memberSize = 0;
|
||||
struct group *data = getgrgid(gid);
|
||||
if (data == NULL || data->gr_mem == NULL) {
|
||||
return 0;
|
||||
}
|
||||
int i = 0;
|
||||
int memIndex = 0;
|
||||
while (data->gr_mem[i]) {
|
||||
uid_t uid;
|
||||
GetUserIdByName(&uid, data->gr_mem[i]);
|
||||
if (INVALID_UID(uid)) {
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
if ((memIndex + 1) > inputLen) {
|
||||
PARAM_LOGE("Not enough memory for uid member %u", gid);
|
||||
break;
|
||||
}
|
||||
member[memIndex++] = uid;
|
||||
i++;
|
||||
}
|
||||
uid_t uid = 0;
|
||||
GetUserIdByName(&uid, data->gr_name);
|
||||
if (!INVALID_UID(uid) && ((memIndex + 1) < inputLen)) {
|
||||
member[memIndex++] = uid;
|
||||
}
|
||||
*memberSize = memIndex;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int LoadOneParam_(const uint32_t *context, const char *name, const char *value)
|
||||
{
|
||||
ParamAuditData auditData = {0};
|
||||
auditData.dacData.gid = -1;
|
||||
auditData.dacData.uid = -1;
|
||||
auditData.name = name;
|
||||
int ret = GetParamDacData(&auditData.dacData, value);
|
||||
ParamAuditData *auditData = (ParamAuditData *)context;
|
||||
auditData->dacData.gid = -1;
|
||||
auditData->dacData.uid = -1;
|
||||
auditData->name = name;
|
||||
int ret = GetParamDacData(&auditData->dacData, value);
|
||||
PARAM_CHECK(ret == 0, return -1, "Failed to get param info %d %s", ret, name);
|
||||
if (INVALID_UID(auditData.dacData.gid) || INVALID_UID(auditData.dacData.uid)) {
|
||||
PARAM_LOGW("Invalid dac for '%s' gid %d uid %d", name, auditData.dacData.gid, auditData.dacData.uid);
|
||||
if (INVALID_UID(auditData->dacData.gid) || INVALID_UID(auditData->dacData.uid)) {
|
||||
PARAM_LOGW("Invalid dac for '%s' gid %d uid %d", name, auditData->dacData.gid, auditData->dacData.uid);
|
||||
}
|
||||
AddSecurityLabel(&auditData);
|
||||
// get uid from group
|
||||
auditData->memberNum = MAX_MEMBER_IN_GROUP;
|
||||
ret = DacGetGroupMember(auditData->dacData.gid, auditData->members, &auditData->memberNum);
|
||||
if (ret != 0) {
|
||||
auditData->memberNum = 1;
|
||||
auditData->members[0] = auditData->dacData.gid;
|
||||
}
|
||||
AddSecurityLabel(auditData);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int LoadParamLabels(const char *fileName)
|
||||
{
|
||||
ParamAuditData *auditData = (ParamAuditData *)calloc(1,
|
||||
sizeof(ParamAuditData) + sizeof(uid_t) * MAX_MEMBER_IN_GROUP);
|
||||
if (auditData == NULL) {
|
||||
PARAM_LOGE("Failed to alloc memory %s", fileName);
|
||||
return 0;
|
||||
}
|
||||
uint32_t infoCount = 0;
|
||||
FILE *fp = fopen(fileName, "r");
|
||||
const uint32_t buffSize = PARAM_NAME_LEN_MAX + PARAM_CONST_VALUE_LEN_MAX + 10; // 10 size
|
||||
char *buff = (char *)calloc(1, buffSize);
|
||||
while (fp != NULL && buff != NULL && fgets(buff, buffSize, fp) != NULL) {
|
||||
buff[buffSize - 1] = '\0';
|
||||
int ret = SplitParamString(buff, NULL, 0, LoadOneParam_, NULL);
|
||||
int ret = SplitParamString(buff, NULL, 0, LoadOneParam_, (const uint32_t *)auditData);
|
||||
if (ret != 0) {
|
||||
PARAM_LOGE("Failed to split string %s fileName %s", buff, fileName);
|
||||
continue;
|
||||
@ -161,6 +208,9 @@ static int LoadParamLabels(const char *fileName)
|
||||
if (buff != NULL) {
|
||||
free(buff);
|
||||
}
|
||||
if (auditData != NULL) {
|
||||
free(auditData);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -237,127 +287,3 @@ INIT_LOCAL_API int RegisterSecurityDacOps(ParamSecurityOps *ops, int isInit)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void AddGroupUser(const char *userName, gid_t gid)
|
||||
{
|
||||
if (userName == NULL || strlen(userName) == 0) {
|
||||
return;
|
||||
}
|
||||
uid_t uid = 0;
|
||||
GetUserIdByName(&uid, userName);
|
||||
PARAM_LOGV("Add group user '%s' gid %d uid %d", userName, gid, uid);
|
||||
if (INVALID_UID(gid) || INVALID_UID(uid)) {
|
||||
PARAM_LOGW("Invalid user for '%s' gid %d uid %d", userName, gid, uid);
|
||||
return;
|
||||
}
|
||||
char buffer[USER_BUFFER_LEN] = {0};
|
||||
int ret = PARAM_SPRINTF(buffer, sizeof(buffer), GROUP_FORMAT, gid, uid);
|
||||
PARAM_CHECK(ret >= 0, return, "Failed to format name for %d.%d", gid, uid);
|
||||
(void)AddParamEntry(WORKSPACE_INDEX_BASE, PARAM_TYPE_STRING, buffer, "1");
|
||||
}
|
||||
|
||||
#ifdef PARAM_DECODE_GROUPID_FROM_FILE
|
||||
static char *UserNameTrim(char *str)
|
||||
{
|
||||
if (str == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
size_t len = strlen(str);
|
||||
if (str == NULL || len == 0) {
|
||||
return NULL;
|
||||
}
|
||||
char *end = str + len - 1;
|
||||
while (end >= str && (*end == ' ' || *end == '\t' || *end == '\n' || *end == '\r')) {
|
||||
*end = '\0';
|
||||
end--;
|
||||
}
|
||||
len = strlen(str);
|
||||
char *head = str;
|
||||
end = str + strlen(str);
|
||||
while (head < end && (*head == ' ' || *head == '\t' || *head == '\n' || *head == '\r')) {
|
||||
*head = '\0';
|
||||
head++;
|
||||
}
|
||||
if (strlen(str) == 0) {
|
||||
return NULL;
|
||||
}
|
||||
return head;
|
||||
}
|
||||
|
||||
static void LoadGroupUser_(void)
|
||||
{
|
||||
// decode group file
|
||||
FILE *fp = fopen(GROUP_FILE_PATH, "r");
|
||||
const uint32_t buffSize = 1024; // 1024 max buffer for decode
|
||||
char *buff = (char *)calloc(1, buffSize);
|
||||
while (fp != NULL && buff != NULL && fgets(buff, buffSize, fp) != NULL) {
|
||||
buff[buffSize - 1] = '\0';
|
||||
// deviceprivate:x:1053:root,shell,system,samgr,hdf_devmgr,deviceinfo,dsoftbus,dms,account
|
||||
char *buffer = UserNameTrim(buff);
|
||||
PARAM_CHECK(buffer != NULL, continue, "Invalid buffer %s", buff);
|
||||
|
||||
PARAM_LOGV("LoadGroupUser_ '%s'", buffer);
|
||||
// group name
|
||||
char *groupName = strtok(buffer, ":");
|
||||
groupName = UserNameTrim(groupName);
|
||||
PARAM_CHECK(groupName != NULL, continue, "Invalid group name %s", buff);
|
||||
gid_t gid = -1;
|
||||
GetGroupIdByName(&gid, groupName);
|
||||
|
||||
// skip x
|
||||
(void)strtok(NULL, ":");
|
||||
char *strGid = strtok(NULL, ":");
|
||||
char *userName = strGid + strlen(strGid) + 1;
|
||||
userName = UserNameTrim(userName);
|
||||
PARAM_LOGV("LoadGroupUser_ %s userName '%s'", groupName, userName);
|
||||
if (userName == NULL) {
|
||||
AddGroupUser(groupName, gid);
|
||||
continue;
|
||||
}
|
||||
char *tmp = strtok(userName, ",");
|
||||
while (tmp != NULL) {
|
||||
PARAM_LOGV("LoadGroupUser_ %s userName '%s'", groupName, tmp);
|
||||
AddGroupUser(UserNameTrim(tmp), gid);
|
||||
userName = tmp + strlen(tmp) + 1;
|
||||
tmp = strtok(NULL, ",");
|
||||
}
|
||||
// last username
|
||||
if (userName != NULL) {
|
||||
AddGroupUser(UserNameTrim(userName), gid);
|
||||
}
|
||||
}
|
||||
if (fp != NULL) {
|
||||
(void)fclose(fp);
|
||||
}
|
||||
if (buff != NULL) {
|
||||
free(buff);
|
||||
}
|
||||
return;
|
||||
}
|
||||
#else
|
||||
static void LoadGroupUser_(void)
|
||||
{
|
||||
struct group *data = NULL;
|
||||
while ((data = getgrent()) != NULL) {
|
||||
if (data->gr_name == NULL || data->gr_mem == NULL) {
|
||||
continue;
|
||||
}
|
||||
if (data->gr_mem[0] == NULL) { // default user in group
|
||||
AddGroupUser(data->gr_name, data->gr_gid);
|
||||
continue;
|
||||
}
|
||||
int index = 0;
|
||||
while (data->gr_mem[index]) { // user in this group
|
||||
AddGroupUser(data->gr_mem[index], data->gr_gid);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
endgrent();
|
||||
}
|
||||
#endif
|
||||
|
||||
INIT_LOCAL_API void LoadGroupUser(void)
|
||||
{
|
||||
PARAM_LOGV("LoadGroupUser ");
|
||||
LoadGroupUser_();
|
||||
}
|
||||
|
@ -208,6 +208,8 @@ static void HandleSelinuxLabelForPermission(const ParameterNode *paramNode, int
|
||||
auditData.dacData.paramType = node->type;
|
||||
auditData.selinuxIndex = labelIndex;
|
||||
auditData.name = paramNode->paraName;
|
||||
auditData.memberNum = 1;
|
||||
auditData.members[0] = node->gid;
|
||||
AddSecurityLabel(&auditData);
|
||||
}
|
||||
|
||||
|
@ -175,6 +175,8 @@ static int CreateWorkSpace(int onlyRead)
|
||||
#else
|
||||
ret = AddWorkSpace(WORKSPACE_NAME_NORMAL, WORKSPACE_INDEX_DAC, onlyRead, PARAM_WORKSPACE_MAX);
|
||||
PARAM_CHECK(ret == 0, return -1, "Failed to add dac workspace");
|
||||
ret = OpenWorkSpace(WORKSPACE_INDEX_DAC, onlyRead);
|
||||
PARAM_CHECK(ret == 0, return -1, "Failed to open dac workspace");
|
||||
paramSpace->maxLabelIndex = 1;
|
||||
#endif
|
||||
return ret;
|
||||
@ -182,9 +184,8 @@ static int CreateWorkSpace(int onlyRead)
|
||||
|
||||
INIT_INNER_API int InitParamWorkSpace(int onlyRead, const PARAM_WORKSPACE_OPS *ops)
|
||||
{
|
||||
if (CheckNeedInit(onlyRead, ops) == 0) {
|
||||
return 0;
|
||||
}
|
||||
PARAM_ONLY_CHECK(CheckNeedInit(onlyRead, ops) != 0, return 0);
|
||||
|
||||
paramMutexEnvInit();
|
||||
if (!PARAM_TEST_FLAG(g_paramWorkSpace.flags, WORKSPACE_FLAGS_INIT)) {
|
||||
g_paramWorkSpace.maxSpaceCount = PARAM_DEF_SELINUX_LABEL;
|
||||
@ -205,8 +206,6 @@ INIT_INNER_API int InitParamWorkSpace(int onlyRead, const PARAM_WORKSPACE_OPS *o
|
||||
ret = AllocSpaceMemory(g_paramWorkSpace.maxLabelIndex);
|
||||
PARAM_CHECK(ret == 0, return -1, "Failed to alloc space size");
|
||||
|
||||
// load user info for dac
|
||||
LoadGroupUser();
|
||||
// add default dac policy
|
||||
ParamAuditData auditData = {0};
|
||||
auditData.name = "#";
|
||||
@ -214,6 +213,8 @@ INIT_INNER_API int InitParamWorkSpace(int onlyRead, const PARAM_WORKSPACE_OPS *o
|
||||
auditData.dacData.uid = DAC_DEFAULT_USER;
|
||||
auditData.dacData.mode = DAC_DEFAULT_MODE; // 0774 default mode
|
||||
auditData.dacData.paramType = PARAM_TYPE_STRING;
|
||||
auditData.memberNum = 1;
|
||||
auditData.members[0] = DAC_DEFAULT_GROUP;
|
||||
#ifdef PARAM_SUPPORT_SELINUX
|
||||
auditData.selinuxIndex = INVALID_SELINUX_INDEX;
|
||||
#endif
|
||||
@ -337,12 +338,9 @@ STATIC_INLINE int CheckAndExtendSpace(ParamWorkSpace *paramSpace, const char *na
|
||||
INIT_LOCAL_API int OpenWorkSpace(uint32_t index, int readOnly)
|
||||
{
|
||||
ParamWorkSpace *paramSpace = GetParamWorkSpace();
|
||||
PARAM_CHECK(paramSpace != NULL && paramSpace->workSpace != NULL,
|
||||
return -1, "Invalid workspace index %u", index);
|
||||
PARAM_CHECK(paramSpace != NULL && paramSpace->workSpace != NULL, return -1, "Invalid workspace index %u", index);
|
||||
WorkSpace *workSpace = NULL;
|
||||
if (index < paramSpace->maxSpaceCount) {
|
||||
workSpace = paramSpace->workSpace[index];
|
||||
}
|
||||
PARAM_ONLY_CHECK(index >= paramSpace->maxSpaceCount, workSpace = paramSpace->workSpace[index]);
|
||||
PARAM_CHECK(workSpace != NULL, return 0, "Invalid index %d", index);
|
||||
int ret = 0;
|
||||
uint32_t rwSpaceLock = 0;
|
||||
@ -359,8 +357,7 @@ INIT_LOCAL_API int OpenWorkSpace(uint32_t index, int readOnly)
|
||||
|
||||
ATOMIC_STORE_EXPLICIT(&workSpace->rwSpaceLock, rwSpaceLock | WORKSPACE_STATUS_IN_PROCESS, MEMORY_ORDER_RELEASE);
|
||||
if (workSpace->area == NULL) {
|
||||
PARAM_LOGI("OpenWorkSpace %s index %d spaceSize: %u onlyRead %s",
|
||||
workSpace->fileName, workSpace->spaceIndex,
|
||||
PARAM_LOGI("OpenWorkSpace %s index %d spaceSize: %u onlyRead %s", workSpace->fileName, workSpace->spaceIndex,
|
||||
workSpace->spaceSize, readOnly ? "true" : "false");
|
||||
ret = InitWorkSpace(workSpace, readOnly, workSpace->spaceSize);
|
||||
if (ret != 0) {
|
||||
@ -413,14 +410,12 @@ STATIC_INLINE int ReadParamWithCheck(WorkSpace **workspace, const char *name, ui
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int CheckUserInGroup(WorkSpace *space, gid_t groupId, uid_t uid)
|
||||
static int CheckUserInGroup(WorkSpace *space, const ParamSecurityNode *node, uid_t uid)
|
||||
{
|
||||
char buffer[USER_BUFFER_LEN] = {0};
|
||||
int ret = PARAM_SPRINTF(buffer, sizeof(buffer), GROUP_FORMAT, groupId, uid);
|
||||
PARAM_CHECK(ret >= 0, return -1, "Failed to format name for "GROUP_FORMAT, groupId, uid);
|
||||
ParamNode *node = GetParamNode(WORKSPACE_INDEX_BASE, buffer);
|
||||
if (node != NULL) {
|
||||
return 0;
|
||||
for (uint32_t i = 0; i < node->memberNum; i++) {
|
||||
if (node->members[i] == uid) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@ -485,7 +480,7 @@ STATIC_INLINE int DacCheckParamPermission(const ParamLabelIndex *labelIndex,
|
||||
return DAC_RESULT_PERMISSION;
|
||||
}
|
||||
// 4, check user in group
|
||||
if (CheckUserInGroup(space, node->gid, srcLabel->cred.uid) == 0) {
|
||||
if (CheckUserInGroup(space, node, srcLabel->cred.uid) == 0) {
|
||||
localMode = (mode & (DAC_READ | DAC_WRITE | DAC_WATCH)) >> DAC_GROUP_START;
|
||||
if ((node->mode & localMode) != 0) {
|
||||
return DAC_RESULT_PERMISSION;
|
||||
|
@ -238,7 +238,7 @@ INIT_LOCAL_API uint32_t AddParamSecurityNode(WorkSpace *workSpace, const ParamAu
|
||||
{
|
||||
PARAM_CHECK(CheckWorkSpace(workSpace) == 0, return 0, "Invalid workSpace");
|
||||
PARAM_CHECK(auditData != NULL, return 0, "Invalid auditData");
|
||||
uint32_t realLen = sizeof(ParamSecurityNode);
|
||||
uint32_t realLen = sizeof(ParamSecurityNode) + sizeof(uid_t) * auditData->memberNum;
|
||||
PARAM_CHECK((workSpace->area->currOffset + realLen) < workSpace->area->dataSize, return 0,
|
||||
"Failed to allocate currOffset %u, dataSize %u datalen %u",
|
||||
workSpace->area->currOffset, workSpace->area->dataSize, realLen);
|
||||
@ -252,6 +252,13 @@ INIT_LOCAL_API uint32_t AddParamSecurityNode(WorkSpace *workSpace, const ParamAu
|
||||
#else
|
||||
node->selinuxIndex = 0;
|
||||
#endif
|
||||
if (auditData->memberNum > 0) {
|
||||
// copy member
|
||||
int ret = PARAM_MEMCPY(node->members,
|
||||
realLen - sizeof(ParamSecurityNode), auditData->members, auditData->memberNum * sizeof(uid_t));
|
||||
PARAM_CHECK(ret == 0, return 0, "Failed to copy members");
|
||||
}
|
||||
node->memberNum = auditData->memberNum;
|
||||
uint32_t offset = workSpace->area->currOffset;
|
||||
workSpace->area->currOffset += realLen;
|
||||
workSpace->area->securityNodeCount++;
|
||||
|
@ -87,6 +87,8 @@ typedef struct {
|
||||
uint16_t mode;
|
||||
uint8_t type;
|
||||
uint8_t length;
|
||||
uint32_t memberNum;
|
||||
uid_t members[0];
|
||||
} ParamSecurityNode;
|
||||
|
||||
typedef struct {
|
||||
@ -134,7 +136,7 @@ typedef struct CachedParameter_ {
|
||||
|
||||
typedef void *CachedHandle;
|
||||
|
||||
typedef struct _SpaceSize{
|
||||
typedef struct _SpaceSize {
|
||||
uint32_t maxLabelIndex;
|
||||
uint32_t spaceSize[0];
|
||||
} WorkSpaceSize;
|
||||
|
@ -88,6 +88,8 @@ typedef struct {
|
||||
char label[SELINUX_CONTENT_LEN];
|
||||
uint32_t selinuxIndex;
|
||||
#endif
|
||||
uint32_t memberNum;
|
||||
uid_t members[1];
|
||||
} ParamAuditData;
|
||||
|
||||
struct WorkSpace_;
|
||||
@ -127,7 +129,6 @@ INIT_LOCAL_API int RegisterSecuritySelinuxOps(ParamSecurityOps *ops, int isInit)
|
||||
#endif
|
||||
|
||||
INIT_LOCAL_API ParamSecurityOps *GetParamSecurityOps(int type);
|
||||
INIT_LOCAL_API void LoadGroupUser(void);
|
||||
INIT_LOCAL_API int RegisterSecurityDacOps(ParamSecurityOps *ops, int isInit);
|
||||
INIT_LOCAL_API int RegisterSecurityOps(int onlyRead);
|
||||
|
||||
|
@ -63,9 +63,9 @@ STATIC_INLINE ParamTrieNode *FindTrieNode_(
|
||||
#endif
|
||||
|
||||
#define GetWorkSpaceSize(workSpace) \
|
||||
(workSpace == NULL || workSpace->area == NULL || \
|
||||
workSpace->area->spaceSizeOffset == 0 || \
|
||||
workSpace->area->spaceSizeOffset >= workSpace->area->dataSize) ? NULL : \
|
||||
((workSpace == NULL) || (workSpace->area == NULL) || \
|
||||
(workSpace->area->spaceSizeOffset == 0) || \
|
||||
(workSpace->area->spaceSizeOffset >= workSpace->area->dataSize)) ? NULL : \
|
||||
(WorkSpaceSize*)(workSpace->area->data + workSpace->area->spaceSizeOffset)
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -95,7 +95,7 @@ int ParamEventSend(const ParamTaskPtr stream, uint64_t eventId, const char *cont
|
||||
void *ParamGetTaskUserData(const ParamTaskPtr stream);
|
||||
|
||||
int FillParamMsgContent(const ParamMessage *request, uint32_t *start, int type, const char *value, uint32_t length);
|
||||
ParamMsgContent *GetNextContent(const ParamMessage *reqest, uint32_t *offset);
|
||||
ParamMsgContent *GetNextContent(const ParamMessage *request, uint32_t *offset);
|
||||
ParamMessage *CreateParamMessage(int type, const char *name, uint32_t msgSize);
|
||||
|
||||
int ConnectServer(int fd, const char *servername);
|
||||
|
@ -81,7 +81,3 @@ INIT_LOCAL_API int RegisterSecurityDacOps(ParamSecurityOps *ops, int isInit)
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
INIT_LOCAL_API void LoadGroupUser(void)
|
||||
{
|
||||
}
|
||||
|
@ -141,12 +141,20 @@ static int DumpTrieDataNodeTraversal(const WorkSpace *workSpace, const ParamTrie
|
||||
entry->commitId, entry->keyLength, entry->valueLength, entry->data);
|
||||
}
|
||||
}
|
||||
if (current->labelIndex != 0 && verbose) {
|
||||
ParamSecurityNode *label = (ParamSecurityNode *)GetTrieNode(workSpace, current->labelIndex);
|
||||
if (label != NULL) {
|
||||
PARAM_DUMP("\tparameter label dac %u %u %o selinuxIndex %u \n",
|
||||
label->uid, label->gid, label->mode, label->selinuxIndex);
|
||||
}
|
||||
if (current->labelIndex == 0) {
|
||||
return 0;
|
||||
}
|
||||
ParamSecurityNode *label = (ParamSecurityNode *)GetTrieNode(workSpace, current->labelIndex);
|
||||
if (label == NULL) {
|
||||
return 0;
|
||||
}
|
||||
PARAM_DUMP("\tparameter label dac %u %u 0%o \n", label->uid, label->gid, label->mode);
|
||||
PARAM_DUMP("\tparameter label dac member [%u] ", label->memberNum);
|
||||
for (uint32_t i = 0; i < label->memberNum; i++) {
|
||||
PARAM_DUMP(" %u", label->members[i]);
|
||||
}
|
||||
if (label->memberNum > 0) {
|
||||
PARAM_DUMP("\n");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
@ -351,7 +351,7 @@ static int LoadOneParamAreaSize_(const uint32_t *context, const char *name, cons
|
||||
WorkSpaceSize *spaceSize = GetWorkSpaceSize(GetWorkSpace(WORKSPACE_INDEX_SIZE));
|
||||
PARAM_CHECK(spaceSize != NULL, return PARAM_CODE_ERROR, "Failed to get workspace size");
|
||||
static char buffer[SELINUX_CONTENT_LEN] = {0};
|
||||
int ret = snprintf(buffer, sizeof(buffer) - 1, "u:object_r:%s:s0", name);
|
||||
int ret = snprintf_s(buffer, sizeof(buffer), sizeof(buffer) - 1, "u:object_r:%s:s0", name);
|
||||
PARAM_CHECK(ret > 0, return PARAM_CODE_ERROR, "Failed to snprintf workspace name");
|
||||
|
||||
for (uint32_t i = WORKSPACE_INDEX_BASE + 1; i < spaceSize->maxLabelIndex; i++) {
|
||||
|
@ -78,13 +78,11 @@ uid_t DecodeUid(const char *name)
|
||||
if (!StringToUint(name, &uid)) {
|
||||
return uid;
|
||||
} else {
|
||||
INIT_LOGE("Failed to decode uid for %s", name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
struct passwd *p = getpwnam(name);
|
||||
if (p == NULL) {
|
||||
INIT_LOGE("Failed to decode uid for %s", name);
|
||||
return -1;
|
||||
}
|
||||
return p->pw_uid;
|
||||
@ -103,7 +101,6 @@ gid_t DecodeGid(const char *name)
|
||||
if (!StringToUint(name, &gid)) {
|
||||
return gid;
|
||||
} else {
|
||||
INIT_LOGE("Failed to decode gid for %s", name);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -134,7 +131,6 @@ char *ReadFileToBuf(const char *configFile)
|
||||
do {
|
||||
if (stat(configFile, &fileStat) != 0 ||
|
||||
fileStat.st_size <= 0 || fileStat.st_size > MAX_JSON_FILE_LEN) {
|
||||
INIT_LOGE("Unexpected config file \" %s \", check if it exist. if exist, check file size", configFile);
|
||||
break;
|
||||
}
|
||||
fd = fopen(configFile, "r");
|
||||
@ -496,7 +492,6 @@ int CheckAndCreatFile(const char *file, mode_t mode)
|
||||
BEGET_LOGE("Failed create %s, err=%d", file, errno);
|
||||
return -1;
|
||||
} else {
|
||||
BEGET_LOGI("Success create %s", file);
|
||||
close(fd);
|
||||
}
|
||||
} else {
|
||||
@ -588,17 +583,17 @@ int StringReplaceChr(char *strl, char oldChr, char newChr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void RedirectStdio(int fd)
|
||||
{
|
||||
#ifndef __LITEOS_M__
|
||||
static void RedirectStdio(int fd)
|
||||
{
|
||||
const int stdError = 2;
|
||||
dup2(fd, 0);
|
||||
dup2(fd, 1);
|
||||
dup2(fd, stdError); // Redirect fd to 0, 1, 2
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void OpenConsole(void)
|
||||
int OpenConsole(void)
|
||||
{
|
||||
#ifndef __LITEOS_M__
|
||||
setsid();
|
||||
@ -609,9 +604,11 @@ void OpenConsole(void)
|
||||
RedirectStdio(fd);
|
||||
close(fd);
|
||||
} else {
|
||||
INIT_LOGE("Open /dev/console failed. err = %d", errno);
|
||||
return errno;
|
||||
}
|
||||
return;
|
||||
return 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,9 @@
|
||||
#include <sys/statvfs.h>
|
||||
|
||||
#include "init_file.h"
|
||||
#include "init_service.h"
|
||||
#include "init_service_file.h"
|
||||
#include "init_service_manager.h"
|
||||
#include "param_stub.h"
|
||||
#include "securec.h"
|
||||
|
||||
@ -46,27 +48,22 @@ HWTEST_F(ServiceFileUnitTest, TestServiceFile, TestSize.Level1)
|
||||
fileOpt->gid = 1000;
|
||||
fileOpt->fd = -1;
|
||||
fileOpt->perm = 0770;
|
||||
if (strncpy_s(fileOpt->fileName, strlen(fileName) + 1, fileName, strlen(fileName)) != 0) {
|
||||
free(fileOpt);
|
||||
fileOpt = nullptr;
|
||||
FAIL();
|
||||
}
|
||||
CreateServiceFile(fileOpt);
|
||||
int ret = GetControlFile("/data/filetest");
|
||||
int ret = strncpy_s(fileOpt->fileName, strlen(fileName) + 1, fileName, strlen(fileName));
|
||||
EXPECT_EQ(ret, 0);
|
||||
Service *service = AddService("test_service8");
|
||||
ASSERT_NE(nullptr, service);
|
||||
|
||||
service->fileCfg = fileOpt;
|
||||
CreateServiceFile(service);
|
||||
ret = GetControlFile("/data/filetest");
|
||||
EXPECT_NE(ret, -1);
|
||||
if (strncpy_s(fileOpt->fileName, strlen(fileName) + 1, "fileName", strlen("fileName")) != 0) {
|
||||
free(fileOpt);
|
||||
fileOpt = nullptr;
|
||||
FAIL();
|
||||
}
|
||||
ret = strncpy_s(fileOpt->fileName, strlen(fileName) + 1, "fileName", strlen("fileName"));
|
||||
EXPECT_EQ(ret, 0);
|
||||
fileOpt->fd = 100; // 100 is fd
|
||||
CreateServiceFile(fileOpt);
|
||||
CreateServiceFile(service);
|
||||
CloseServiceFile(fileOpt);
|
||||
if (strncpy_s(fileOpt->fileName, strlen(fileName) + 1, "/dev/filetest", strlen("/dev/filetest")) != 0) {
|
||||
free(fileOpt);
|
||||
fileOpt = nullptr;
|
||||
FAIL();
|
||||
}
|
||||
ret = strncpy_s(fileOpt->fileName, strlen(fileName) + 1, "/dev/filetest", strlen("/dev/filetest"));
|
||||
EXPECT_EQ(ret, 0);
|
||||
char *wrongName = (char *)malloc(PATH_MAX);
|
||||
ASSERT_NE(wrongName, nullptr);
|
||||
EXPECT_EQ(memset_s(wrongName, PATH_MAX, 1, PATH_MAX), 0);
|
||||
@ -78,13 +75,13 @@ HWTEST_F(ServiceFileUnitTest, TestServiceFile, TestSize.Level1)
|
||||
GetControlFile("testPath");
|
||||
EXPECT_EQ(setenv("OHOS_FILE_ENV_PREFIX_testPath1", "aaaaaaaa", 0), 0);
|
||||
GetControlFile("testPath1");
|
||||
free(wrongName);
|
||||
|
||||
fileOpt->fd = -1;
|
||||
CreateServiceFile(fileOpt);
|
||||
CreateServiceFile(service);
|
||||
CloseServiceFile(fileOpt);
|
||||
free(fileOpt);
|
||||
free(wrongName);
|
||||
fileOpt = nullptr;
|
||||
wrongName = nullptr;
|
||||
service->fileCfg = nullptr;
|
||||
ReleaseService(service);
|
||||
}
|
||||
}
|
||||
|
@ -71,7 +71,7 @@ HWTEST_F(ServiceUnitTest, case01, TestSize.Level1)
|
||||
int ret = ParseOneService(serviceItem, service);
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
ret = ServiceStart(service);
|
||||
ret = ServiceStart(service, &service->pathArgs);
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
ret = ServiceStop(service);
|
||||
@ -98,7 +98,7 @@ HWTEST_F(ServiceUnitTest, case02, TestSize.Level1)
|
||||
int fds[1] = {-1}; // ServiceStop will release fds
|
||||
UpdaterServiceFds(service, fds, 1);
|
||||
service->attribute = SERVICE_ATTR_ONDEMAND;
|
||||
ret = ServiceStart(service);
|
||||
ret = ServiceStart(service, &service->pathArgs);
|
||||
EXPECT_EQ(ret, 0);
|
||||
CmdLines *cmdline = (CmdLines *)malloc(sizeof(CmdLines) + sizeof(CmdLine));
|
||||
ASSERT_NE(nullptr, cmdline);
|
||||
@ -138,11 +138,11 @@ HWTEST_F(ServiceUnitTest, TestServiceStartAbnormal, TestSize.Level1)
|
||||
int ret = ParseOneService(serviceItem, service);
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
ret = ServiceStart(service);
|
||||
ret = ServiceStart(service, &service->pathArgs);
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
service->attribute &= SERVICE_ATTR_INVALID;
|
||||
ret = ServiceStart(service);
|
||||
ret = ServiceStart(service, &service->pathArgs);
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
service->pid = -1;
|
||||
@ -373,7 +373,7 @@ HWTEST_F(ServiceUnitTest, TestServiceExec, TestSize.Level1)
|
||||
service->servPerm.capsCnt = 1;
|
||||
IsEnableSandbox();
|
||||
EnterServiceSandbox(service);
|
||||
int ret = ServiceExec(service);
|
||||
int ret = ServiceExec(service, &service->pathArgs);
|
||||
EXPECT_EQ(ret, 0);
|
||||
|
||||
const int invalidImportantValue = 20;
|
||||
|
@ -935,7 +935,7 @@ HWTEST_F(StartupInitUTest, cmdJobTest_001, TestSize.Level0)
|
||||
StartServiceByName("service name does not exist");
|
||||
StopAllServices(0, nullptr, 0, nullptr);
|
||||
ServiceReap(nullptr);
|
||||
EXPECT_NE(0, ServiceStart(nullptr));
|
||||
EXPECT_NE(0, ServiceStart(nullptr, nullptr));
|
||||
EXPECT_NE(0, ServiceStop(nullptr));
|
||||
}
|
||||
|
||||
|
@ -595,11 +595,13 @@ static __attribute__((constructor(101))) void ParamTestStubInit(void)
|
||||
PARAM_LOGI("TestSetSelinuxOps \n");
|
||||
#ifndef OHOS_LITE
|
||||
TestBeforeInit();
|
||||
#endif
|
||||
SystemPrepare();
|
||||
#ifndef __LITEOS_A__
|
||||
SystemInit();
|
||||
#endif
|
||||
PARAM_LOGI("SystemConfig \n");
|
||||
SystemConfig();
|
||||
#endif
|
||||
PrepareInitUnitTestEnv();
|
||||
}
|
||||
|
||||
|
@ -378,10 +378,14 @@ HWTEST_F(SysparaUnitTest, parameterTest0016, TestSize.Level0)
|
||||
|
||||
HWTEST_F(SysparaUnitTest, parameterTest0017, TestSize.Level0)
|
||||
{
|
||||
GetDistributionOSName();
|
||||
GetDistributionOSVersion();
|
||||
GetDistributionOSApiVersion();
|
||||
GetDistributionOSReleaseType();
|
||||
printf("distributionOS name =%s\n", GetDistributionOSName());
|
||||
EXPECT_STRNE(GetDistributionOSName(), nullptr);
|
||||
printf("distributionOS version =%s\n", GetDistributionOSVersion());
|
||||
EXPECT_STRNE(GetDistributionOSVersion(), nullptr);
|
||||
printf("distributionOS api version =%d\n", GetDistributionOSApiVersion());
|
||||
EXPECT_GT(GetDistributionOSApiVersion(), 0);
|
||||
printf("distributionOS name =%s\n", GetDistributionOSReleaseType());
|
||||
EXPECT_STRNE(GetDistributionOSReleaseType(), nullptr);
|
||||
}
|
||||
#endif
|
||||
} // namespace OHOS
|
||||
|
Loading…
x
Reference in New Issue
Block a user