From b0e0837d9824a004e753bab00c811fd08aa14daf Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 8 Oct 2019 08:29:41 +0900 Subject: [PATCH 01/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 02/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 03/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 04/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 05/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 06/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 07/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 08/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 09/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 10/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 From 42c0e226cfd1128a32100ea6b6fa999842607342 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 15 Nov 2019 12:22:57 +0900 Subject: [PATCH 11/16] Release version 0.10.1 Changes: - Support prelink feature Change-Id: I8c6c1b11f1e6541cd78a37b44b1818e25a52373f 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 89b88b4..0deb0e4 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.10.0 +Version: 0.10.1 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From 464357174a33d96b8ded3c48080c083cc73e3f14 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 20 Dec 2019 10:17:04 +0900 Subject: [PATCH 12/16] Use monotonic time To measure launching time properly, we should use monotonic time. Requires: - https://review.tizen.org/gerrit/#/c/platform/core/appfw/aul-1/+/220595/ - https://review.tizen.org/gerrit/#/c/platform/core/appfw/amd/+/220598/ - https://review.tizen.org/gerrit/#/c/platform/core/appfw/launchpad/+/220600/ Change-Id: I3df67a01234fcd5cb54248bbfc0519d9564a08d6 Signed-off-by: Hwankyu Jhun --- inc/perf.h | 58 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/inc/perf.h b/inc/perf.h index 3bc169f..ca87d12 100644 --- a/inc/perf.h +++ b/inc/perf.h @@ -19,38 +19,38 @@ #ifdef PERF_ACTIVATE -#include -static struct timeval __g_base_time = { +#include + +static struct timespec __g_base_time = { .tv_sec = 0, - .tv_usec = 0 + .tv_nsec = 0 }; -#define INIT_PERF(kb) \ - do { \ - const char *tmp; \ - struct timeval tv; \ - tmp = bundle_get_val(kb, AUL_K_STARTTIME); \ - if (tmp != NULL) \ - sscanf(tmp, "%ld/%ld", &tv.tv_sec, &tv.tv_usec); \ - else \ - gettimeofday(&tv, NULL); \ - __g_base_time.tv_sec = tv.tv_sec; \ - __g_base_time.tv_usec = tv.tv_usec; \ - } while (0) - -#define PERF(fmt, arg...) \ - do { \ - struct timeval cur; \ - struct timeval res; \ - gettimeofday(&cur, NULL); \ - if (__g_base_time.tv_sec != 0) { \ - timersub(&cur, &__g_base_time, &res); \ - printf("%c[1;31m[%s,%d] %ld sec %ld msec "fmt \ - " %c[0m\n", 27, __func__, \ - __LINE__, res.tv_sec, \ - res.tv_usec/1000, ##arg, 27);\ - } \ - } while (0) +#define INIT_PERF(kb) do { \ + const char *tmp; \ + struct timespec tv; \ + tmp = bundle_get_val(kb, AUL_K_STARTTIME); \ + if (tmp != NULL) \ + sscanf(tmp, "%ld/%ld", &tv.tv_sec, &tv.tv_nsec); \ + else \ + clock_gettime(CLOCK_MONOTONIC, &tv); \ + __g_base_time.tv_sec = tv.tv_sec; \ + __g_base_time.tv_nsec = tv.tv_nsec; \ +} while (0) + +#define PERF(fmt, arg...) do { \ + struct timespec cur; \ + struct timespec res; \ + clock_gettime(CLOCK_MONOTONIC, &cur); \ + if (__g_base_time.tv_sec != 0) { \ + res->tv_sec = cur.tv_sec - __g_base_time.tv_sec; \ + res->tv_nsec = cur.tv_nsec - __g_base_time.tv_nsec; \ + printf("%c[1;31m[%s,%d] %ld sec %ld msec "fmt \ + " %c[0m\n", 27, __func__, \ + __LINE__, res.tv_sec, \ + res.tv_nsec / 1e6, ##arg, 27); \ + } \ +} while (0) #else -- 2.7.4 From 91c66de283a78423238d5a9364c7814a5026e529 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Fri, 20 Dec 2019 13:45:12 +0900 Subject: [PATCH 13/16] Release version 0.10.2 Changes: - Use monotonic time Change-Id: Ie2c454ff5823f8b94db0b88dffff73c8f059b2f2 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 0deb0e4..1581432 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.10.1 +Version: 0.10.2 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From dc5bfa56676c513bba15da0d2b3f324ca01632f8 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 30 Dec 2019 14:26:20 +0900 Subject: [PATCH 14/16] Remove compile warning messages Change-Id: I94eca9e33a0776784ae0cae1a52c5781eff84ce1 Signed-off-by: Hwankyu Jhun --- src/launchpad_common.c | 2 +- src/launchpad_hydra.c | 7 ++++++- src/launchpad_signal.c | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/launchpad_common.c b/src/launchpad_common.c index 39a1a58..26fce8b 100644 --- a/src/launchpad_common.c +++ b/src/launchpad_common.c @@ -1383,7 +1383,7 @@ static int __send_raw(int fd, int cmd, unsigned char *data, int datalen) int _send_message_to_logger(const char *tag, const char *format, ...) { - char fmt[PATH_MAX]; + char fmt[PATH_MAX - 256]; char buf[PATH_MAX]; va_list ap; int ret; diff --git a/src/launchpad_hydra.c b/src/launchpad_hydra.c index 5d43b5d..7ffb5bd 100644 --- a/src/launchpad_hydra.c +++ b/src/launchpad_hydra.c @@ -258,6 +258,11 @@ static int __create_client_socket(const char *path) int retry = CONNECT_RETRY_COUNT; int fd; + if (sizeof(addr.sun_path) <= strlen(path)) { + _E("lenght of path is too long"); + return -1; + } + fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); if (fd < 0) { _E("Failed to create socket(%s). errno(%d)", path, errno); @@ -265,7 +270,7 @@ static int __create_client_socket(const char *path) } addr.sun_family = AF_UNIX; - snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", path); + strncpy(addr.sun_path, path, sizeof(addr.sun_path) - strlen(path) - 1); while (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { if (errno != ETIMEDOUT || retry <= 0) { _E("Failed to connect socket(%s). errno(%d)", diff --git a/src/launchpad_signal.c b/src/launchpad_signal.c index e6a6503..8dbf565 100644 --- a/src/launchpad_signal.c +++ b/src/launchpad_signal.c @@ -128,7 +128,7 @@ static void __socket_garbage_collector(void) { DIR *dp; struct dirent *dentry = NULL; - char tmp[MAX_LOCAL_BUFSZ]; + char tmp[PATH_MAX]; snprintf(tmp, sizeof(tmp), "/run/aul/apps/%d", getuid()); dp = opendir(tmp); @@ -139,7 +139,7 @@ static void __socket_garbage_collector(void) if (!isdigit(dentry->d_name[0])) continue; - snprintf(tmp, MAX_LOCAL_BUFSZ, "/proc/%s", dentry->d_name); + snprintf(tmp, sizeof(tmp), "/proc/%s", dentry->d_name); if (access(tmp, F_OK) < 0) { /* Flawfinder: ignore */ _delete_sock_path(atoi(dentry->d_name), getuid()); continue; -- 2.7.4 From 7cf6d2936cb0ce9098a10c3364b517f7b02905a3 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 31 Dec 2019 09:14:46 +0900 Subject: [PATCH 15/16] Fix wrong implementation Change-Id: Ie65ecbb277f13df6102236748d8709e7a4ff2090 Signed-off-by: Hwankyu Jhun --- src/launchpad_hydra.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/launchpad_hydra.c b/src/launchpad_hydra.c index 7ffb5bd..f2c7779 100644 --- a/src/launchpad_hydra.c +++ b/src/launchpad_hydra.c @@ -270,7 +270,8 @@ static int __create_client_socket(const char *path) } addr.sun_family = AF_UNIX; - strncpy(addr.sun_path, path, sizeof(addr.sun_path) - strlen(path) - 1); + strncpy(addr.sun_path, path, sizeof(addr.sun_path)); + addr.sun_path[sizeof(addr.sun_path) - 1] = '\0'; while (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) { if (errno != ETIMEDOUT || retry <= 0) { _E("Failed to connect socket(%s). errno(%d)", -- 2.7.4 From 494b322f06e7f29ea06fb6a8def8fc0435ef4674 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Tue, 31 Dec 2019 08:07:14 +0900 Subject: [PATCH 16/16] Release version 0.10.3 Changes: - Remove compile warning messages - Fix wrong implementation Change-Id: I67c9ece883875cbb7579110812ac84df1a8f145b 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 1581432..f1cc49e 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.10.2 +Version: 0.10.3 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4