From 856e301a7ae4850efde31feb2b7ba2c32b694b49 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Mon, 14 Oct 2019 17:18:04 +0900 Subject: [PATCH 01/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 02/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 03/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 04/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 05/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 06/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 07/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 08/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 09/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 10/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 11/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 12/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 From 24f7e3ba66036cd1f26b9c98ca989e91fb08834a Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 22 Jan 2020 09:45:28 +0900 Subject: [PATCH 13/16] Fix type The return value type of iniparser_getstring() is changed to "const char *". Change-Id: I85ad74f7019d6fdc9f861e894e29fd81263e2da6 Signed-off-by: Hwankyu Jhun --- src/launchpad_config.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/launchpad_config.c b/src/launchpad_config.c index 5c459e8..8c74693 100644 --- a/src/launchpad_config.c +++ b/src/launchpad_config.c @@ -84,7 +84,7 @@ int _config_get_int_value(config_type_e type) return value; } -static char *__get_string_value(dictionary *d, const char *tag, +static const char *__get_string_value(dictionary *d, const char *tag, const char *key) { char buf[128]; @@ -106,7 +106,7 @@ int _config_init(void) { dictionary *d; char *val; - char *str; + const char *str; int ret; _D("config init"); -- 2.7.4 From 96f0974c960adf8e6b0c79ac59e999fd794ee498 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 22 Jan 2020 09:51:45 +0900 Subject: [PATCH 14/16] Release version 0.10.4 Changes: - Fix type Change-Id: I20100e2f21d6b708e4199703bd9fd0764e12681c 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 f1cc49e..0077851 100644 --- a/packaging/launchpad.spec +++ b/packaging/launchpad.spec @@ -1,6 +1,6 @@ Name: launchpad Summary: Launchpad for launching applications -Version: 0.10.3 +Version: 0.10.4 Release: 1 Group: Application Framework/Daemons License: Apache-2.0 -- 2.7.4 From b772f01c490f3769e00b5cd2b20af4e97965547a Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Wed, 22 Jan 2020 17:13:13 +0900 Subject: [PATCH 15/16] Fix static anlysis issue Change-Id: I8672a904fae3b77f158b4955f0383b76465d468b Signed-off-by: Hwankyu Jhun --- src/launchpad.c | 111 ++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 88 insertions(+), 23 deletions(-) diff --git a/src/launchpad.c b/src/launchpad.c index 16dc627..e751fbb 100755 --- a/src/launchpad.c +++ b/src/launchpad.c @@ -105,6 +105,8 @@ typedef struct { guint live_timer; int state; bool is_hydra; + guint pollfd; + guint hydra_pollfd; } candidate_process_context_t; typedef struct { @@ -2076,7 +2078,27 @@ end: return G_SOURCE_CONTINUE; } -static candidate_process_context_t *__add_slot(int type, int loader_id, +static void __destroy_slot(candidate_process_context_t *cpc) +{ + if (!cpc) + return; + + if (cpc->hydra_pollfd) + g_source_remove(cpc->hydra_pollfd); + + if (cpc->pollfd) + g_source_remove(cpc->pollfd); + + if (cpc->loader_extra) + free(cpc->loader_extra); + + if (cpc->loader_path) + free(cpc->loader_path); + + free(cpc); +} + +static candidate_process_context_t *__create_slot(int type, int loader_id, int caller_pid, const char *loader_path, const char *loader_extra, int detection_method, int activation_method, int deactivation_method, @@ -2085,16 +2107,27 @@ static candidate_process_context_t *__add_slot(int type, int loader_id, bool on_boot, bool app_exists, bool is_hydra) { candidate_process_context_t *cpc; - int fd = -1; - guint pollfd; - if (__find_slot(type, loader_id) != NULL) + cpc = calloc(1, sizeof(candidate_process_context_t)); + if (cpc == NULL) { + _E("Out of memory"); return NULL; + } - cpc = (candidate_process_context_t *)malloc( - sizeof(candidate_process_context_t)); - if (cpc == NULL) + cpc->loader_path = strdup(loader_path); + if (cpc->loader_path == NULL) { + _E("Failed to duplicate loader path(%s)", loader_path); + __destroy_slot(cpc); return NULL; + } + + cpc->loader_extra = loader_extra ? strdup(loader_extra) : strdup(""); + if (cpc->loader_extra == NULL) { + _E("Failed to duplicate loader extra(%s)", + loader_extra ? loader_extra : "null"); + __destroy_slot(cpc); + return NULL; + } cpc->type = type; cpc->prepared = false; @@ -2107,8 +2140,6 @@ static candidate_process_context_t *__add_slot(int type, int loader_id, cpc->last_exec_time = 0; cpc->source = 0; cpc->timer = 0; - cpc->loader_path = strdup(loader_path); - cpc->loader_extra = loader_extra ? strdup(loader_extra) : strdup(""); cpc->detection_method = detection_method; cpc->timeout_val = timeout_val; cpc->cpu_total_time = 0; @@ -2132,12 +2163,42 @@ static candidate_process_context_t *__add_slot(int type, int loader_id, else cpc->state = CANDIDATE_PROCESS_STATE_RUNNING; + return cpc; +} + +static candidate_process_context_t *__add_slot(int type, int loader_id, + int caller_pid, const char *loader_path, + const char *loader_extra, int detection_method, + int activation_method, int deactivation_method, + unsigned int ttl, int timeout_val, + int threshold_max, int threshold_min, + bool on_boot, bool app_exists, bool is_hydra) +{ + candidate_process_context_t *cpc; + int fd; + guint pollfd; + int hydra_fd; + guint hydra_pollfd; + + if (__find_slot(type, loader_id) != NULL) + return NULL; + + cpc = __create_slot(type, loader_id, + caller_pid, loader_path, + loader_extra, detection_method, + activation_method, deactivation_method, + ttl, timeout_val, + threshold_max, threshold_min, + on_boot, app_exists, is_hydra); + if (cpc == NULL) + return NULL; + fd = __listen_candidate_process(cpc->type, cpc->loader_id); if (fd == -1) { _E("[launchpad] Listening the socket to " \ "the type %d candidate process failed.", cpc->type); - free(cpc); + __destroy_slot(cpc); return NULL; } @@ -2145,29 +2206,37 @@ static candidate_process_context_t *__add_slot(int type, int loader_id, cpc->type, cpc->loader_id); if (pollfd == 0) { close(fd); - free(cpc); + __destroy_slot(cpc); return NULL; } + cpc->pollfd = pollfd; + if (is_hydra) { - fd = __listen_hydra_process(cpc->type, cpc->loader_id); - if (fd == -1) { + hydra_fd = __listen_hydra_process(cpc->type, cpc->loader_id); + if (hydra_fd == -1) { _E("[launchpad] Listening the socket to " \ "the type %d hydra process failed.", cpc->type); - free(cpc); + close(fd); + __destroy_slot(cpc); return NULL; } - pollfd = __poll_fd(fd, G_IO_IN, (GSourceFunc)__handle_hydra_event, - cpc->type, cpc->loader_id); - if (pollfd == 0) { + hydra_pollfd = __poll_fd(hydra_fd, G_IO_IN, + (GSourceFunc)__handle_hydra_event, + cpc->type, cpc->loader_id); + if (hydra_pollfd == 0) { + close(hydra_fd); close(fd); - free(cpc); + __destroy_slot(cpc); return NULL; } + + cpc->hydra_pollfd = hydra_pollfd; } + candidate_slot_list = g_list_append(candidate_slot_list, cpc); return cpc; @@ -2185,11 +2254,7 @@ static int __remove_slot(int type, int loader_id) __dispose_candidate_process(cpc); candidate_slot_list = g_list_delete_link( candidate_slot_list, iter); - free(cpc->loader_path); - if (cpc->loader_extra) - free(cpc->loader_extra); - - free(cpc); + __destroy_slot(cpc); return 0; } -- 2.7.4 From 479332d45c45dd5057ca94fd98e42e3358713447 Mon Sep 17 00:00:00 2001 From: Hwankyu Jhun Date: Thu, 23 Jan 2020 11:04:14 +0900 Subject: [PATCH 16/16] Fix fd event handling - Uses GIOChannel instead of GSource Change-Id: Iaf999693e8da5b0830f015435d0ebf37accab91a Signed-off-by: Hwankyu Jhun --- CMakeLists.txt | 1 + inc/launchpad_io_channel.h | 38 ++++++ src/launchpad.c | 315 ++++++++++++++------------------------------- src/launchpad_io_channel.c | 159 +++++++++++++++++++++++ src/log_private.h | 17 ++- 5 files changed, 314 insertions(+), 216 deletions(-) create mode 100644 inc/launchpad_io_channel.h create mode 100644 src/launchpad_io_channel.c diff --git a/CMakeLists.txt b/CMakeLists.txt index ad32426..5239b49 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -146,6 +146,7 @@ SET(${LAUNCHPAD_PROCESS_POOL}_SOURCE_FILES src/launchpad_debug.c src/launchpad_signal.c src/launchpad_config.c + src/launchpad_io_channel.c ) ADD_EXECUTABLE(${LAUNCHPAD_PROCESS_POOL} ${${LAUNCHPAD_PROCESS_POOL}_SOURCE_FILES}) diff --git a/inc/launchpad_io_channel.h b/inc/launchpad_io_channel.h new file mode 100644 index 0000000..6498fb3 --- /dev/null +++ b/inc/launchpad_io_channel.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020 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. + */ + +#pragma once + +#include + +typedef enum { + IO_IN = 0x01, + IO_OUT = 0x02, + IO_PRI = 0x04, + IO_ERR = 0x08, + IO_HUP = 0x10, + IO_NVAL = 0x20, +} io_condition_e; + +typedef bool (*io_channel_event_cb)(int fd, io_condition_e condition, + void *user_data); + +typedef struct io_channel_s *io_channel_h; + +io_channel_h _io_channel_create(int fd, io_condition_e condition, + io_channel_event_cb, void *user_data); + +void _io_channel_destroy(io_channel_h channel); diff --git a/src/launchpad.c b/src/launchpad.c index e751fbb..b847c2c 100755 --- a/src/launchpad.c +++ b/src/launchpad.c @@ -44,6 +44,7 @@ #include "launchpad_common.h" #include "launchpad_config.h" #include "launchpad_debug.h" +#include "launchpad_io_channel.h" #include "launchpad_signal.h" #include "launchpad_types.h" #include "loader_info.h" @@ -84,7 +85,6 @@ typedef struct { int send_fd; int hydra_fd; int last_exec_time; - guint source; guint timer; char *loader_path; char *loader_extra; @@ -105,8 +105,9 @@ typedef struct { guint live_timer; int state; bool is_hydra; - guint pollfd; - guint hydra_pollfd; + io_channel_h client_channel; + io_channel_h channel; + io_channel_h hydra_channel; } candidate_process_context_t; typedef struct { @@ -152,6 +153,11 @@ static sequencer __sequencer; static int MEMORY_STATUS_LOW; static int MEMORY_STATUS_NORMAL; +static io_channel_h __logger_channel; +static io_channel_h __label_monitor_channel; +static io_channel_h __sigchild_channel; +static io_channel_h __launchpad_channel; + static candidate_process_context_t *__add_slot(int type, int loader_id, int caller_pid, const char *loader_path, const char *extra, int detection_method, int activation_method, @@ -787,7 +793,7 @@ static void __reset_slot(candidate_process_context_t *cpc) cpc->send_fd = -1; cpc->prepared = false; cpc->pid = CANDIDATE_NONE; - cpc->source = 0; + cpc->client_channel = NULL; cpc->timer = 0; cpc->live_timer = 0; } @@ -804,8 +810,8 @@ static void __dispose_candidate_process(candidate_process_context_t *cpc) } if (cpc->live_timer > 0) g_source_remove(cpc->live_timer); - if (cpc->source > 0) - g_source_remove(cpc->source); + if (cpc->client_channel) + _io_channel_destroy(cpc->client_channel); if (cpc->timer > 0) g_source_remove(cpc->timer); if (cpc->send_fd > 0) @@ -1216,172 +1222,57 @@ static int __launchpad_pre_init(int argc, char **argv) return fd; } -static void __destroy_poll_data(gpointer data) -{ - free(data); -} - -static gboolean __glib_check(GSource *src) -{ - GSList *fd_list; - GPollFD *tmp; - - fd_list = src->poll_fds; - do { - tmp = (GPollFD *) fd_list->data; - if ((tmp->revents & (G_IO_IN | G_IO_PRI | G_IO_HUP | - G_IO_NVAL))) - return TRUE; - fd_list = fd_list->next; - } while (fd_list); - - return FALSE; -} - -static gboolean __glib_dispatch(GSource *src, GSourceFunc callback, - gpointer data) -{ - return callback(data); -} - -static gboolean __glib_prepare(GSource *src, gint *timeout) -{ - return FALSE; -} - -static void __glib_finalize(GSource *src) -{ - GSList *fd_list; - GPollFD *gpollfd; - - fd_list = src->poll_fds; - do { - gpollfd = (GPollFD *)fd_list->data; - close(gpollfd->fd); - g_free(gpollfd); - - fd_list = fd_list->next; - } while (fd_list); -} - -static GSourceFuncs funcs = { - .prepare = __glib_prepare, - .check = __glib_check, - .dispatch = __glib_dispatch, - .finalize = __glib_finalize -}; - -static guint __poll_fd(int fd, gushort events, GSourceFunc func, int type, - int loader_id) +static bool __handle_loader_client_event(int fd, io_condition_e cond, + void *data) { - int r; - GPollFD *gpollfd; - GSource *src; - loader_context_t *lc; - - src = g_source_new(&funcs, sizeof(GSource)); - if (!src) { - _E("out of memory"); - return 0; - } - - gpollfd = (GPollFD *)g_malloc(sizeof(GPollFD)); - if (!gpollfd) { - _E("out of memory"); - g_source_destroy(src); - return 0; - } - - gpollfd->events = events; - gpollfd->fd = fd; - - lc = malloc(sizeof(loader_context_t)); - if (lc == NULL) { - g_free(gpollfd); - g_source_destroy(src); - return 0; - } - - lc->gpollfd = gpollfd; - lc->type = type; - lc->loader_id = loader_id; - - g_source_add_poll(src, gpollfd); - g_source_set_callback(src, func, - (gpointer) lc, __destroy_poll_data); - g_source_set_priority(src, G_PRIORITY_DEFAULT); - - r = g_source_attach(src, NULL); - if (r == 0) { - g_free(gpollfd); - g_source_destroy(src); - return 0; - } - - return r; -} - -static gboolean __handle_loader_client_event(gpointer data) -{ - loader_context_t *lc = (loader_context_t *) data; - int type = lc->type; - int loader_id = lc->loader_id; - gushort revents = lc->gpollfd->revents; - candidate_process_context_t *cpc = __find_slot(type, loader_id); + candidate_process_context_t *cpc = data; if (cpc == NULL) - return G_SOURCE_REMOVE; + return false; - if (revents & (G_IO_HUP | G_IO_NVAL)) { - SECURE_LOGE("Type %d candidate process was " \ + if (cond & (IO_HUP | IO_NVAL)) { + SECURE_LOGE("Type %d candidate process was " "(POLLHUP|POLLNVAL), pid: %d", cpc->type, cpc->pid); cpc->pid = CANDIDATE_NONE; __dispose_candidate_process(cpc); __prepare_candidate_process(cpc->type, cpc->loader_id); - return G_SOURCE_REMOVE; + return false; } - return G_SOURCE_CONTINUE; + return true; + } -static gboolean __handle_hydra_client_event(gpointer data) +static bool __handle_hydra_client_event(int fd, io_condition_e cond, + void *data) { - loader_context_t *lc = (loader_context_t *)data; - int type = lc->type; - int loader_id = lc->loader_id; - gushort revents = lc->gpollfd->revents; - candidate_process_context_t *cpc = __find_slot(type, loader_id); + candidate_process_context_t *cpc = data; if (cpc == NULL) - return G_SOURCE_REMOVE; + return false; - if (revents & (G_IO_HUP | G_IO_NVAL)) { - SECURE_LOGE("Type %d hydra process was " \ + if (cond & (IO_HUP | IO_NVAL)) { + SECURE_LOGE("Type %d hydra process was " "(POLLHUP|POLLNVAL), pid: %d", cpc->type, cpc->hydra_pid); __dispose_hydra_process(cpc); __prepare_candidate_process(cpc->type, cpc->loader_id); - return G_SOURCE_REMOVE; + return false; } - return G_SOURCE_CONTINUE; + return true; } -static gboolean __handle_loader_event(gpointer data) +static bool __handle_loader_event(int fd, io_condition_e cond, void *data) { - loader_context_t *lc = (loader_context_t *) data; - int fd = lc->gpollfd->fd; - int type = lc->type; - int loader_id = lc->loader_id; + candidate_process_context_t *cpc = data; int client_fd; int client_pid; int ret; - candidate_process_context_t *cpc = __find_slot(type, loader_id); - if (cpc == NULL) - return G_SOURCE_REMOVE; + return false; if (!cpc->prepared) { ret = __accept_candidate_process(fd, &client_fd, &client_pid); @@ -1394,12 +1285,13 @@ static gboolean __handle_loader_event(gpointer data) cpc->prepared = true; cpc->send_fd = client_fd; - SECURE_LOGD("Type %d candidate process was connected," \ - " pid: %d", type, cpc->pid); - cpc->source = __poll_fd(client_fd, G_IO_IN | G_IO_HUP, - __handle_loader_client_event, type, - loader_id); - if (cpc->source == 0) + SECURE_LOGD("Type %d candidate process was connected, " + "pid: %d", cpc->type, cpc->pid); + cpc->client_channel = _io_channel_create(client_fd, + IO_IN | IO_HUP, + __handle_loader_client_event, + cpc); + if (!cpc->client_channel) close(client_fd); } } else { @@ -1407,36 +1299,32 @@ static gboolean __handle_loader_event(gpointer data) _E("Refused candidate process connection"); } - return G_SOURCE_CONTINUE; + return true; } -static gboolean __handle_hydra_event(gpointer data) +static bool __handle_hydra_event(int fd, io_condition_e cond, void *data) { - loader_context_t *lc = (loader_context_t *) data; - int fd = lc->gpollfd->fd; - int type = lc->type; - int loader_id = lc->loader_id; + candidate_process_context_t *cpc = data; int client_fd; int client_pid; int ret; - candidate_process_context_t *cpc = __find_slot(type, loader_id); - if (cpc == NULL) - return G_SOURCE_REMOVE; + return false; if (!cpc->prepared) { ret = __accept_candidate_process(fd, &client_fd, &client_pid); if (ret >= 0) { cpc->hydra_fd = client_fd; - SECURE_LOGD("Type %d hydra process was connected," \ - " pid: %d", type, cpc->hydra_pid); + SECURE_LOGD("Type %d hydra process was connected," + " pid: %d", cpc->type, cpc->hydra_pid); - cpc->source = __poll_fd(client_fd, G_IO_IN | G_IO_HUP, - __handle_hydra_client_event, type, - loader_id); - if (cpc->source == 0) + cpc->client_channel = _io_channel_create(client_fd, + IO_IN | IO_HUP, + __handle_hydra_client_event, + cpc); + if (!cpc->client_channel) close(client_fd); } } else { @@ -1444,14 +1332,12 @@ static gboolean __handle_hydra_event(gpointer data) _E("Refused hydra process connection"); } - return G_SOURCE_CONTINUE; + return true; } -static gboolean __handle_sigchild(gpointer data) +static bool __handle_sigchild(int fd, io_condition_e cond, void *data) { candidate_process_context_t *cpc; - loader_context_t *lc = (loader_context_t *) data; - int fd = lc->gpollfd->fd; struct signalfd_siginfo siginfo; ssize_t s; char *appid; @@ -1498,15 +1384,15 @@ static gboolean __handle_sigchild(gpointer data) } } while (s > 0); - return G_SOURCE_CONTINUE; + return true; } -static gboolean __handle_label_monitor(gpointer data) +static bool __handle_label_monitor(int fd, io_condition_e cond, void *data) { candidate_process_context_t *cpc; GList *iter = candidate_slot_list; - _D("__handle_label_monitor()"); + _D("%s()", __FUNCTION__); security_manager_app_labels_monitor_process(label_monitor); while (iter) { @@ -1525,7 +1411,7 @@ static gboolean __handle_label_monitor(gpointer data) iter = g_list_next(iter); } - return G_SOURCE_CONTINUE; + return true; } static float __interpolator(float input, int cpu_max, int cpu_min) @@ -1894,10 +1780,8 @@ static void __update_slot_state(candidate_process_context_t *cpc, int method) } } -static gboolean __handle_launch_event(gpointer data) +static bool __handle_launch_event(int fd, io_condition_e cond, void *data) { - loader_context_t *lc = (loader_context_t *) data; - int fd = lc->gpollfd->fd; bundle *kb = NULL; app_pkt_t *pkt = NULL; appinfo_t *menu_info = NULL; @@ -2075,7 +1959,7 @@ end: traceEnd(TTRACE_TAG_APPLICATION_MANAGER); - return G_SOURCE_CONTINUE; + return true; } static void __destroy_slot(candidate_process_context_t *cpc) @@ -2083,11 +1967,11 @@ static void __destroy_slot(candidate_process_context_t *cpc) if (!cpc) return; - if (cpc->hydra_pollfd) - g_source_remove(cpc->hydra_pollfd); + if (cpc->hydra_channel) + _io_channel_destroy(cpc->hydra_channel); - if (cpc->pollfd) - g_source_remove(cpc->pollfd); + if (cpc->channel) + _io_channel_destroy(cpc->channel); if (cpc->loader_extra) free(cpc->loader_extra); @@ -2138,7 +2022,6 @@ static candidate_process_context_t *__create_slot(int type, int loader_id, cpc->send_fd = -1; cpc->hydra_fd = -1; cpc->last_exec_time = 0; - cpc->source = 0; cpc->timer = 0; cpc->detection_method = detection_method; cpc->timeout_val = timeout_val; @@ -2176,9 +2059,9 @@ static candidate_process_context_t *__add_slot(int type, int loader_id, { candidate_process_context_t *cpc; int fd; - guint pollfd; + io_channel_h channel; int hydra_fd; - guint hydra_pollfd; + io_channel_h hydra_channel; if (__find_slot(type, loader_id) != NULL) return NULL; @@ -2202,15 +2085,14 @@ static candidate_process_context_t *__add_slot(int type, int loader_id, return NULL; } - pollfd = __poll_fd(fd, G_IO_IN, (GSourceFunc)__handle_loader_event, - cpc->type, cpc->loader_id); - if (pollfd == 0) { + channel = _io_channel_create(fd, IO_IN, __handle_loader_event, cpc); + if (!channel) { close(fd); __destroy_slot(cpc); return NULL; } - cpc->pollfd = pollfd; + cpc->channel = channel; if (is_hydra) { hydra_fd = __listen_hydra_process(cpc->type, cpc->loader_id); @@ -2218,22 +2100,19 @@ static candidate_process_context_t *__add_slot(int type, int loader_id, _E("[launchpad] Listening the socket to " \ "the type %d hydra process failed.", cpc->type); - close(fd); __destroy_slot(cpc); return NULL; } - hydra_pollfd = __poll_fd(hydra_fd, G_IO_IN, - (GSourceFunc)__handle_hydra_event, - cpc->type, cpc->loader_id); - if (hydra_pollfd == 0) { + hydra_channel = _io_channel_create(hydra_fd, IO_IN, + __handle_hydra_event, cpc); + if (!hydra_channel) { close(hydra_fd); - close(fd); __destroy_slot(cpc); return NULL; } - cpc->hydra_pollfd = hydra_pollfd; + cpc->hydra_channel = hydra_channel; } @@ -2267,7 +2146,6 @@ static int __remove_slot(int type, int loader_id) static int __init_launchpad_fd(int argc, char **argv) { int fd = -1; - guint pollfd; fd = __launchpad_pre_init(argc, argv); if (fd < 0) { @@ -2275,9 +2153,9 @@ static int __init_launchpad_fd(int argc, char **argv) return -1; } - pollfd = __poll_fd(fd, G_IO_IN, (GSourceFunc)__handle_launch_event, 0, - 0); - if (pollfd == 0) { + __launchpad_channel = _io_channel_create(fd, IO_IN, + __handle_launch_event, NULL); + if (!__launchpad_channel) { close(fd); return -1; } @@ -2288,7 +2166,6 @@ static int __init_launchpad_fd(int argc, char **argv) static int __init_sigchild_fd(void) { int fd = -1; - guint pollfd; fd = _signal_get_sigchld_fd(); if (fd < 0) { @@ -2296,8 +2173,9 @@ static int __init_sigchild_fd(void) return -1; } - pollfd = __poll_fd(fd, G_IO_IN, (GSourceFunc)__handle_sigchild, 0, 0); - if (pollfd == 0) { + __sigchild_channel = _io_channel_create(fd, IO_IN, + __handle_sigchild, NULL); + if (!__sigchild_channel) { close(fd); return -1; } @@ -2309,7 +2187,6 @@ static int __init_label_monitor_fd(void) { int r; int fd = -1; - guint pollfd; r = security_manager_app_labels_monitor_init(&label_monitor); if (r != SECURITY_MANAGER_SUCCESS) @@ -2325,9 +2202,9 @@ static int __init_label_monitor_fd(void) goto err; } - pollfd = __poll_fd(fd, G_IO_IN, - (GSourceFunc)__handle_label_monitor, 0, 0); - if (pollfd == 0) + __label_monitor_channel = _io_channel_create(fd, IO_IN, + __handle_label_monitor, NULL); + if (!__label_monitor_channel) goto err; return 0; @@ -2590,18 +2467,16 @@ static int __register_vconf_events(void) return 0; } -static gboolean __handle_logger(gpointer data) +static bool __handle_logger(int fd, io_condition_e cond, void *data) { - loader_context_t *lc = (loader_context_t *)data; - int fd = lc->gpollfd->fd; - app_pkt_t *pkt = NULL; + app_pkt_t *pkt; struct ucred cr; int clifd = -1; pkt = _accept_recv_pkt_raw(fd, &clifd, &cr); if (!pkt) { _E("Failed to receive the packet"); - return G_SOURCE_CONTINUE; + return true; } if (getuid() != cr.uid) { @@ -2615,20 +2490,18 @@ static gboolean __handle_logger(gpointer data) } SECURE_LOGE("[%d] %s", cr.pid, (const char *)pkt->data); - end: if (clifd != -1) close(clifd); - if (pkt) - free(pkt); - return G_SOURCE_CONTINUE; + free(pkt); + + return true; } static int __init_logger_fd(void) { int fd; - guint pollfd; fd = _create_server_sock(LAUNCHPAD_LOGGER_SOCK); if (fd < 0) { @@ -2636,8 +2509,8 @@ static int __init_logger_fd(void) return -1; } - pollfd = __poll_fd(fd, G_IO_IN, (GSourceFunc)__handle_logger, 0, 0); - if (pollfd == 0) { + __logger_channel = _io_channel_create(fd, IO_IN, __handle_logger, NULL); + if (!__logger_channel) { close(fd); return -1; } @@ -2713,9 +2586,21 @@ static void __after_loop(void) _launcher_info_unload(launcher_info_list); _config_fini(); + if (__label_monitor_channel) + _io_channel_destroy(__label_monitor_channel); + if (label_monitor) security_manager_app_labels_monitor_finish(label_monitor); + if (__logger_channel) + _io_channel_destroy(__logger_channel); + + if (__launchpad_channel) + _io_channel_destroy(__launchpad_channel); + + if (__sigchild_channel) + _io_channel_destroy(__sigchild_channel); + __sequencer_fini(); } diff --git a/src/launchpad_io_channel.c b/src/launchpad_io_channel.c new file mode 100644 index 0000000..f20cb92 --- /dev/null +++ b/src/launchpad_io_channel.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2020 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 "launchpad_io_channel.h" +#include "log_private.h" + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0])) + +struct io_channel_s { + GIOChannel *io; + guint tag; + int fd; + io_channel_event_cb callback; + void *user_data; +}; + +struct io_condition_s { + io_condition_e io_cond; + GIOCondition g_io_cond; +}; + +static struct io_condition_s __cond_map[] = { + { + .io_cond = IO_IN, + .g_io_cond = G_IO_IN + }, + { + .io_cond = IO_OUT, + .g_io_cond = G_IO_OUT + }, + { + .io_cond = IO_PRI, + .g_io_cond = G_IO_PRI + }, + { + .io_cond = IO_ERR, + .g_io_cond = G_IO_ERR + }, + { + .io_cond = IO_HUP, + .g_io_cond = G_IO_HUP + }, + { + .io_cond = IO_NVAL, + .g_io_cond = G_IO_NVAL, + } +}; + +static io_condition_e __convert_g_io_condition(GIOCondition cond) +{ + io_condition_e condition = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(__cond_map); i++) { + if (__cond_map[i].g_io_cond & cond) + condition |= __cond_map[i].io_cond; + } + + return condition; +} + +static GIOCondition __convert_io_condition(io_condition_e cond) +{ + GIOCondition condition = 0; + int i; + + for (i = 0; i < ARRAY_SIZE(__cond_map); i++) { + if (__cond_map[i].io_cond & cond) + condition |= __cond_map[i].g_io_cond; + } + + return condition; +} + +static gboolean __io_event_cb(GIOChannel *source, GIOCondition condition, + gpointer data) +{ + io_channel_h channel = (io_channel_h)data; + io_condition_e cond = __convert_g_io_condition(condition); + + if (!channel->callback(channel->fd, cond, channel->user_data)) + return G_SOURCE_REMOVE; + + return G_SOURCE_CONTINUE; +} + +io_channel_h _io_channel_create(int fd, io_condition_e cond, + io_channel_event_cb callback, void *user_data) +{ + struct io_channel_s *channel; + + if (fd < 3 || !callback) { + _E("Invalid parameter"); + return NULL; + } + + channel = calloc(1, sizeof(struct io_channel_s)); + if (!channel) { + _E("Out of memory"); + return NULL; + } + + channel->io = g_io_channel_unix_new(fd); + if (!channel->io) { + _E("Failed to create GIOChannel"); + _io_channel_destroy(channel); + return NULL; + } + + channel->tag = g_io_add_watch(channel->io, __convert_io_condition(cond), + __io_event_cb, channel); + if (!channel->tag) { + _E("Failed to add GIO watch"); + _io_channel_destroy(channel); + return NULL; + } + + channel->fd = fd; + channel->callback = callback; + channel->user_data = user_data; + + return channel; +} + +void _io_channel_destroy(io_channel_h channel) +{ + if (!channel) + return; + + if (channel->tag) + g_source_remove(channel->tag); + + if (channel->io) + g_io_channel_unref(channel->io); + + if (channel->fd) + close(channel->fd); + + free(channel); +} diff --git a/src/log_private.h b/src/log_private.h index f214b78..c3b0662 100644 --- a/src/log_private.h +++ b/src/log_private.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved + * Copyright (c) 2019 - 2020 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. @@ -24,9 +24,24 @@ #endif #define LOG_TAG "LAUNCHPAD" +#ifdef _E +#undef _E +#endif #define _E(fmt, arg...) LOGE(fmt, ##arg) + +#ifdef _D +#undef _D +#endif #define _D(fmt, arg...) LOGD(fmt, ##arg) + +#ifdef _W +#undef _W +#endif #define _W(fmt, arg...) LOGW(fmt, ##arg) + +#ifdef _I +#undef _I +#endif #define _I(fmt, arg...) LOGI(fmt, ##arg) #endif /* __LOG_PRIVATE_H__ */ -- 2.7.4