From fb41a54c41ab8a8422451eb20f9848d0799eae2f Mon Sep 17 00:00:00 2001 From: Wonki Kim Date: Wed, 18 Sep 2019 15:40:42 +0900 Subject: [PATCH 01/16] Add a logic to specify the app id while forking Application runs by forking a launchpad process in Tizen. A forked application process inherits whole information of launchpad including atspi application name that is specified by calling elm_app_name_set. this patch adds a logic to have the own name for each forked applications in atspi point of view. Change-Id: I42c892e4c8c15a67ddc5fac0bdd435305fcababe --- src/launchpad_loader.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/launchpad_loader.c b/src/launchpad_loader.c index cf92185..d91fd97 100644 --- a/src/launchpad_loader.c +++ b/src/launchpad_loader.c @@ -274,6 +274,8 @@ static int __loader_launch_cb(int argc, char **argv, const char *app_path, const char *high_priority; #endif + elm_app_name_set(appid); + vconf_ignore_key_changed(VCONFKEY_SETAPPL_APP_HW_ACCELERATION, __vconf_cb); if (kb == NULL) -- 2.7.4 From 178013f98aeb2c190071fd96895a84c5a415033e Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 25 Sep 2019 09:20:55 +0900 Subject: [PATCH 02/16] Release version 0.9.1 Changes: - Add a logic to specify the app id while forking Change-Id: I731f7de141e70819c5ece3ba4a617a194b0f9f3c Signed-off-by: Hwankyu Jhun --- packaging/launchpad.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index d17f4c3..acd4cce 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.9.0 +Version: 0.9.1 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From 418490a0284aa5e08921fd6a6480fdee1369056d Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 2 Oct 2019 10:42:17 +0900 Subject: [PATCH 03/16] Print HW clock logs for performance measurement Change-Id: I69f247fcd08e4a03912f0e2257912a8f234187bc Signed-off-by: Hwankyu Jhun --- inc/launchpad_common.h | 1 + src/launchpad.c | 3 +++ src/launchpad_common.c | 17 +++++++++++++++++ 3 files changed, 21 insertions(+) diff --git a/inc/launchpad_common.h b/inc/launchpad_common.h index 0ebb452..b66fa62 100644 --- a/inc/launchpad_common.h +++ b/inc/launchpad_common.h @@ -139,6 +139,7 @@ int _prepare_app_socket(void); int _enable_external_pkg(bundle *b, const char *pkgid, uid_t pkg_uid); int _verify_proc_caps(void); int _prepare_id_file(void); +void _print_hwc_log(const char *format, ...); #endif /* __LAUNCHPAD_COMMON_H__ */ diff --git a/src/launchpad.c b/src/launchpad.c index 4d6cabb..cf54b45 100755 --- a/src/launchpad.c +++ b/src/launchpad.c @@ -1131,6 +1131,8 @@ static int __exec_app_process(void *arg) struct app_launch_arg *launch_arg = arg; int ret; + _print_hwc_log("%d|after calling fork(). %s", + getpid(), launch_arg->appid); PERF("fork done"); _D("lock up test log(no error) : fork done"); @@ -1166,6 +1168,7 @@ static int __launch_directly(const char *appid, const char *app_path, int clifd, arg.menu_info = menu_info; arg.kb = kb; + _print_hwc_log("before calling fork(). %s", appid); pid = __fork_app_process(__exec_app_process, &arg); if (pid <= 0) _E("failed to fork app process"); diff --git a/src/launchpad_common.c b/src/launchpad_common.c index eade9b5..5607c77 100644 --- a/src/launchpad_common.c +++ b/src/launchpad_common.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -68,6 +69,10 @@ #define APP2SD_RETRY_MAX 5 #define APP2SD_WAIT_USEC (1000000 / 2) /* 0.5 sec */ +#ifndef PR_TASK_PERF_USER_TRACE +#define PR_TASK_PERF_USER_TRACE 666 +#endif + static int __read_proc(const char *path, char *buf, int size) { int fd; @@ -1437,3 +1442,15 @@ int _send_message_to_logger(const char *tag, const char *format, ...) return 0; } + +void _print_hwc_log(const char *format, ...) +{ + char buf[1024]; + va_list ap; + + va_start(ap, format); + vsnprintf(buf, sizeof(buf), format, ap); + va_end(ap); + + prctl(PR_TASK_PERF_USER_TRACE, buf, strlen(buf)); +} -- 2.7.4 From d1564d55441f39dbeef1617455205ab86698dfbd Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 2 Oct 2019 11:24:07 +0900 Subject: [PATCH 04/16] Release version 0.9.2 Changes: - Print HW clock logs for performance measurement Change-Id: I6e851e6e1643b6cba3a4547701822124828a009e Signed-off-by: Hwankyu Jhun --- packaging/launchpad.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index acd4cce..8b887f7 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.9.1 +Version: 0.9.2 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From d79467a0fc7d715caeccb811a56e37d958955a79 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 7 Oct 2019 18:39:00 +0900 Subject: [PATCH 05/16] Add AUL_HWACC variable to the environment Change-Id: I1f3b9e3444d41a5a6123ac6a1874eddebacc7e8b Signed-off-by: Hwankyu Jhun --- src/launchpad_loader.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/launchpad_loader.c b/src/launchpad_loader.c index d91fd97..afc6c28 100644 --- a/src/launchpad_loader.c +++ b/src/launchpad_loader.c @@ -223,11 +223,13 @@ static void __loader_create_cb(bundle *extra, int type, void *user_data) switch (__type) { case TYPE_SW: elm_config_accel_preference_set("none"); + setenv("AUL_HWACC", "none", 1); __init_window(); break; case TYPE_HW: elm_config_accel_preference_set("hw"); + setenv("AUL_HWACC", "hw", 1); __init_window(); break; @@ -379,7 +381,7 @@ do_exec: setenv("LD_LIBRARY_PATH", libdir, 1); free(libdir); unsetenv("AUL_LOADER_INIT"); - unsetenv("VC_ELM_INIT"); + unsetenv("AUL_HWACC"); if (execv(argv[LOADER_ARG_PATH], argv) < 0) { _send_message_to_logger(argv[LOADER_ARG_PATH], "Failed to execute a file. error(%d:%s)", -- 2.7.4 From ab2a6c0a94d996d325f7bcb9932c2028bb551488 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 7 Oct 2019 18:18:21 +0900 Subject: [PATCH 06/16] Check if the main loop is stopped properly If the main loop is stopped forcedly, the loader_terminate_cb callback function must not be called. Change-Id: Idb1e253e4be5a46fa1b954221f0d083bce7761a3 Signed-off-by: Hwankyu Jhun --- src/launchpad_lib.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/launchpad_lib.c b/src/launchpad_lib.c index 5ce202e..c3f41d8 100644 --- a/src/launchpad_lib.c +++ b/src/launchpad_lib.c @@ -54,6 +54,7 @@ static int __loader_type = LAUNCHPAD_TYPE_UNSUPPORTED; static int __loader_id; static pid_t __candidate_pid = -1; static struct sigaction __prev_sigchld; +static bool __loop_quit; static void __at_exit_to_release_bundle(void) { @@ -309,6 +310,7 @@ static void __receiver_cb(int fd) if (ret >= 0) { __loader_adapter->loop_quit(__loader_user_data); _D("[candidate] ecore main loop quit"); + __loop_quit = true; } } @@ -547,6 +549,11 @@ API int launchpad_loader_main(int argc, char **argv, _D("[candidate] ecore main loop begin"); __loader_adapter->loop_begin(__loader_user_data); + if (!__loop_quit) { + _E("[candidate] loop was stopped forcedly"); + return -1; + } + return __after_loop(); } @@ -681,4 +688,4 @@ API int launchpad_hydra_main(int argc, char **argv, } return 0; -} \ No newline at end of file +} -- 2.7.4 From b0e0837d9824a004e753bab00c811fd08aa14daf Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 8 Oct 2019 08:29:41 +0900 Subject: [PATCH 07/16] Release version 0.9.3 Changes: - Add AUL_HWACC variable to the environment - Check if the main loop is stopped properly Change-Id: Ief4583d89d068ace81ca8d6c0023a2eb8cd2b944 Signed-off-by: Hwankyu Jhun --- packaging/launchpad.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index 8b887f7..52a3e20 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.9.2 +Version: 0.9.3 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From 763bfd522f303d34c2743eb3eb0512d3695fde15 Mon Sep 17 00:00:00 2001 From: Hyungju Lee Date: Fri, 11 Oct 2019 16:05:31 +0900 Subject: [PATCH 08/16] Fix candidate start bug on hydra mode Change-Id: I3d71eeb7606cd73b8b251dd6bbc0f52fce3651da --- src/launchpad_lib.c | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/src/launchpad_lib.c b/src/launchpad_lib.c index c3f41d8..24532b9 100644 --- a/src/launchpad_lib.c +++ b/src/launchpad_lib.c @@ -55,6 +55,7 @@ static int __loader_id; static pid_t __candidate_pid = -1; static struct sigaction __prev_sigchld; static bool __loop_quit; +static bool __is_candidate = false; static void __at_exit_to_release_bundle(void) { @@ -320,7 +321,6 @@ static void __hydra_receiver_cb(int fd) enum hydra_cmd cmd = -1; int len; pid_t pid; - int r; _D("[hydra] ECORE_FD_READ"); @@ -352,12 +352,15 @@ retry_recv: _E("[hydra] unable to fork: %s", strerror_r(errno, err_str, sizeof(err_str))); } else if (pid > 0) { - SECURE_LOGD("[hydra] forked candidate with pid=%d", pid); + SECURE_LOGD("[hydra] forked new candidate with pid=%d", pid); __candidate_pid = pid; + __is_candidate = false; return; } else { + __is_candidate = true; + if (sigaction(SIGCHLD, &__prev_sigchld, NULL)) { _E("[hydra] sigaction failed: %s", strerror_r(errno, err_str, sizeof(err_str))); @@ -373,15 +376,7 @@ retry_recv: __loader_adapter->loop_quit(__loader_user_data); - if (__hydra_callbacks->terminate) - __hydra_callbacks->terminate(__loader_user_data); - - r = launchpad_loader_main(__argc, __argv, __loader_callbacks, - __loader_adapter, __loader_user_data); - if (r != 0) - _E("[hydra] launchpad_loader_main failed. Error: %d", r); - - exit(r); + return; } err: @@ -572,6 +567,7 @@ API int launchpad_hydra_main(int argc, char **argv, int loader_type; int loader_id; int client_fd; + int r = -1; pid_t pid; struct sigaction new_act; @@ -650,8 +646,12 @@ API int launchpad_hydra_main(int argc, char **argv, if (hydra_callbacks->fork) hydra_callbacks->fork(user_data); - return launchpad_loader_main(argc, argv, callbacks, - adapter, user_data); + r = launchpad_loader_main(argc, argv, callbacks, adapter, user_data); + + if (r != 0) + _E("[hydra] launchpad_loader_main failed. Error: %d", r); + + return r; } else { __hydra_callbacks = hydra_callbacks; __loader_callbacks = callbacks; @@ -681,10 +681,19 @@ API int launchpad_hydra_main(int argc, char **argv, __loader_adapter->loop_begin(__loader_user_data); + /* At this point, either end of hydra process or start of candidate process main loop */ if (__hydra_callbacks->terminate) - return __hydra_callbacks->terminate(__loader_user_data); + r = __hydra_callbacks->terminate(__loader_user_data); - return -1; + if (__is_candidate) { + r = launchpad_loader_main(__argc, __argv, __loader_callbacks, + __loader_adapter, __loader_user_data); + + if (r != 0) + _E("[hydra] launchpad_loader_main failed. Error: %d", r); + } + + return r; } return 0; -- 2.7.4 From 5436a5d69cdc9a3a82846d8d4895d9a37d10a512 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 11 Oct 2019 16:50:35 +0900 Subject: [PATCH 09/16] Release version 0.9.4 Changes: - Fix candidate start bug on hydra mode Change-Id: If0822da887f8293ddc4aa780f4413964c57ca118 Signed-off-by: Hwankyu Jhun --- packaging/launchpad.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index 52a3e20..b02380c 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.9.3 +Version: 0.9.4 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From b17d61536aa967842bacea0ebae50a1258d702d3 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 14 Oct 2019 14:54:08 +0900 Subject: [PATCH 10/16] Fix a bug about hydra loader After a new package is installed, the launchpad has to send SIGKILL signal to the running hydra loaders. Change-Id: Ia44e768c893fb8ffe1680452b3688e8fd3ccb552 Signed-off-by: Hwankyu Jhun --- src/launchpad.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/launchpad.c b/src/launchpad.c index cf54b45..2fc5c02 100755 --- a/src/launchpad.c +++ b/src/launchpad.c @@ -1357,7 +1357,6 @@ static gboolean __handle_hydra_client_event(gpointer data) SECURE_LOGE("Type %d hydra process was " \ "(POLLHUP|POLLNVAL), pid: %d", cpc->type, cpc->hydra_pid); - cpc->hydra_pid = HYDRA_NONE; __dispose_hydra_process(cpc); __prepare_candidate_process(cpc->type, cpc->loader_id); return G_SOURCE_REMOVE; @@ -1509,7 +1508,13 @@ static gboolean __handle_label_monitor(gpointer data) while (iter) { cpc = (candidate_process_context_t *)iter->data; - if (cpc->pid > 0) { + if (cpc->is_hydra) { + if (cpc->hydra_pid > 0) { + __dispose_hydra_process(cpc); + __prepare_candidate_process(cpc->type, + cpc->loader_id); + } + } else if (cpc->pid > 0) { __dispose_candidate_process(cpc); __prepare_candidate_process(cpc->type, cpc->loader_id); } -- 2.7.4 From 856e301a7ae4850efde31feb2b7ba2c32b694b49 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 14 Oct 2019 17:18:04 +0900 Subject: [PATCH 11/16] Release version 0.9.5 Changes: - Fix a bug about hydra loader Change-Id: Iee9c52e1b5b739f7e0e1c6946e2a6966e554545c Signed-off-by: Hwankyu Jhun --- packaging/launchpad.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index b02380c..85ee3d9 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.9.4 +Version: 0.9.5 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From 56df0ac045ded474e3b2eb1a7ab4e761aca7cc86 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 17 Oct 2019 10:50:14 +0900 Subject: [PATCH 12/16] Add missing function call To separate mount namespace, security_manager_prepare_app_candidate() has to be called. Change-Id: Ie3a5d7e6f35b82694fd8760b4839e0e9deffec6c Signed-off-by: Hwankyu Jhun --- src/launchpad_lib.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/launchpad_lib.c b/src/launchpad_lib.c index 24532b9..6441104 100644 --- a/src/launchpad_lib.c +++ b/src/launchpad_lib.c @@ -320,6 +320,7 @@ static void __hydra_receiver_cb(int fd) char err_str[MAX_LOCAL_BUFSZ] = { 0, }; enum hydra_cmd cmd = -1; int len; + int ret; pid_t pid; _D("[hydra] ECORE_FD_READ"); @@ -361,6 +362,14 @@ retry_recv: } else { __is_candidate = true; + _W("security_manager_prepare_app_candidate ++"); + ret = security_manager_prepare_app_candidate(); + _W("security_manager_prepare_app_candidate --"); + if (ret != SECURITY_MANAGER_SUCCESS) { + _E("Failed to prepare app candidate process (%d)", ret); + exit(1); + } + if (sigaction(SIGCHLD, &__prev_sigchld, NULL)) { _E("[hydra] sigaction failed: %s", strerror_r(errno, err_str, sizeof(err_str))); @@ -637,6 +646,14 @@ API int launchpad_hydra_main(int argc, char **argv, strerror_r(errno, err_str, sizeof(err_str))); return -1; } else if (pid == 0) { + _W("security_manager_prepare_app_candidate ++"); + r = security_manager_prepare_app_candidate(); + _W("security_manager_prepare_app_candidate --"); + if (r != SECURITY_MANAGER_SUCCESS) { + _E("Failed to prepare app candidate process (%d)", r); + exit(1); + } + if (sigaction(SIGCHLD, &__prev_sigchld, NULL)) { _E("[hydra] sigaction failed: %s", strerror_r(errno, err_str, sizeof(err_str))); -- 2.7.4 From 718dc0e6d51423c2f72f9914a4d239ba46a1251f Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 17 Oct 2019 15:58:01 +0900 Subject: [PATCH 13/16] Release version 0.9.6 Changes: - Add missing function call Change-Id: I738b48c50b42dcd76ae00e7b0466985510c07d27 Signed-off-by: Hwankyu Jhun --- packaging/launchpad.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index 85ee3d9..4a89322 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.9.5 +Version: 0.9.6 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From a1216be365eba387db206ecea51157132131623c Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 22 Oct 2019 19:25:53 +0900 Subject: [PATCH 14/16] Refactor Launchpad Hydra Loader - Add a new API to exit the main loop of hydra loader - Use sd-event loop instead of custom loop Change-Id: If5030933db38ecca12bb46cb81c3ec448fc9ad08 Signed-off-by: Hwankyu Jhun --- CMakeLists.txt | 23 +++ inc/launchpad.h | 17 -- inc/launchpad_common.h | 17 -- inc/launchpad_hydra.h | 131 ++++++++++++++ inc/launchpad_types.h | 48 +++++ launchpad.pc.in | 2 +- liblaunchpad-hydra.pc.in | 13 ++ packaging/launchpad.spec | 2 + src/launchpad.c | 13 +- src/launchpad_common.c | 34 +--- src/launchpad_debug.c | 5 +- src/launchpad_hydra.c | 455 +++++++++++++++++++++++++++++++++++++++++++++++ src/launchpad_lib.c | 264 +-------------------------- src/launchpad_loader.c | 1 + src/log_private.h | 32 ++++ 15 files changed, 719 insertions(+), 338 deletions(-) create mode 100644 inc/launchpad_hydra.h create mode 100644 inc/launchpad_types.h create mode 100644 liblaunchpad-hydra.pc.in create mode 100644 src/launchpad_hydra.c create mode 100644 src/log_private.h diff --git a/CMakeLists.txt b/CMakeLists.txt index a557924..e338b05 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,6 +2,7 @@ CMAKE_MINIMUM_REQUIRED(VERSION 2.6) SET (this_target_pool launchpad_pool) SET (this_target_loader launchpad_loader) SET (this_target_lib launchpad) +SET (this_target_hydra launchpad_hydra) INCLUDE(FindPkgConfig) PKG_CHECK_MODULES(${this_target_pool} REQUIRED @@ -59,6 +60,14 @@ FOREACH(flag ${${this_target_lib}_CFLAGS}) SET(EXTRA_CFLAGS_lib "${EXTRA_CFLAGS_lib} ${flag}") ENDFOREACH(flag) +PKG_CHECK_MODULES(${this_target_hydra} REQUIRED + dlog + libsystemd) + +FOREACH(flag ${${this_target_hydra}_CFLAGS}) + SET(EXTRA_CFLAGS_hydra "${EXTRA_CFLAGS_hydra} ${flag}") +ENDFOREACH(flag) + SET(EXTRA_CFLAGS_common "${EXTRA_CFLAGS_common} -Wl,-zdefs" ) SET(EXTRA_CFLAGS_common "${EXTRA_CFLAGS_common} -fvisibility=hidden") SET(EXTRA_CFLAGS_common "${EXTRA_CFLAGS_common} -fdata-sections -ffunction-sections -Wl,--gc-sections") @@ -68,6 +77,7 @@ SET(EXTRA_CFLAGS_common "${EXTRA_CFLAGS_common} -Werror") SET(EXTRA_CFLAGS_pool "${EXTRA_CFLAGS_pool} ${EXTRA_CFLAGS_common} -fPIE") SET(EXTRA_CFLAGS_loader "${EXTRA_CFLAGS_loader} ${EXTRA_CFLAGS_common} -fPIE") SET(EXTRA_CFLAGS_lib "${EXTRA_CFLAGS_lib} ${EXTRA_CFLAGS_common}") +SET(EXTRA_CFLAGS_hydra "${EXTRA_CFLAGS_hydra} ${EXTRA_CFLAGS_common}") SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") SET(CMAKE_C_FLAGS_RELEASE "-O2") @@ -159,5 +169,18 @@ INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/launchpad.pc DESTINATION ${LIB_INSTALL CONFIGURE_FILE(launchpad.pc.in liblaunchpad.pc @ONLY) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/liblaunchpad.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) +# liblaunchpad_hydra +SET(LAUNCHPAD_HYDRA "launchpad-hydra") +ADD_LIBRARY(${LAUNCHPAD_HYDRA} SHARED + src/launchpad_hydra.c + ) +SET_TARGET_PROPERTIES(${LAUNCHPAD_HYDRA} PROPERTIES SOVERSION ${MAJORVER}) +SET_TARGET_PROPERTIES(${LAUNCHPAD_HYDRA} PROPERTIES VERSION ${VERSION}) +SET_TARGET_PROPERTIES(${LAUNCHPAD_HYDRA} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_hydra}) +TARGET_LINK_LIBRARIES(${LAUNCHPAD_HYDRA} ${${this_target_hydra}_LDFLAGS} "-ldl") +INSTALL(TARGETS ${LAUNCHPAD_HYDRA} DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) +INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/inc/launchpad_hydra.h DESTINATION include/launchpad) +CONFIGURE_FILE(liblaunchpad-hydra.pc.in liblaunchpad-hydra.pc @ONLY) +INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/liblaunchpad-hydra.pc DESTINATION ${LIB_INSTALL_DIR}/pkgconfig) diff --git a/inc/launchpad.h b/inc/launchpad.h index 0dfea81..b5a11db 100644 --- a/inc/launchpad.h +++ b/inc/launchpad.h @@ -29,11 +29,6 @@ typedef int (*loader_launch_cb)(int argc, char **argv, const char *app_path, void *user_data); typedef int (*loader_terminate_cb)(int argc, char **argv, void *user_data); -typedef void (*hydra_precreate_cb)(void *user_data); -typedef void (*hydra_create_cb)(void *user_data); -typedef void (*hydra_fork_cb)(void *user_data); -typedef int (*hydra_terminate_cb)(void *user_data); - typedef void (*loader_receiver_cb)(int fd); typedef void (*loader_loop_begin_cb)(void *user_data); typedef void (*loader_loop_quit_cb)(void *user_data); @@ -48,13 +43,6 @@ typedef struct { } loader_lifecycle_callback_s; typedef struct { - hydra_precreate_cb precreate; - hydra_create_cb create; - hydra_fork_cb fork; - hydra_terminate_cb terminate; -} hydra_lifecycle_callback_s; - -typedef struct { loader_loop_begin_cb loop_begin; loader_loop_quit_cb loop_quit; loader_add_fd_cb add_fd; @@ -72,11 +60,6 @@ int launchpad_loader_main(int argc, char **argv, loader_lifecycle_callback_s *callbacks, loader_adapter_s *adapter, void *user_data); -int launchpad_hydra_main(int argc, char **argv, - hydra_lifecycle_callback_s *hydra_callbacks, - loader_lifecycle_callback_s *callbacks, - loader_adapter_s *adapter, void *user_data); - /* * @par Description * Set program scheduling priority. diff --git a/inc/launchpad_common.h b/inc/launchpad_common.h index b66fa62..c5859e2 100644 --- a/inc/launchpad_common.h +++ b/inc/launchpad_common.h @@ -33,9 +33,6 @@ #define LOG_TAG "LAUNCHPAD" #endif -#define SOCKET_PATH "/run/aul" -#define LAUNCHPAD_LOADER_SOCKET_NAME ".launchpad-type" -#define HYDRA_LOADER_SOCKET_NAME ".hydra-loader" #define MAX_PENDING_CONNECTIONS 10 #define MAX_LOCAL_BUFSZ 128 #define AUL_SOCK_MAXBUFF 131071 @@ -74,19 +71,6 @@ #define ARRAY_SIZE(x) ((sizeof(x)) / sizeof(x[0])) #define GLOBAL_USER tzplatform_getuid(TZ_SYS_GLOBALAPP_USER) -enum loader_arg { - LOADER_ARG_PATH, - LOADER_ARG_TYPE, - LOADER_ARG_ID, - LOADER_ARG_HYDRA, - LOADER_ARG_EXTRA, - LOADER_ARG_DUMMY, -}; - -enum hydra_cmd { - LAUNCH_CANDIDATE, -}; - typedef struct _app_pkt_t { int cmd; int len; @@ -119,7 +103,6 @@ app_pkt_t *_recv_pkt_raw(int fd); app_pkt_t *_accept_recv_pkt_raw(int fd, int *clifd, struct ucred *cr); int _send_pkt_raw(int client_fd, app_pkt_t *pkt); int _connect_to_launchpad(int type, int id); -int _connect_to_launchpad_hydra(int type, int id); int _set_sock_option(int fd, int cli); void _set_env(appinfo_t *menu_info, bundle *kb); char **_create_argc_argv(bundle *kb, int *margc); diff --git a/inc/launchpad_hydra.h b/inc/launchpad_hydra.h new file mode 100644 index 0000000..bf0f4f9 --- /dev/null +++ b/inc/launchpad_hydra.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __LAUNCHPAD_HYDRA_H__ +#define __LAUNCHPAD_HYDRA_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Called when the hydra loader starts. + * @details The callback function is called before the main loop of the hydra loader starts. + * In this callback, you can initialize resources like preloading libraries. + * @since_tizen 5.5 + * + * @param[in] user_data The user data passed from the callback registration function + * + * @see launchpad_hydra_main() + * @see #hydra_lifecycle_callback_s + */ +typedef void (*hydra_precreate_cb)(void *user_data); + +/** + * @brief Called when the hydra loader starts. + * @details The callback function is called before the main loop of the hydra loader starts. + * @since_tizen 5.5 + * + * @param[in] user_data The user data passed from the callback registration function + * + * @see launchpad_hydra_main() + * @see #hydra_lifecycle_callback_s + */ +typedef void (*hydra_create_cb)(void *user_data); + +/** + * @brief Called when a child process of the hydra loader is created. + * @details This callback function is called in the child process when the child process is created. + * After this callback function returns, the process will be terminated. + * @since_tizen 5.5 + * + * @param[in] argc The argument count + * @param[in] argv The argument vector + * @param[in] user_data The user data passed from the callback registration function + * @return @c 0 on success, + * otherwise a negative error value + * + * @see launchpad_hydra_main() + * @see #hydra_lifecycle_callback_s + */ +typedef int (*hydra_fork_cb)(int argc, char **argv, void *user_data); + +/** + * @brief Called when the hydra loader main loop exits. + * @details You should release the hydra loader's resources in this function. + * @since_tizen 5.5 + * + * @param[in] user_data The user data passed from the callback registration function + * @return @c 0 on success, + * otherwise a negative error value + * + * @see launchpad_hydra_main() + * @see #hydra_lifecycle_callback_s + */ +typedef int (*hydra_terminate_cb)(void *user_data); + +/** + * @brief The structure type containing the set of callback functions for handling hydra lifecycle events. + * @details It is one of the input parameters of the launchpad_hydra_main() function. + * @since_tizen 5.5 + * @see hydra_precreate_cb() + * @see hydra_create_cb() + * @see hydra_fork_cb() + * @see hydra_terminate_cb() + */ +typedef struct { + hydra_precreate_cb precreate; /**< This callback function is called at the start of the hydra loader. */ + hydra_create_cb create; /**< This callback function is called at the start of the hydra loader. */ + hydra_fork_cb fork; /**< This callback function is called at the start of the child process. */ + hydra_terminate_cb terminate; /**< This callback function is called once after the main loop of the hydra loader exits. */ +} hydra_lifecycle_callback_s; + +/** + * @brief Runs the hydra loaders' main loop until launchpad_hydra_exit() is called. + * @since_tizen 5.5 + * + * @param[in] argc The argument count + * @param[in] argv The argument vector + * @param[in] hydra_callbacks The set of callback functions to handle hydra lifecycle events. + * @param[in] user_data The user data to be passed to the callback functions + * @return @c 0 on success, + * otherwise a negative error value + * + * @see hydra_precreate_cb() + * @see hydra_create_cb() + * @see hydra_fork_cb() + * @see hydra_terminate_cb() + * @see launchpad_hydra_exit() + * @see #hydra_lifecycle_callback_s + */ +int launchpad_hydra_main(int argc, char **argv, + hydra_lifecycle_callback_s *hydra_callbacks, + void *user_data); + +/** + * @brief Exits the main loop of hydra. + * @details The main loop of hydra stops and hydra_terminate_cb() is called. + * @since_tizen 5.5 + * @see launchpad_hydra_main() + * @see hydra_terminate_cb() + */ +void launchpad_hydra_exit(void); + +#ifdef __cplusplus +} +#endif + +#endif /* __LAUNCHPAD_HYDRA_H__ */ diff --git a/inc/launchpad_types.h b/inc/launchpad_types.h new file mode 100644 index 0000000..22ae867 --- /dev/null +++ b/inc/launchpad_types.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __LAUNCHPAD_TYPES_H__ +#define __LAUNCHPAD_TYPES_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#define SOCKET_PATH "/run/aul" +#define LAUNCHPAD_LOADER_SOCKET_NAME ".launchpad-type" +#define HYDRA_LOADER_SOCKET_NAME ".hydra-loader" +#define CONNECT_RETRY_TIME (100 * 1000) +#define CONNECT_RETRY_COUNT 3 + +typedef enum loader_arg { + LOADER_ARG_PATH, + LOADER_ARG_TYPE, + LOADER_ARG_ID, + LOADER_ARG_HYDRA, + LOADER_ARG_EXTRA, + LOADER_ARG_DUMMY, +} loader_arg_e; + +typedef enum hydra_cmd { + LAUNCH_CANDIDATE, +} hydra_cmd_e; + +#ifdef __cplusplus +} +#endif + +#endif /* __LAUNCHPAD_TYPES_H__ */ + diff --git a/launchpad.pc.in b/launchpad.pc.in index a3da8bf..5db405b 100644 --- a/launchpad.pc.in +++ b/launchpad.pc.in @@ -8,6 +8,6 @@ includedir=@INCLUDE_INSTALL_DIR@ Name: liblaunchpad Description: launchpad library for making other types of loader Version: @VERSION@ -Requires: bundle dlog aul +Requires: bundle dlog aul security-manager tanchor dbus-1 Libs: -L${libdir} -llaunchpad Cflags: -I${includedir} -I${includedir}/launchpad diff --git a/liblaunchpad-hydra.pc.in b/liblaunchpad-hydra.pc.in new file mode 100644 index 0000000..fae6cdd --- /dev/null +++ b/liblaunchpad-hydra.pc.in @@ -0,0 +1,13 @@ +# Package Information for pkg-config + +prefix=/usr +exec_prefix=@EXEC_PREFIX@ +libdir=@LIB_INSTALL_DIR@ +includedir=@INCLUDE_INSTALL_DIR@ + +Name: liblaunchpad-hydra +Description: launchpad hydra library for making other types of loader +Version: @VERSION@ +Requires: dlog libsystemd +Libs: -L${libdir} -llaunchpad-hydra +Cflags: -I${includedir} -I${includedir}/launchpad diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index 4a89322..406742a 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -144,9 +144,11 @@ ln -sf ../launchpad-process-pool.service %{buildroot}%{_unitdir_user}/basic.targ %manifest liblaunchpad.manifest %license LICENSE %attr(0644,root,root) %{_libdir}/liblaunchpad.so.* +%attr(0644,root,root) %{_libdir}/liblaunchpad-hydra.so.* %files -n liblaunchpad-devel %{_includedir}/launchpad/*.h %{_libdir}/*.so %{_libdir}/pkgconfig/liblaunchpad.pc +%{_libdir}/pkgconfig/liblaunchpad-hydra.pc diff --git a/src/launchpad.c b/src/launchpad.c index 2fc5c02..16dc627 100755 --- a/src/launchpad.c +++ b/src/launchpad.c @@ -38,15 +38,16 @@ #include #include -#include "perf.h" -#include "launchpad_common.h" -#include "launchpad_signal.h" #include "key.h" -#include "launchpad.h" -#include "loader_info.h" #include "launcher_info.h" -#include "launchpad_debug.h" +#include "launchpad.h" +#include "launchpad_common.h" #include "launchpad_config.h" +#include "launchpad_debug.h" +#include "launchpad_signal.h" +#include "launchpad_types.h" +#include "loader_info.h" +#include "perf.h" #define AUL_PR_NAME 16 #define EXEC_CANDIDATE_EXPIRED 5 diff --git a/src/launchpad_common.c b/src/launchpad_common.c index 5607c77..39a1a58 100644 --- a/src/launchpad_common.c +++ b/src/launchpad_common.c @@ -39,18 +39,16 @@ #include #include #include -#include #include #include "launchpad_common.h" +#include "launchpad_types.h" #include "key.h" #define MAX_PATH_LEN 1024 #define MAX_CMD_BUFSZ 1024 #define MAX_PENDING_CONNECTIONS 10 -#define CONNECT_RETRY_TIME (100 * 1000) -#define CONNECT_RETRY_COUNT 3 #define AUL_PKT_HEADER_SIZE (sizeof(int) + sizeof(int) + sizeof(int)) #define PATH_AMD_SOCK "/run/aul/daemons/.amd-sock" #define PATH_DEV_NULL "/dev/null" @@ -713,36 +711,6 @@ int _connect_to_launchpad(int type, int id) return fd; } -int _connect_to_launchpad_hydra(int type, int id) -{ - char path[PATH_MAX]; - int fd; - int send_ret; - pid_t client_pid; - - - _D("[hydra] enter, type: %d", type); - - snprintf(path, sizeof(path), "%s/daemons/%d/%s%d-%d", - SOCKET_PATH, getuid(), HYDRA_LOADER_SOCKET_NAME, - type, id); - fd = __create_client_socket(path); - if (fd < 0) - return -1; - - client_pid = getpid(); - send_ret = send(fd, &client_pid, sizeof(client_pid), MSG_NOSIGNAL); - _D("send(%d) : %d", client_pid, send_ret); - if (send_ret == -1) { - _E("send error"); - close(fd); - return -1; - } - - SECURE_LOGD("[hydra] done, connect fd: %d", fd); - return fd; -} - #ifdef TIZEN_FEATURE_SET_PERSONALITY_32 static void __set_execution_domain(void) { diff --git a/src/launchpad_debug.c b/src/launchpad_debug.c index 9b292f5..811e721 100644 --- a/src/launchpad_debug.c +++ b/src/launchpad_debug.c @@ -24,10 +24,11 @@ #include #include -#include "launchpad_common.h" -#include "launchpad_debug.h" #include "debugger_info.h" #include "key.h" +#include "launchpad_common.h" +#include "launchpad_debug.h" +#include "launchpad_types.h" #define DEBUGGER_INFO_PATH "/usr/share/aul" diff --git a/src/launchpad_hydra.c b/src/launchpad_hydra.c new file mode 100644 index 0000000..5d43b5d --- /dev/null +++ b/src/launchpad_hydra.c @@ -0,0 +1,455 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "launchpad_hydra.h" +#include "launchpad_types.h" +#include "log_private.h" + +#ifndef API +#define API __attribute__ ((visibility("default"))) +#endif + +typedef enum { + LAUNCHPAD_TYPE_UNSUPPORTED = -1, + LAUNCHPAD_TYPE_USER = 1, + LAUNCHPAD_TYPE_DYNAMIC = 100, + LAUNCHPAD_TYPE_MAX +} launchpad_type_e; + +typedef struct hydra_context_s { + sigset_t oldmask; + sd_event *event; + sd_event_source *fd_source; + sd_event_source *sig_source; + int signal_fd; + int client_fd; + int candidate_pid; + int argc; + char **argv; + hydra_lifecycle_callback_s *hydra_callbacks; + void *user_data; +} hydra_context_t; + +static hydra_context_t __context; + +static void __fini_hydra(void); + +static int __init_signal(void) +{ + sigset_t mask; + int sfd; + + _D("[__HYDRA__] init signal"); + sigemptyset(&mask); + sigaddset(&mask, SIGCHLD); + + if (sigprocmask(SIG_BLOCK, &mask, &__context.oldmask) < 0) + _E("sigprocmask() is failed. errno(%d)", errno); + else + _D("SIGCHLD blocked"); + + sfd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC); + if (sfd < 0) { + _E("Failed to create SIGCHLD fd. errno(%d)", errno); + return -1; + } + + return sfd; +} + +static void __fini_signal(void) +{ + _D("[__HYDRA__] finish signal"); + if (sigprocmask(SIG_SETMASK, &__context.oldmask, NULL) < 0) + _E("sigprocmask() is failed. errno(%d)", errno); + else + _D("SIGCHLD unblocked"); +} + +static int (*__security_manager_prepare_app_candidate)(void); +static int __load_security_manager_func(void) +{ +#define PATH_SECURITY_MANAGER_CLIENT "/usr/lib/libsecurity-manager-client.so.3" + void *handle; + + handle = dlopen(PATH_SECURITY_MANAGER_CLIENT, RTLD_LAZY | RTLD_LOCAL); + if (!handle) { + _E("Failed to open security manager client library. error(%s)", + dlerror()); + return -1; + } + + __security_manager_prepare_app_candidate = dlsym(handle, + "security_manager_prepare_app_candidate"); + if (!__security_manager_prepare_app_candidate) { + _E("Failed to load security_manager_prepare_app_candidate()"); + return -1; + } + + return 0; +} + +static int __fork_process(int (*child_fn)(void *), void *arg) +{ + int ret; + pid_t pid; + + pid = fork(); + if (pid < 0) { + _E("[__HYDRA__] Failed to create a child process. errno(%d)", + errno); + return pid; + } + + if (pid == 0) { + __load_security_manager_func(); + + if (__security_manager_prepare_app_candidate) { + _W("security_manager_prepare_app_candidate ++"); + ret = __security_manager_prepare_app_candidate(); + _W("security_manager_prepare_app_candidate --"); + if (ret != 0) { + _E("Failed to prepare app candidate process. error(%d)", + ret); + exit(1); + } + } + + ret = child_fn(arg); + _E("Failed to exec child process. errno(%d)", errno); + exit(ret); + } + + return pid; +} + +static int __run_loader(void *arg) +{ + int ret = 0; + + _D("[__HYDRA__] Run loader. pid(%d)", getpid()); + __fini_signal(); + + /* Set new sesssion ID & new process group ID */ + setsid(); + + launchpad_hydra_exit(); + __fini_hydra(); + + if (__context.hydra_callbacks->fork) { + ret = __context.hydra_callbacks->fork(__context.argc, + __context.argv, __context.user_data); + } + + return ret; +} + +static int __handle_launch_event(sd_event_source *s, + int fd, uint32_t revents, void *user_data) +{ + enum hydra_cmd cmd = -1; + int len; + +retry_recv: + len = recv(fd, &cmd, sizeof(cmd), MSG_WAITALL); + if (len < 0) { + if (errno == EINTR) + goto retry_recv; + } + + if (len < sizeof(cmd)) { + _E("[__HYDRA__] Failed to recv data. errno(%d)", errno); + goto err; + } + + if (cmd == LAUNCH_CANDIDATE) { + _D("[__HYDRA__] Launch new child"); + } else { + _E("[__HYDRA__] Unknown command(%d)", cmd); + goto err; + } + + __context.candidate_pid = __fork_process(__run_loader, NULL); + _D("[__HYDRA__] candidate process(%d)", __context.candidate_pid); + + return 0; +err: + __fini_hydra(); + exit(-1); + return -1; +} + +static int __process_sigchld(struct signalfd_siginfo *info) +{ + union sigval val; + int status; + pid_t child_pid; + pid_t child_pgid; + + child_pgid = getpgid(info->ssi_pid); + _D("[__HYDRA__] Dead pid(%d), pgid(%d), signo(%d), status(%d)", + info->ssi_pid, child_pgid, info->ssi_signo, + info->ssi_status); + + while ((child_pid = waitpid(-1, &status, WNOHANG)) > 0) { + if (child_pid == child_pgid) + killpg(child_pgid, SIGKILL); + + val.sival_int = child_pid; + sigqueue(getppid(), SIGCHLD, val); + } + + return 0; +} + +static int __handle_sigchld_event(sd_event_source *s, + int fd, uint32_t revents, void *user_data) +{ + struct signalfd_siginfo siginfo; + ssize_t size; + + do { + size = read(fd, &siginfo, sizeof(struct signalfd_siginfo)); + if (size == 0) + break; + + if (size != sizeof(struct signalfd_siginfo)) + break; + + __process_sigchld(&siginfo); + } while (size > 0); + + return 0; +} + +static int __create_client_socket(const char *path) +{ + struct sockaddr_un addr = { 0, }; + int retry = CONNECT_RETRY_COUNT; + int fd; + + fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + if (fd < 0) { + _E("Failed to create socket(%s). errno(%d)", path, errno); + return -1; + } + + addr.sun_family = AF_UNIX; + snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path); + while (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + if (errno != ETIMEDOUT || retry <= 0) { + _E("Failed to connect socket(%s). errno(%d)", + path, errno); + close(fd); + return -1; + } + + usleep(CONNECT_RETRY_TIME); + retry--; + _W("Retry(%d) to connect %s", retry, path); + } + + return fd; +} + +int __connect_to_launchpad_hydra(int type, int id) +{ + char path[PATH_MAX]; + int fd; + int send_ret; + pid_t client_pid; + + + _D("[hydra] enter, type: %d", type); + + snprintf(path, sizeof(path), "%s/daemons/%d/%s%d-%d", + SOCKET_PATH, getuid(), HYDRA_LOADER_SOCKET_NAME, + type, id); + fd = __create_client_socket(path); + if (fd < 0) + return -1; + + client_pid = getpid(); + send_ret = send(fd, &client_pid, sizeof(client_pid), MSG_NOSIGNAL); + _D("send(%d) : %d", client_pid, send_ret); + if (send_ret == -1) { + _E("send error"); + close(fd); + return -1; + } + + SECURE_LOGD("[hydra] done, connect fd: %d", fd); + return fd; +} + +static int __init_hydra(int loader_type, int loader_id) +{ + int ret; + + _D("[__HYDRA__] init hydra"); + __context.signal_fd = __init_signal(); + if (__context.signal_fd < 0) { + _E("Failed to initialize signal"); + return -1; + } + + __context.client_fd = __connect_to_launchpad_hydra(loader_type, + loader_id); + if (__context.client_fd < 0) { + _E("Failed to connect to launchpad"); + return -1; + } + + ret = sd_event_default(&__context.event); + if (ret < 0) { + _E("Failed to create default sd event. error(%d)", ret); + return ret; + } + + sd_event_add_io(__context.event, &__context.fd_source, + __context.client_fd, EPOLLIN, + __handle_launch_event, NULL); + sd_event_add_io(__context.event, &__context.sig_source, + __context.signal_fd, EPOLLIN, + __handle_sigchld_event, NULL); + + return 0; +} + +static void __fini_hydra(void) +{ + _D("[__HYDRA__] finish hydra"); + if (__context.sig_source) + sd_event_source_unref(__context.sig_source); + + if (__context.fd_source) + sd_event_source_unref(__context.fd_source); + + if (__context.event) + sd_event_unref(__context.event); + + if (__context.client_fd > 0) + close(__context.client_fd); + + if (__context.signal_fd > 0) + close(__context.signal_fd); +} + +static void __run_loop(void) +{ + int ret; + + ret = sd_event_loop(__context.event); + if (ret < 0) + _E("Failed to run sd event loop. error(%d)", ret); + + _D("[__HYDRA__] Run main loop"); +} + +static void __exit_loop(void) +{ + if (__context.event) + sd_event_exit(__context.event, 0); + + _D("[__HYDRA__] Exit main loop"); +} + +API int launchpad_hydra_main(int argc, char **argv, + hydra_lifecycle_callback_s *hydra_callbacks, + void *user_data) +{ + int loader_type; + int loader_id; + int is_hydra; + int ret = 0; + + if (argc < 4) { + _E("[__HYDRA__] too few argument"); + return -EINVAL; + } + + loader_type = argv[LOADER_ARG_TYPE][0] - '0'; + if (loader_type < 0 || loader_type >= LAUNCHPAD_TYPE_MAX) { + _E("[__HYDRA__] Invalid argument. type(%d)", loader_type); + return -EINVAL; + } + + if (!hydra_callbacks) { + _E("[__HYDRA__] Invalid argument"); + return -EINVAL; + } + + is_hydra = argv[LOADER_ARG_HYDRA][0] - '0'; + _D("[__HYDRA__] mode: %d", is_hydra); + if (!is_hydra) { + _W("Run in non hydra mode"); + return -EINVAL; + } + + argv[LOADER_ARG_HYDRA] = "0"; + loader_id = atoi(argv[LOADER_ARG_ID]); + + __context.argc = argc; + __context.argv = argv; + __context.hydra_callbacks = hydra_callbacks; + __context.user_data = user_data; + + ret = __init_hydra(loader_type, loader_id); + if (ret < 0) { + _E("Failed to initialize hydra loader"); + return ret; + } + + if (__context.hydra_callbacks->precreate) + __context.hydra_callbacks->precreate(user_data); + + if (__context.hydra_callbacks->create) + __context.hydra_callbacks->create(__context.user_data); + + __context.candidate_pid = __fork_process(__run_loader, NULL); + _D("[__HYDRA__] candidate process(%d)", __context.candidate_pid); + + __run_loop(); + + if (__context.hydra_callbacks->terminate) + ret = __context.hydra_callbacks->terminate(__context.user_data); + + __fini_hydra(); + + return ret; +} + +API void launchpad_hydra_exit(void) +{ + __exit_loop(); +} diff --git a/src/launchpad_lib.c b/src/launchpad_lib.c index 6441104..118f561 100644 --- a/src/launchpad_lib.c +++ b/src/launchpad_lib.c @@ -33,8 +33,9 @@ #include #include -#include "launchpad_common.h" #include "launchpad.h" +#include "launchpad_common.h" +#include "launchpad_types.h" #include "preexec.h" #ifndef API @@ -43,7 +44,6 @@ #define AUL_PR_NAME 16 -static hydra_lifecycle_callback_s *__hydra_callbacks; static loader_lifecycle_callback_s *__loader_callbacks; static loader_adapter_s *__loader_adapter; static void *__loader_user_data; @@ -52,10 +52,7 @@ static char **__argv; static bundle *__bundle; static int __loader_type = LAUNCHPAD_TYPE_UNSUPPORTED; static int __loader_id; -static pid_t __candidate_pid = -1; -static struct sigaction __prev_sigchld; static bool __loop_quit; -static bool __is_candidate = false; static void __at_exit_to_release_bundle(void) { @@ -315,85 +312,6 @@ static void __receiver_cb(int fd) } } -static void __hydra_receiver_cb(int fd) -{ - char err_str[MAX_LOCAL_BUFSZ] = { 0, }; - enum hydra_cmd cmd = -1; - int len; - int ret; - pid_t pid; - - _D("[hydra] ECORE_FD_READ"); - -retry_recv: - len = recv(fd, &cmd, sizeof(cmd), MSG_WAITALL); - if (len < 0) - if (errno == EINTR) - goto retry_recv; - - if (len < sizeof(cmd)) { - _E("[hydra] failed to recv: %s", - strerror_r(errno, err_str, sizeof(err_str))); - goto err; - } - - _D("[hydra] success recv cmd: %d", cmd); - - switch (cmd) { - case LAUNCH_CANDIDATE: - _D("[hydra] launch new child"); - break; - default: - _E("[hydra] unknown command from launchpad: %d", cmd); - goto err; - } - - pid = fork(); - if (pid < 0) { - _E("[hydra] unable to fork: %s", - strerror_r(errno, err_str, sizeof(err_str))); - } else if (pid > 0) { - SECURE_LOGD("[hydra] forked new candidate with pid=%d", pid); - - __candidate_pid = pid; - __is_candidate = false; - - return; - } else { - __is_candidate = true; - - _W("security_manager_prepare_app_candidate ++"); - ret = security_manager_prepare_app_candidate(); - _W("security_manager_prepare_app_candidate --"); - if (ret != SECURITY_MANAGER_SUCCESS) { - _E("Failed to prepare app candidate process (%d)", ret); - exit(1); - } - - if (sigaction(SIGCHLD, &__prev_sigchld, NULL)) { - _E("[hydra] sigaction failed: %s", - strerror_r(errno, err_str, sizeof(err_str))); - exit(-1); - } - - if (__hydra_callbacks->fork) - __hydra_callbacks->fork(__loader_user_data); - - /* child, exit loop and start initialization */ - __loader_adapter->remove_fd(__loader_user_data, fd); - close(fd); - - __loader_adapter->loop_quit(__loader_user_data); - - return; - } - -err: - __loader_adapter->remove_fd(__loader_user_data, fd); - close(fd); - exit(-1); -} - static void __update_lang(keynode_t *node, void *user_data) { char *lang = vconf_keynode_get_str(node); @@ -469,34 +387,6 @@ bundle *launchpad_loader_get_bundle() return __bundle; } -static void sigchld_hdl(int code, siginfo_t *siginfo, void *context) -{ - pid_t child_pid; - union sigval val; - bool is_group_leader = !kill(-siginfo->si_pid, 0); - - while ((child_pid = waitpid(-1, NULL, WNOHANG)) > 0) { - /* sigqueue to launchpad getppid() with data=child_pid */ - if (child_pid == __candidate_pid) - __candidate_pid = -1; - - if (is_group_leader) - kill(-child_pid, SIGKILL); - - val.sival_int = child_pid; - sigqueue(getppid(), SIGCHLD, val); - } - - if (__prev_sigchld.sa_flags & SA_SIGINFO) { - if (__prev_sigchld.sa_sigaction) - __prev_sigchld.sa_sigaction(code, siginfo, context); - } else if (__prev_sigchld.sa_handler && - __prev_sigchld.sa_handler != SIG_IGN && - __prev_sigchld.sa_handler != SIG_DFL) { - __prev_sigchld.sa_handler(code); - } -} - API int launchpad_loader_main(int argc, char **argv, loader_lifecycle_callback_s *callbacks, loader_adapter_s *adapter, void *user_data) @@ -565,153 +455,3 @@ API int launchpad_loader_set_priority(int prio) { return _set_priority(prio); } - -API int launchpad_hydra_main(int argc, char **argv, - hydra_lifecycle_callback_s *hydra_callbacks, - loader_lifecycle_callback_s *callbacks, - loader_adapter_s *adapter, void *user_data) -{ - char err_str[MAX_LOCAL_BUFSZ] = { 0, }; - int is_hydra; - int loader_type; - int loader_id; - int client_fd; - int r = -1; - pid_t pid; - struct sigaction new_act; - - if (argc < 4) { - _E("[hydra] too few argument."); - return -1; - } - - is_hydra = argv[LOADER_ARG_HYDRA][0] - '0'; - argv[LOADER_ARG_HYDRA] = "0"; - _D("[hydra] mode: %d", is_hydra); - - loader_type = argv[LOADER_ARG_TYPE][0] - '0'; - if (loader_type < 0 || loader_type >= LAUNCHPAD_TYPE_MAX) { - _E("[hydra] invalid argument. (type: %d)", loader_type); - return -1; - } - - loader_id = atoi(argv[LOADER_ARG_ID]); - - if (hydra_callbacks == NULL) { - _E("[hydra] invalid argument. hydra_callback is null"); - return -1; - } - - if (adapter == NULL) { - _E("[hydra] invalid argument. adapter is null"); - return -1; - } - - if (adapter->loop_begin == NULL || adapter->loop_quit == NULL - || adapter->add_fd == NULL || adapter->remove_fd == NULL) { - _E("[hydra] invalid argument. adapter callback is null"); - return -1; - } - - if (hydra_callbacks->precreate) - hydra_callbacks->precreate(user_data); - - if (!is_hydra) { - _D("Run in non hydra mode"); - return launchpad_loader_main(argc, argv, callbacks, - adapter, user_data); - } - - if (hydra_callbacks->create) - hydra_callbacks->create(user_data); - - /* Set sigchld handler after calling create, because it can overwrite */ - /* our handler */ - memset(&new_act, 0, sizeof(new_act)); - new_act.sa_sigaction = sigchld_hdl; - new_act.sa_flags |= SA_SIGINFO; - - if (sigaction(SIGCHLD, &new_act, &__prev_sigchld)) { - _E("[hydra] sigaction failed: %s", - strerror_r(errno, err_str, sizeof(err_str))); - return -1; - } - - /* initial fork to prepare first loader */ - _D("[hydra] initial fork"); - - pid = fork(); - if (pid < 0) { - _E("[hydra] unable to fork: %s", - strerror_r(errno, err_str, sizeof(err_str))); - return -1; - } else if (pid == 0) { - _W("security_manager_prepare_app_candidate ++"); - r = security_manager_prepare_app_candidate(); - _W("security_manager_prepare_app_candidate --"); - if (r != SECURITY_MANAGER_SUCCESS) { - _E("Failed to prepare app candidate process (%d)", r); - exit(1); - } - - if (sigaction(SIGCHLD, &__prev_sigchld, NULL)) { - _E("[hydra] sigaction failed: %s", - strerror_r(errno, err_str, sizeof(err_str))); - return -1; - } - - if (hydra_callbacks->fork) - hydra_callbacks->fork(user_data); - - r = launchpad_loader_main(argc, argv, callbacks, adapter, user_data); - - if (r != 0) - _E("[hydra] launchpad_loader_main failed. Error: %d", r); - - return r; - } else { - __hydra_callbacks = hydra_callbacks; - __loader_callbacks = callbacks; - __loader_adapter = adapter; - __loader_user_data = user_data; - __candidate_pid = pid; - __argc = argc; - __argv = argv; - - __preexec_init(argc, argv); - - /* Set new session ID & new process group ID*/ - /* In linux, child can set new session ID without check permission */ - /* TODO : should be add to check permission in the kernel*/ - setsid(); - - malloc_trim(0); - - client_fd = _connect_to_launchpad_hydra(loader_type, loader_id); - if (client_fd == -1) { - _D("[hydra] connecting to launchpad process was failed."); - return -1; - } - - __loader_adapter->add_fd(__loader_user_data, client_fd, - __hydra_receiver_cb); - - __loader_adapter->loop_begin(__loader_user_data); - - /* At this point, either end of hydra process or start of candidate process main loop */ - if (__hydra_callbacks->terminate) - r = __hydra_callbacks->terminate(__loader_user_data); - - if (__is_candidate) { - r = launchpad_loader_main(__argc, __argv, __loader_callbacks, - __loader_adapter, __loader_user_data); - - if (r != 0) - _E("[hydra] launchpad_loader_main failed. Error: %d", r); - } - - return r; - } - - return 0; -} diff --git a/src/launchpad_loader.c b/src/launchpad_loader.c index afc6c28..4dc371e 100644 --- a/src/launchpad_loader.c +++ b/src/launchpad_loader.c @@ -29,6 +29,7 @@ #include #include "launchpad_common.h" +#include "launchpad_types.h" #include "launchpad.h" #include "key.h" diff --git a/src/log_private.h b/src/log_private.h new file mode 100644 index 0000000..f214b78 --- /dev/null +++ b/src/log_private.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * + * 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 __LOG_PRIVATE_H__ +#define __LOG_PRIVATE_H__ + +#include + +#ifdef LOG_TAG +#undef LOG_TAG +#endif +#define LOG_TAG "LAUNCHPAD" + +#define _E(fmt, arg...) LOGE(fmt, ##arg) +#define _D(fmt, arg...) LOGD(fmt, ##arg) +#define _W(fmt, arg...) LOGW(fmt, ##arg) +#define _I(fmt, arg...) LOGI(fmt, ##arg) + +#endif /* __LOG_PRIVATE_H__ */ -- 2.7.4 From 2226f5c1880661e5c26ccd42cdc3a8547d8fe982 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 11 Nov 2019 09:47:51 +0900 Subject: [PATCH 15/16] Release version 0.10.0 Changes: - Refactor Launchpad Hydra Loader Change-Id: I93e611f010745e3efbe6f23f6428a75cf85b7596 Signed-off-by: Hwankyu Jhun --- packaging/launchpad.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index 406742a..ae7f379 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.9.6 +Version: 0.10.0 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From ead9132d51e8ec67e818b478d4fb252dcb36c2a3 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 15 Nov 2019 11:24:32 +0900 Subject: [PATCH 16/16] Support prelink feature If the `_prelink_enable` is defined, launchpad-process-pool and launchpad-loader will be compiled without -pie and -fPIE option. Change-Id: I91c2743b781121b1862d4b567e875c0d4da62943 Signed-off-by: Hwankyu Jhun --- CMakeLists.txt | 18 ++++++++++++++++++ packaging/launchpad.spec | 11 +++++++++++ 2 files changed, 29 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index e338b05..ad32426 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -74,8 +74,16 @@ SET(EXTRA_CFLAGS_common "${EXTRA_CFLAGS_common} -fdata-sections -ffunction-secti SET(EXTRA_CFLAGS_common "${EXTRA_CFLAGS_common} -D_FILE_OFFSET_BITS=64") SET(EXTRA_CFLAGS_common "${EXTRA_CFLAGS_common} -Werror") +IF(_TIZEN_FEATURE_PRELINK) +MESSAGE(STATUS "[__PRELINK__] Enable") +SET(EXTRA_CFLAGS_pool "${EXTRA_CFLAGS_pool} ${EXTRA_CFLAGS_common}") +SET(EXTRA_CFLAGS_loader "${EXTRA_CFLAGS_loader} ${EXTRA_CFLAGS_common}") +ELSE(_TIZEN_FEATURE_PRELINK) +MESSAGE(STATUS "[__PRELINK__] Disable") SET(EXTRA_CFLAGS_pool "${EXTRA_CFLAGS_pool} ${EXTRA_CFLAGS_common} -fPIE") SET(EXTRA_CFLAGS_loader "${EXTRA_CFLAGS_loader} ${EXTRA_CFLAGS_common} -fPIE") +ENDIF(_TIZEN_FEATURE_PRELINK) + SET(EXTRA_CFLAGS_lib "${EXTRA_CFLAGS_lib} ${EXTRA_CFLAGS_common}") SET(EXTRA_CFLAGS_hydra "${EXTRA_CFLAGS_hydra} ${EXTRA_CFLAGS_common}") @@ -114,7 +122,13 @@ ADD_EXECUTABLE(${LAUNCHPAD_LOADER} ${${LAUNCHPAD_LOADER}_SOURCE_FILES}) # Since we cannot set LD_LIBRARY_PATH directly by security issue, we make the # dynamic linker looks in the CWD forcely. TARGET_LINK_LIBRARIES(${LAUNCHPAD_LOADER} "-ldl -Wl,-rpath,: -Wl,--disable-new-dtags") + +IF(_TIZEN_FEATURE_PRELINK) +TARGET_LINK_LIBRARIES(${LAUNCHPAD_LOADER} ${${this_target_loader}_LDFLAGS}) +ELSE(_TIZEN_FEATURE_PRELINK) TARGET_LINK_LIBRARIES(${LAUNCHPAD_LOADER} ${${this_target_loader}_LDFLAGS} "-pie") +ENDIF(_TIZEN_FEATURE_PRELINK) + SET_TARGET_PROPERTIES(${LAUNCHPAD_LOADER} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_loader}) SET_TARGET_PROPERTIES(${LAUNCHPAD_LOADER} PROPERTIES SKIP_BUILD_RPATH TRUE @@ -135,7 +149,11 @@ SET(${LAUNCHPAD_PROCESS_POOL}_SOURCE_FILES ) ADD_EXECUTABLE(${LAUNCHPAD_PROCESS_POOL} ${${LAUNCHPAD_PROCESS_POOL}_SOURCE_FILES}) +IF(_TIZEN_FEATURE_PRELINK) +TARGET_LINK_LIBRARIES(${LAUNCHPAD_PROCESS_POOL} ${${this_target_pool}_LDFLAGS} "-lm") +ELSE(_TIZEN_FEATURE_PRELINK) TARGET_LINK_LIBRARIES(${LAUNCHPAD_PROCESS_POOL} ${${this_target_pool}_LDFLAGS} "-pie -lm") +ENDIF(_TIZEN_FEATURE_PRELINK) SET_TARGET_PROPERTIES(${LAUNCHPAD_PROCESS_POOL} PROPERTIES COMPILE_FLAGS ${EXTRA_CFLAGS_pool}) SET_TARGET_PROPERTIES(${LAUNCHPAD_PROCESS_POOL} PROPERTIES SKIP_BUILD_RPATH TRUE diff --git a/packaging/launchpad.spec b/packaging/launchpad.spec index ae7f379..89b88b4 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -44,6 +44,13 @@ Obsoletes: amd-mod-launchpad %define tizen_arch32 0 %endif + +%if "%{?_prelink_enable}" == "y" +%define tizen_feature_prelink 1 +%else +%define tizen_feature_prelink 0 +%endif + %description Launchpad for launching applications @@ -95,6 +102,9 @@ _TIZEN_FEATURE_LOADER_PRIORITY=ON %if 0%{?tizen_arch32} _TIZEN_FEATURE_SET_PERSONALITY_32=ON %endif +%if 0%{?tizen_feature_prelink} +_TIZEN_FEATURE_PRELINK=ON +%endif MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` %cmake -DVERSION=%{version} \ @@ -102,6 +112,7 @@ MAJORVER=`echo %{version} | awk 'BEGIN {FS="."}{print $1}'` -D_TIZEN_FEATURE_PRIORITY_CHANGE:BOOL=${_TIZEN_FEATURE_PRIORITY_CHANGE} \ -D_TIZEN_FEATURE_LOADER_PRIORITY:BOOL=${_TIZEN_FEATURE_LOADER_PRIORITY} \ -D_TIZEN_FEATURE_SET_PERSONALITY_32:BOOL=${_TIZEN_FEATURE_SET_PERSONALITY_32} \ + -D_TIZEN_FEATURE_PRELINK:BOOL=${_TIZEN_FEATURE_PRELINK} \ . %__make %{?_smp_mflags} -- 2.7.4