diff --git a/services/etc/console.cfg b/services/etc/console.cfg index 5df3b774d6f52e6dec834397b393cf786ee96619..d3ada076331e3fcd74160a074544f8dc5a93bbee 100644 --- a/services/etc/console.cfg +++ b/services/etc/console.cfg @@ -8,6 +8,7 @@ "sandbox" : 0, "uid" : "root", "gid" : ["shell", "log", "readproc"], + "ondemand" : true, "jobs" : { "on-start" : "services:console" }, diff --git a/services/etc/init.cfg b/services/etc/init.cfg index f90de37cd577a26807e4c2ea2408bdcf950ee133..ab2c8bd7392f2efe882dfdddb8f806ec3a8fbfe4 100755 --- a/services/etc/init.cfg +++ b/services/etc/init.cfg @@ -212,12 +212,6 @@ "cmds" : [ "write /proc/sys/kernel/perf_event_paranoid 3" ] - }, { - "name" : "boot && param:const.debuggable=1", - "condition" : "boot && const.debuggable=1", - "cmds" : [ - "start console" - ] }, { "name" : "services:console", "cmds" : [ diff --git a/services/include/init_utils.h b/services/include/init_utils.h index 5a76a64f5974d58dfdcb87ff66f200fbcf063db2..1b91ff9da7378f7cf732f768cb7a3138dadc68fc 100644 --- a/services/include/init_utils.h +++ b/services/include/init_utils.h @@ -42,6 +42,7 @@ typedef struct { #define WAIT_MAX_SECOND 5 #define MAX_BUFFER_LEN 256 #define CMDLINE_VALUE_LEN_MAX 512 +#define STDERR_HANDLE 2 #define ARRAY_LENGTH(array) (sizeof((array)) / sizeof((array)[0])) #ifndef STARTUP_INIT_UT_PATH @@ -83,7 +84,8 @@ char *TrimHead(char *str, char c); 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); #ifdef __cplusplus #if __cplusplus } diff --git a/services/init/include/device.h b/services/init/include/device.h index 043b2f14f3c2903dc7b783dc3c091d8bfe02ef23..fb6d92d758fef5a51625b11f436ce5a2efa7c6b6 100644 --- a/services/init/include/device.h +++ b/services/init/include/device.h @@ -29,7 +29,6 @@ extern "C" { void MountBasicFs(void); void CreateDeviceNode(void); -void CloseStdio(void); #ifdef __cplusplus #if __cplusplus diff --git a/services/init/include/init_service.h b/services/init/include/init_service.h index ff5eba1bcfd8482d506cc887e67bd057163ef5b0..e1ac68a37a134d9cb1ac864e29ea286afbc7e321 100644 --- a/services/init/include/init_service.h +++ b/services/init/include/init_service.h @@ -67,6 +67,12 @@ extern "C" { #define IsOnDemandService(service) \ (((service)->attribute & SERVICE_ATTR_ONDEMAND) == SERVICE_ATTR_ONDEMAND) +#define MarkServiceAsOndemand(service) \ + ((service)->attribute |= SERVICE_ATTR_ONDEMAND) + +#define UnMarkServiceAsOndemand(service) \ + ((service)->attribute &= ~SERVICE_ATTR_ONDEMAND) + #define IsServiceWithTimerEnabled(service) \ (((service)->attribute & SERVICE_ATTR_TIMERSTART) == SERVICE_ATTR_TIMERSTART) diff --git a/services/init/include/init_service_manager.h b/services/init/include/init_service_manager.h index a007e772419d92b63715d6ede2acb80b9901e83f..9dffafd343c56b1dbf4dabe7cfcbdba8fcba342a 100644 --- a/services/init/include/init_service_manager.h +++ b/services/init/include/init_service_manager.h @@ -64,6 +64,7 @@ Service *AddService(const char *name); void DumpServiceHookExecute(const char *name, const char *info); void ProcessControlFd(uint16_t type, const char *serviceCmd, const void *context); int GetKillServiceSig(const char *name); +int WatchConsoleDevice(Service *service); #ifdef __cplusplus #if __cplusplus } diff --git a/services/init/init_common_service.c b/services/init/init_common_service.c index 5a858719a61af1fbdcfa76f1e2c9b76f141071b0..817f9998db66fa4eefce02fa1b93579b0c82cfcd 100644 --- a/services/init/init_common_service.c +++ b/services/init/init_common_service.c @@ -308,8 +308,12 @@ static int InitServicePropertys(Service *service) } CreateServiceFile(service->fileCfg); - if (service->attribute & SERVICE_ATTR_CONSOLE) { - OpenConsole(); + if ((service->attribute & SERVICE_ATTR_CONSOLE)) { + if (strcmp(service->name, "console") != 0 || !IsOnDemandService(service)) { + OpenConsole(); + } else { + setsid(); + } } PublishHoldFds(service); @@ -317,7 +321,7 @@ static int InitServicePropertys(Service *service) "binding core number failed for service %s", service->name); SetSystemSeccompPolicy(service); - + // permissions INIT_ERROR_CHECK(SetPerms(service) == SERVICE_SUCCESS, return -1, "service %s exit! set perms failed! err %d.", service->name, errno); @@ -524,9 +528,15 @@ void ServiceReap(Service *service) return; } } - // service no need to restart which socket managed by init until socket message detected + // service no need to restart if it is an ondemand service. if (IsOnDemandService(service)) { CheckServiceSocket(service); + if (strcmp(service->name, "console") == 0) { + if (WatchConsoleDevice(service) < 0) { + INIT_LOGE("Failed to watch console service after it exit, mark console service invalid"); + service->attribute |= SERVICE_ATTR_INVALID; + } + } return; } diff --git a/services/init/init_service_manager.c b/services/init/init_service_manager.c index 5e05cbd7a901e7232bf3bbf45c4544fa73aa268b..6b8d1a05bce86bb8c13d27c291e18f8604ed37ca 100755 --- a/services/init/init_service_manager.c +++ b/services/init/init_service_manager.c @@ -20,7 +20,7 @@ #include #include #include - +#include #include "cJSON.h" #include "init.h" #include "init_group_manager.h" @@ -31,6 +31,7 @@ #include "init_utils.h" #include "securec.h" #include "service_control.h" +#include "sys_param.h" #ifdef ASAN_DETECTOR #include "init_param.h" #endif @@ -872,6 +873,90 @@ static void ParseServiceHookExecute(const char *name, const cJSON *serviceNode) } #endif +static void ProcessConsoleEvent(const WatcherHandle handler, int fd, uint32_t *events, const void *context) +{ + Service *service = (Service *)context; + LE_RemoveWatcher(LE_GetDefaultLoop(), (WatcherHandle)handler); + if (fd < 0 || service == NULL) { + INIT_LOGE("Process console event with invalid arguments"); + return; + } + + if (strcmp(service->name, "console") != 0) { + INIT_LOGE("Process console event with invalid service %s, only console service should do this", service->name); + return; + } + + // Check if debuggable + char value[MAX_BUFFER_LEN] = {0}; + unsigned int len = MAX_BUFFER_LEN; + if (SystemReadParam("const.debuggable", value, &len) != 0) { + INIT_LOGE("Failed to read parameter \'const.debuggable\', prevent console service starting"); + CloseStdio(); + return; + } + + int isDebug = StringToInt(value, 0); + if (isDebug != 1) { + INIT_LOGI("Non-debuggable system, prevent console service starting"); + CloseStdio(); + return; + } + ioctl(fd, TIOCSCTTY, 0); + RedirectStdio(fd); + close(fd); + if (ServiceStart(service) != SERVICE_SUCCESS) { + INIT_LOGE("Start console service failed"); + } + return; +} + +static int AddFileDescriptorToWatcher(int fd, Service *service) +{ + if (fd < 0 || service == NULL) { + return -1; + } + + WatcherHandle watcher = NULL; + LE_WatchInfo info = {}; + info.fd = fd; + info.flags = 0; // WATCHER_ONCE; + info.events = Event_Read; + info.processEvent = ProcessConsoleEvent; + int ret = LE_StartWatcher(LE_GetDefaultLoop(), &watcher, &info, service); + if (ret != LE_SUCCESS) { + INIT_LOGE("Failed to watch console device for service \' %s \'", service->name); + return -1; + } + return 0; +} + +int WatchConsoleDevice(Service *service) +{ + if (service == NULL) { + return -1; + } + + int fd = open("/dev/console", O_RDWR); + if (fd < 0) { + if (errno == ENOENT) { + INIT_LOGW("/dev/console is not exist, wait for it..."); + WaitForFile("/dev/console", WAIT_MAX_SECOND); + fd = open("/dev/console", O_RDWR); + if (fd < 0) { + INIT_LOGW("Failed to open /dev/console after try 1 time"); + return -1; + } + } + } + + if (AddFileDescriptorToWatcher(fd, service) < 0) { + close(fd); + return -1; + } + return 0; +} + void ParseAllServices(const cJSON *fileRoot) { int servArrSize = 0; @@ -916,6 +1001,14 @@ void ParseAllServices(const cJSON *fileRoot) service->fileCfg = NULL; } + // Watch "/dev/console" node for starting console service ondemand. + if ((strcmp(service->name, "console") == 0) && IsOnDemandService(service)) { + if (WatchConsoleDevice(service) < 0) { + INIT_LOGW("Failed to watch \'/dev/console\' device"); + INIT_LOGW("Remove service \' %s \' ondemand attribute", service->name); + UnMarkServiceAsOndemand(service); + } + } #ifndef OHOS_LITE /* * Execute service parsing hooks diff --git a/services/init/standard/device.c b/services/init/standard/device.c index 201f78f799129470302f5d0c3a2891b67c579d5b..82a91ec19ed937c6052691e013c428e54e6dd50c 100644 --- a/services/init/standard/device.c +++ b/services/init/standard/device.c @@ -25,19 +25,6 @@ #define DEFAULT_RW_MODE (S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH) #define DEFAULT_NO_AUTHORITY_MODE (S_IWUSR | S_IRUSR) -#define STDERR_HANDLE 2 - -void CloseStdio(void) -{ - int fd = open("/dev/null", O_RDWR | O_CLOEXEC); - if (fd < 0) { - return; - } - dup2(fd, 0); - dup2(fd, 1); - dup2(fd, STDERR_HANDLE); - close(fd); -} void MountBasicFs(void) { diff --git a/services/utils/init_utils.c b/services/utils/init_utils.c index 1c5ebead5559cc775f4ccfd2636227823c35eaa1..fba6ba2b077344c421cf815162c1b726aecba85d 100644 --- a/services/utils/init_utils.c +++ b/services/utils/init_utils.c @@ -160,6 +160,20 @@ char *ReadFileToBuf(const char *configFile) return buffer; } +void CloseStdio(void) +{ +#ifndef __LITEOS_M__ + int fd = open("/dev/null", O_RDWR | O_CLOEXEC); + if (fd < 0) { + return; + } + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, STDERR_HANDLE); + close(fd); +#endif +} + char *ReadFileData(const char *fileName) { if (fileName == NULL) { @@ -531,18 +545,25 @@ uint32_t GetRandom() return ulSeed; } -void OpenConsole(void) +void RedirectStdio(int fd) { #ifndef __LITEOS_M__ const int stdError = 2; + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, stdError); // Redirect fd to 0, 1, 2 +#endif +} + +void OpenConsole(void) +{ +#ifndef __LITEOS_M__ setsid(); WaitForFile("/dev/console", WAIT_MAX_SECOND); int fd = open("/dev/console", O_RDWR); if (fd >= 0) { ioctl(fd, TIOCSCTTY, 0); - dup2(fd, 0); - dup2(fd, 1); - dup2(fd, stdError); // Redirect fd to 0, 1, 2 + RedirectStdio(fd); close(fd); } else { INIT_LOGE("Open /dev/console failed. err = %d", errno); diff --git a/ueventd/ueventd.c b/ueventd/ueventd.c index 829086fc01e0d2e51f5d5fc4dd3fa0f09e11dcee..09b5de54db211e4c96d66802be89f5ce0c315ab5 100644 --- a/ueventd/ueventd.c +++ b/ueventd/ueventd.c @@ -134,8 +134,10 @@ typedef struct { #define DEV_NODE_PATH_PREFIX_LEN 5 static const DYNAMIC_DEVICE_NODE dynamicDevices[] = { - { DEV_NODE_PATH_PREFIX"tty", S_IFCHR | DEFAULT_RW_MODE }, - { DEV_NODE_PATH_PREFIX"binder", S_IFCHR | DEFAULT_RW_MODE } + { DEV_NODE_PATH_PREFIX"tty", S_IFCHR | DEFAULT_RW_MODE }, + { DEV_NODE_PATH_PREFIX"binder", S_IFCHR | DEFAULT_RW_MODE }, + { DEV_NODE_PATH_PREFIX"console", S_IFCHR | DEFAULT_RW_MODE }, + { DEV_NODE_PATH_PREFIX"tty", S_IFCHR | DEFAULT_RW_MODE } }; static void HandleRequiredDynamicDeviceNodes(const struct Uevent *uevent)