From: Hwankyu Jhun Date: Fri, 4 Dec 2015 11:57:26 +0000 (+0900) Subject: Refactoring debug-launchpad X-Git-Tag: accepted/tizen/mobile/20151212.070856^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9164fbcd6860ce11073f9bc0414d635907d165d9;p=platform%2Fcore%2Fappfw%2Fdebug-launchpad.git Refactoring debug-launchpad - sync with tizen_2.4 - use glib main loop - remove unnecessary dependencies (x11, aul, ail) Change-Id: I79652c1a5415f4f5a9bf0cbb68d4c13e8e8a7c8e Signed-off-by: Hwankyu Jhun --- diff --git a/CMakeLists.txt b/CMakeLists.txt index 9a65cf3..bc44053 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,11 +16,16 @@ IF("${CMAKE_BUILD_TYPE}" STREQUAL "") ENDIF() MESSAGE("Build type: ${CMAKE_BUILD_TYPE}") - # Set required packages INCLUDE(FindPkgConfig) -pkg_check_modules(pkgs REQUIRED dlog x11 libprivilege-control dbus-glib-1 sqlite3 bundle vconf libsmack aul) +SET(pkgs_requires "dlog glib-2.0 libprivilege-control dbus-glib-1 bundle vconf libsmack security-manager pkgmgr-info") +IF(_APPFW_FEATURE_SOCKET_ACTIVATION) + SET(pkgs_requires "${pkgs_requires} libsystemd-daemon") + ADD_DEFINITIONS("-D_APPFW_FEATURE_SOCKET_ACTIVATION") +ENDIF(_APPFW_FEATURE_SOCKET_ACTIVATION) + +pkg_check_modules(pkgs REQUIRED ${pkgs_requires}) FIND_LIBRARY(LIB_DL dl) @@ -38,51 +43,28 @@ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}") SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${TEST_CFLAGS}") SET(CMAKE_C_FLAGS_DEBUG "-O0 -g") SET(CMAKE_C_FLAGS_RELEASE "-O2") - SET(CMAKE_SKIP_BUILD_RPATH true) -# Get uname value to set 'TARGET' definition -# TODO: Is this needed? -FIND_PROGRAM(UNAME NAMES uname) -EXEC_PROGRAM("${UNAME}" ARGS "-m" OUTPUT_VARIABLE "ARCH") -IF("${ARCH}" STREQUAL "arm") - ADD_DEFINITIONS("-DTARGET") - MESSAGE("add -DTARGET") -ENDIF("${ARCH}" STREQUAL "arm") - ADD_DEFINITIONS("-DPREFIX=\"${CMAKE_INSTALL_PREFIX}\"") ADD_DEFINITIONS("-DSHARE_PREFIX=\"/usr/share/aul\"") # Linker flags SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed") - ### Build ### - -# launchpad(old avatar) daemon -SET(AVATAR_NAME "debug_launchpad_preloading_preinitializing_daemon") -add_executable(${AVATAR_NAME} - src/fileutils.c - src/app_sock.c - src/simple_util.c - src/launchpad.c +# debug_launchpad_preloading_preinitializing_daemon +SET(DEBUG_LAUNCHPAD "debug_launchpad_preloading_preinitializing_daemon") +add_executable(${DEBUG_LAUNCHPAD} + src/file_util.c + src/debug_util.c + src/security_util.c + src/signal_util.c + src/common.c + src/debug-launchpad.c ) -MESSAGE(" "${pkgs_LDFLAGS}) -target_link_libraries(${AVATAR_NAME} aul cap ${pkgs_LDFLAGS} ${LIB_DL}) -set_target_properties(${AVATAR_NAME} - PROPERTIES SKIP_BUILD_RPATH true - ) # remove rpath option that is automatically generated by cmake. - - -INSTALL(TARGETS ${LAUNCH_AGENT} DESTINATION bin) - - - -# pkgconfig file - - -### Install ### -INSTALL(TARGETS ${AVATAR_NAME} DESTINATION bin) - +target_link_libraries(${DEBUG_LAUNCHPAD} ${pkgs_LDFLAGS} ${LIB_DL} "-pie") +set_target_properties(${DEBUG_LAUNCHPAD} PROPERTIES COMPILE_FLAGS ${CFLAGS} "-fPIE") +set_target_properties(${DEBUG_LAUNCHPAD} PROPERTIES SKIP_BUILD_RPATH true) +INSTALL(TARGETS ${DEBUG_LAUNCHPAD} DESTINATION bin) diff --git a/LICENSE.APLv2 b/LICENSE similarity index 100% rename from LICENSE.APLv2 rename to LICENSE diff --git a/debug-launchpad.manifest b/debug-launchpad.manifest new file mode 100644 index 0000000..5874aa8 --- /dev/null +++ b/debug-launchpad.manifest @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/feature/preexec.h b/feature/preexec.h deleted file mode 100755 index 644c416..0000000 --- a/feature/preexec.h +++ /dev/null @@ -1,187 +0,0 @@ -/* - * debug-launchpad - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungmin Cho , Gwangho Hwang - * - * 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. - * - */ - -#ifdef PREEXEC_ACTIVATE - -#include -#include -#define PREEXEC_FILE SHARE_PREFIX"/preexec_list.txt" - -static int preexec_initialized = 0; - -GSList *preexec_list = NULL; - -typedef struct _preexec_list_t { - char *pkg_type; - char *so_path; - int (*dl_do_pre_exe) (char *, char *); -} preexec_list_t; - -static void __preexec_list_free() -{ - GSList *iter = NULL; - preexec_list_t *type_t; - - for (iter = preexec_list; iter != NULL; iter = g_slist_next(iter)) { - type_t = iter->data; - if (type_t) { - if (type_t->pkg_type) - free(type_t->pkg_type); - if (type_t->so_path) - free(type_t->so_path); - free(type_t); - } - } - g_slist_free(preexec_list); - preexec_initialized = 0; - return; -} - -static inline void __preexec_init(int argc, char **argv) -{ - void *handle = NULL; - FILE *preexec_file; - char *saveptr = NULL; - char line[MAX_LOCAL_BUFSZ]; - char *type = NULL; - char *sopath = NULL; - char *symbol = NULL; - int (*func) (char *, char *) = NULL; - preexec_list_t *type_t = NULL; - - preexec_file = fopen(PREEXEC_FILE, "rt"); - if (preexec_file == NULL) { - _E("no preexec\n"); - return; - } - - _D("preexec start\n"); - - while (fgets(line, MAX_LOCAL_BUFSZ, preexec_file) > 0) { - /* Parse each line */ - if (line[0] == '#' || line[0] == '\0') - continue; - - type = strtok_r(line, ":\f\n\r\t\v ", &saveptr); - if (type == NULL) - continue; - sopath = strtok_r(NULL, ",\f\n\r\t\v ", &saveptr); - if (sopath == NULL) - continue; - symbol = strtok_r(NULL, ",\f\n\r\t\v ", &saveptr); - if (symbol == NULL) - continue; - - type_t = (preexec_list_t *) calloc(1, sizeof(preexec_list_t)); - if (type_t == NULL) { - _E("no available memory\n"); - __preexec_list_free(); - fclose(preexec_file); - return; - } - - handle = dlopen(sopath, RTLD_NOW); - if (handle == NULL) { - free(type_t); - continue; - } - _D("preexec %s %s# - handle : %x\n", type, sopath, handle); - - func = dlsym(handle, symbol); - if (func == NULL) { - _E("failed to get symbol type:%s path:%s\n", - type, sopath); - free(type_t); - dlclose(handle); - handle = NULL; - continue; - } - - type_t->pkg_type = strdup(type); - if (type_t->pkg_type == NULL) { - _E("no available memory\n"); - free(type_t); - __preexec_list_free(); - fclose(preexec_file); - return; - } - type_t->so_path = strdup(sopath); - if (type_t->so_path == NULL) { - _E("no available memory\n"); - free(type_t->pkg_type); - free(type_t); - __preexec_list_free(); - fclose(preexec_file); - return; - } - type_t->dl_do_pre_exe = func; - - preexec_list = g_slist_append(preexec_list, (void *)type_t); - } - - fclose(preexec_file); - preexec_initialized = 1; -} - -static inline void __preexec_run(const char *pkg_type, const char *pkg_name, - const char *app_path) -{ - GSList *iter = NULL; - preexec_list_t *type_t; - - if (!preexec_initialized) - return; - - for (iter = preexec_list; iter != NULL; iter = g_slist_next(iter)) { - type_t = iter->data; - if (type_t) { - if (!strcmp(pkg_type, type_t->pkg_type)) { - if (type_t->dl_do_pre_exe != NULL) { - type_t->dl_do_pre_exe((char *)pkg_name, - (char *)app_path); - _D("called dl_do_pre_exe() type: %s", - pkg_type); - } else { - _E("no symbol for this type: %s", - pkg_type); - } - } - } - } - -} - -#else - -static void __preexec_list_free() -{ -} - -static inline void __preexec_init(int argc, char **argv) -{ -} - -static inline void __preexec_run(const char *pkg_type, const char *pkg_name, - const char *app_path) -{ -} - -#endif diff --git a/include/access_control.h b/include/access_control.h deleted file mode 100755 index 604b095..0000000 --- a/include/access_control.h +++ /dev/null @@ -1,42 +0,0 @@ -/* - * debug-launchpad - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungmin Cho , Gwangho Hwang - * - * 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. - * - */ - - -#ifdef DAC_ACTIVATE - -#include - -#define INHOUSE_UID 5000 -static inline int __set_access(const char* pkg_name, const char* pkg_type, const char* app_path) -{ - return set_app_privilege(pkg_name, pkg_type, app_path); -} - -#else - -static inline int __set_access(const char* pkg_name, const char* pkg_type, const char* app_path) -{ - return 0; -} - -#endif - - diff --git a/include/app_signal.h b/include/app_signal.h deleted file mode 100755 index 474def5..0000000 --- a/include/app_signal.h +++ /dev/null @@ -1,44 +0,0 @@ -/* - * debug-launchpad - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungmin Cho , Gwangho Hwang - * - * 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 __APP_DBUS_H__ -#define __APP_DBUS_H__ - -#include -#include -#include - -#define AUL_DBUS_PATH "/aul/dbus_handler" -#define AUL_DBUS_SIGNAL_INTERFACE "org.tizen.aul.signal" -#define AUL_DBUS_APPDEAD_SIGNAL "app_dead" -#define AUL_DBUS_APPLAUNCH_SIGNAL "app_launch" - -#define OPT_VALGRIND_LOGFILE "--log-file=" -#define OPT_VALGRIND_LOGFILE_FIXED "--log-file=/tmp/valgrind_result.txt" -#define PATH_VALGRIND_LOGFILE "/tmp/valgrind_result.txt" -#define OPT_VALGRIND_XMLFILE "--xml-file=" -#define OPT_VALGRIND_XMLFILE_FIXED "--xml-file=/tmp/valgrind_result.xml" -#define PATH_VALGRIND_XMLFILE "/tmp/valgrind_result.xml" -#define OPT_VALGRIND_MASSIFFILE "--massif-out-file=" -#define OPT_VALGRIND_MASSIFFILE_FIXED "--massif-out-file=/tmp/valgrind_result.xml" - -#endif diff --git a/include/app_sock.h b/include/app_sock.h deleted file mode 100755 index 35d400c..0000000 --- a/include/app_sock.h +++ /dev/null @@ -1,78 +0,0 @@ -/* - * debug-launchpad - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungmin Cho , Gwangho Hwang - * - * 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 __APP_PKT_H_ -#define __APP_PKT_H_ - -#include -#define __USE_GNU -#include -#include - -enum app_cmd { - APP_START, - APP_OPEN, - APP_RESUME, - APP_RESUME_BY_PID, - APP_TERM_BY_PID, - APP_RESULT, - APP_START_RES, - APP_CANCEL, - APP_KILL_BY_PID, - APP_ADD_HISTORY, - APP_RUNNING_INFO, - APP_RUNNING_INFO_RESULT, - APP_IS_RUNNING, - APP_GET_APPID_BYPID, - APP_GET_APPID_BYPID_OK, - APP_GET_APPID_BYPID_ERROR, - APP_KEY_EVENT, - APP_KEY_RESERVE, - APP_KEY_RELEASE, - APP_STATUS_UPDATE, - APP_RELEASED, - APP_RUNNING_LIST_UPDATE -}; - -#define AUL_SOCK_PREFIX "/tmp/alaunch" -#define AUL_SOCK_MAXBUFF 65535 -#define DEBUG_LAUNCHPAD_PID -4 -#define ELOCALLAUNCH_ID 128 -#define EILLEGALACCESS 127 -#define ETERMINATING 126 - -typedef struct _app_pkt_t { - int cmd; - int len; - unsigned char data[1]; -} app_pkt_t; - -int __create_server_sock(int pid); -int __create_client_sock(int pid); -int __app_send_raw(int pid, int cmd, unsigned char *kb_data, int datalen); -int __app_send_raw_with_noreply(int pid, int cmd, unsigned char *kb_data, int datalen); -app_pkt_t *__app_recv_raw(int fd, int *clifd, struct ucred *cr); -app_pkt_t *__app_send_cmd_with_result(int pid, int cmd, unsigned char *kb_data, int datalen); - - -#endif - diff --git a/include/aul_util.h b/include/aul_util.h deleted file mode 100755 index c6ebb8f..0000000 --- a/include/aul_util.h +++ /dev/null @@ -1,51 +0,0 @@ -/* - * debug-launchpad - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungmin Cho , Gwangho Hwang - * - * 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 __AUL_UTIL_H_ -#define __AUL_UTIL_H_ - -#define AUL_UTIL_PID -2 - -#define MAX_PACKAGE_STR_SIZE 512 -#define MAX_PACKAGE_APP_PATH_SIZE 512 -#define MAX_RUNNING_APP_INFO 512 - -typedef struct _app_status_info_t{ - char appid[MAX_PACKAGE_STR_SIZE]; - char app_path[MAX_PACKAGE_APP_PATH_SIZE]; - int status; - int pid; -} app_status_info_t; - -struct amdmgr { - struct appinfomgr *af; /* appinfo manager */ - struct cginfo *cg; /* cgroup infomation */ -}; - -int _add_app_status_info_list(char *appid, int pid); -int _update_app_status_info_list(int pid, int status); -int _remove_app_status_info_list(int pid); - -#endif - - - diff --git a/include/common.h b/include/common.h new file mode 100644 index 0000000..487c120 --- /dev/null +++ b/include/common.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2015 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 __COMMON_H__ +#define __COMMON_H__ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include + +#ifdef LOG_TAG +#undef LOG_TAG +#define LOG_TAG "DEBUG_LAUNCHPAD" +#endif + +#define _E(fmt, arg...) LOGE(fmt, ##arg) +#define _D(fmt, arg...) LOGD(fmt, ##arg) +#define _W(fmt, arg...) LOGW(fmt, ##arg) + +#define SOCKET_PATH "/run/user" +#define MAX_LOCAL_BUFSZ 128 +#define AUL_SOCK_MAXBUFF 65535 + +#define PAD_CMD_LAUNCH 0 + +typedef struct _app_pkt_t { + int cmd; + int len; + unsigned char data[1]; +} app_pkt_t; + +typedef struct { + char *appid; + char *app_path; + char *original_app_path; + char *debug_appid; + char *pkg_type; + char *hwacc; + char *taskmanage; + char *comp_type; +} appinfo_t; + +struct ucred; + +int _create_server_sock(void); +app_pkt_t *_recv_pkt_raw(int fd, int *clifd, struct ucred *cr); +int _send_pkt_raw(int client_fd, app_pkt_t *pkt); + +appinfo_t *_appinfo_create(bundle *kb); +void _appinfo_free(appinfo_t *appinfo); +void _modify_bundle(bundle *kb, int caller_pid, appinfo_t *appinfo, int cmd); + +void _set_env(appinfo_t *app_info, bundle *kb); +char **_create_argc_argv(bundle *kb, int *margc, const char *app_path); + +char *_proc_get_cmdline_bypid(int pid); + +#endif /* __COMMON_H__ */ diff --git a/include/debug_util.h b/include/debug_util.h new file mode 100644 index 0000000..4168c95 --- /dev/null +++ b/include/debug_util.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2015 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 __DEBUG_UTIL_H__ +#define __DEBUG_UTIL_H__ + +#include +#include + +bool _gdbserver_is_running(void); +int _get_gdbserver_pid(void); +int _get_gdbserver_app_pid(void); +int _get_valgrind_option(void); +int _prepare_debug_tool(bundle *kb, const char *appid, + const char **str_arr, int len); +void _change_file(const char *path); +void _wait_for_valgrind_output(void); +void _set_env(appinfo_t *app_info, bundle *kb); +char **_create_argc_argv(bundle *kb, int *margc, const char *app_path); + +#endif /* __DEBUG_UTIL_H__ */ diff --git a/include/defs.h b/include/defs.h new file mode 100644 index 0000000..8e48b21 --- /dev/null +++ b/include/defs.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2015 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 __DEFS_H__ +#define __DEFS_H__ + +#define AUL_K_STARTTIME "__AUL_STARTTIME__" +#define AUL_K_EXEC "__AUL_EXEC__" +#define AUL_K_PACKAGETYPE "__AUL_PACKAGETYPE__" +#define AUL_K_HWACC "__AUL_HWACC__" +#define AUL_K_APPID "__AUL_APPID__" +#define AUL_K_PID "__AUL_PID__" +#define AUL_K_TASKMANAGE "__AUL_TASKMANAGE__" +#define AUL_K_INTERNAL_POOL "__AUL_INTERNAL_POOL__" +#define AUL_K_PKGID "__AUL_PKGID_" +#define AUL_K_DEBUG "__AUL_DEBUG__" +#define AUL_K_SDK "__AUL_SDK__" +#define AUL_K_ORG_CALLER_PID "__AUL_ORG_CALLER_PID__" +#define AUL_K_CALLER_PID "__AUL_CALLER_PID__" +#define AUL_K_COMP_TYPE "__AUL_COMP_TYPE__" +#define AUL_K_PRIVACY_APPID "__AUL_PRIVACY_APPID__" + +#define SDK_CODE_COVERAGE "CODE_COVERAGE" +#define SDK_DEBUG "DEBUG" +#define SDK_DYNAMIC_ANALYSIS "DYNAMIC_ANALYSIS" +#define SDK_UNIT_TEST "UNIT_TEST" +#define SDK_VALGRIND "VALGRIND" +#define SDK_ATTACH "ATTACH" + +/* DLP is short for debug-launchpad */ +#define DLP_K_DEBUG_ARG "__DLP_DEBUG_ARG__" +#define DLP_K_UNIT_TEST_ARG "__DLP_UNIT_TEST_ARG__" +#define DLP_K_VALGRIND_ARG "__DLP_VALGRIND_ARG__" +#define DLP_K_ATTACH_ARG "__DLP_ATTACH_ARG__" + +#define PATH_GDBSERVER "/home/developer/sdk_tools/gdbserver/gdbserver" +#define PATH_VALGRIND "/home/developer/sdk_tools/valgrind/usr/bin/valgrind" +#define PATH_DA_SO "/home/developer/sdk_tools/da/da_probe.so" + +#define OPT_VALGRIND_LOGFILE_FIXED "--log-file=/tmp/valgrind_result.txt" +#define OPT_VALGRIND_XMLFILE_FIXED "--xml-file=/tmp/valgrind_result.xml" +#define OPT_VALGRIND_MASSIFFILE_FIXED "--massif-out-file=/tmp/valgrind_result.xml" +#define PATH_VALGRIND_LOGFILE "/tmp/valgrind_result.txt" +#define PATH_VALGRIND_XMLFILE "/tmp/valgrind_result.xml" +#define PATH_VALGRIND_MASSIFFILE PATH_VALGRIND_XMLFILE + +#endif /* __DEFS_H__ */ + diff --git a/src/fileutils.h b/include/file_util.h similarity index 71% rename from src/fileutils.h rename to include/file_util.h index 948c261..dbc158e 100644 --- a/src/fileutils.h +++ b/include/file_util.h @@ -1,9 +1,5 @@ /* - * debug-launchpad - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungmin Cho , Gwangho Hwang + * Copyright (c) 2015 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. @@ -16,12 +12,13 @@ * 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 _FILEUTILS_H_ -#define _FILEUTILS_H_ +#ifndef __FILE_UTIL_H__ +#define __FILE_UTIL_H__ + +#include int dlp_chmod(const char *path, mode_t mode, int recursive); -#endif +#endif /* __FILE_UTIL_H__ */ diff --git a/include/menu_db_util.h b/include/menu_db_util.h deleted file mode 100755 index 2179d85..0000000 --- a/include/menu_db_util.h +++ /dev/null @@ -1,232 +0,0 @@ -/* - * debug-launchpad - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungmin Cho , Gwangho Hwang - * - * 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. - * - */ - - -#include -#include -#include -#include "simple_util.h" - -#define MAX_PATH_LEN 1024 - -#define AUL_APP_INFO_FLD_PKG_NAME "package" -#define AUL_APP_INFO_FLD_APP_PATH "exec" -#define AUL_APP_INFO_FLD_APP_TYPE "x_slp_packagetype" -#define AUL_APP_INFO_FLD_WIDTH "x_slp_baselayoutwidth" -#define AUL_APP_INFO_FLD_HEIGHT "x_slp_baselayoutheight" -#define AUL_APP_INFO_FLD_VERTICAL "x_slp_ishorizontalscale" -#define AUL_APP_INFO_FLD_MULTIPLE "x_slp_multiple" -#define AUL_APP_INFO_FLD_TASK_MANAGE "x_slp_taskmanage" -#define AUL_APP_INFO_FLD_MIMETYPE "mimetype" -#define AUL_APP_INFO_FLD_SERVICE "x_slp_service" - -#define AUL_RETRIEVE_PKG_NAME "package = '?'" -#define AUL_RETRIEVE_APP_PATH "exec = '?'" -#define AUL_RETRIEVE_MIMETYPE "mimetype like '?'" -#define AUL_RETRIEVE_SERVICE "x_slp_service like '?'" - -typedef struct { - char *pkg_name; /* package */ - char *app_path; /* exec */ - char *original_app_path; /* exec */ - char *pkg_type; /* x_slp_packagetype */ - char *hwacc; /* hwacceleration */ -} app_info_from_db; - -static inline char *_get_pkgname(app_info_from_db *menu_info) -{ - return menu_info ? menu_info->pkg_name : NULL; -} - -static inline char *_get_app_path(app_info_from_db *menu_info) -{ - int i = 0; - int path_len = -1; - - if (!menu_info || menu_info->app_path == NULL) - return NULL; - - while (menu_info->app_path[i] != 0) { - if (menu_info->app_path[i] == ' ' - || menu_info->app_path[i] == '\t') { - path_len = i; - break; - } - i++; - } - - if (path_len == 0) { - free(menu_info->app_path); - menu_info->app_path = NULL; - } else if (path_len > 0) { - char *tmp_app_path = malloc(sizeof(char) * (path_len + 1)); - if(tmp_app_path == NULL) - return NULL; - snprintf(tmp_app_path, path_len + 1, "%s", menu_info->app_path); - free(menu_info->app_path); - menu_info->app_path = tmp_app_path; - } - - return menu_info->app_path; -} - -static inline char *_get_original_app_path(app_info_from_db *menu_info) -{ - return menu_info ? menu_info->original_app_path : NULL; -} - -static inline void _free_app_info_from_db(app_info_from_db *menu_info) -{ - if (menu_info != NULL) { - if (menu_info->pkg_name != NULL) - free(menu_info->pkg_name); - if (menu_info->app_path != NULL) - free(menu_info->app_path); - if (menu_info->original_app_path != NULL) - free(menu_info->original_app_path); - if (menu_info->hwacc != NULL) - free(menu_info->hwacc); - free(menu_info); - } -} - -static inline app_info_from_db *_get_app_info_from_db_by_pkgname( - const char *pkgname) -{ - app_info_from_db *menu_info; - ail_appinfo_h handle; - ail_error_e ret; - char *str = NULL; - - menu_info = calloc(1, sizeof(app_info_from_db)); - if (menu_info == NULL) { - return NULL; - } - - ret = ail_get_appinfo(pkgname, &handle); - if (ret != AIL_ERROR_OK) { - _free_app_info_from_db(menu_info); - return NULL; - } - - ret = ail_appinfo_get_str(handle, AIL_PROP_PACKAGE_STR, &str); - if (str) { - menu_info->pkg_name = strdup(str); - str = NULL; - } - - ret = ail_appinfo_get_str(handle, AIL_PROP_EXEC_STR, &str); - if (str) { - menu_info->app_path = strdup(str); - str = NULL; - } - - if (menu_info->app_path != NULL) - menu_info->original_app_path = strdup(menu_info->app_path); - - ret = ail_appinfo_get_str(handle, AIL_PROP_X_SLP_PACKAGETYPE_STR, &str); - if (str) { - menu_info->pkg_type = strdup(str); - str = NULL; - } - - ret = ail_destroy_appinfo(handle); - if (ret != AIL_ERROR_OK) { - _E("ail_destroy_appinfo failed"); - } - - if (!_get_app_path(menu_info)) { - _free_app_info_from_db(menu_info); - return NULL; - } - - return menu_info; -} - -static inline ail_cb_ret_e __appinfo_func(const ail_appinfo_h appinfo, void *user_data) -{ - app_info_from_db *menu_info = (app_info_from_db *)user_data; - char *package; - ail_cb_ret_e ret = AIL_CB_RET_CONTINUE; - - if (!menu_info) - return ret; - - ail_appinfo_get_str(appinfo, AIL_PROP_PACKAGE_STR, &package); - if (package) { - menu_info->pkg_name = strdup(package); - ret = AIL_CB_RET_CANCEL; - } - - return ret; -} - -static inline app_info_from_db *_get_app_info_from_db_by_apppath( - const char *apppath) -{ - app_info_from_db *menu_info = NULL; - ail_filter_h filter; - ail_error_e ret; - int count; - - if (apppath == NULL) - return NULL; - - menu_info = calloc(1, sizeof(app_info_from_db)); - if (menu_info == NULL) - return NULL; - - ret = ail_filter_new(&filter); - if (ret != AIL_ERROR_OK) { - _free_app_info_from_db(menu_info); - return NULL; - } - - ret = ail_filter_add_str(filter, AIL_PROP_X_SLP_EXE_PATH, apppath); - if (ret != AIL_ERROR_OK) { - ail_filter_destroy(filter); - _free_app_info_from_db(menu_info); - return NULL; - } - - ret = ail_filter_count_appinfo(filter, &count); - if (ret != AIL_ERROR_OK) { - ail_filter_destroy(filter); - _free_app_info_from_db(menu_info); - return NULL; - } - if (count < 1) { - ail_filter_destroy(filter); - _free_app_info_from_db(menu_info); - return NULL; - } - - ail_filter_list_appinfo_foreach(filter, __appinfo_func, (void *)menu_info); - - ail_filter_destroy(filter); - - menu_info->app_path = strdup(apppath); - menu_info->original_app_path = strdup(apppath); - - return menu_info; - -} - diff --git a/include/perf.h b/include/perf.h index bec46e8..cfa9f59 100755 --- a/include/perf.h +++ b/include/perf.h @@ -1,9 +1,5 @@ /* - * debug-launchpad - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungmin Cho , Gwangho Hwang + * Copyright (c) 2015 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. @@ -16,53 +12,48 @@ * 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 __PERF_H__ #define __PERF_H__ #ifdef PERF_ACTIVATE - #include +#include + static struct timeval __g_base_time = { .tv_sec = 0, .tv_usec = 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, __FUNCTION__, __LINE__, \ - res.tv_sec, res.tv_usec/1000, ##arg, 27);\ - } \ -} while (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, __FUNCTION__, __LINE__, \ + res.tv_sec, res.tv_usec/1000, ##arg, 27); \ + } \ + } while (0) #else - #define INIT_PERF(kb) #define PERF(fmt, arg...) - -#endif - #endif +#endif /* __PERF_H__ */ diff --git a/include/preload.h b/include/preload.h deleted file mode 100755 index b817375..0000000 --- a/include/preload.h +++ /dev/null @@ -1,146 +0,0 @@ -/* - * debug-launchpad - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungmin Cho , Gwangho Hwang - * - * 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. - * - */ - - -#ifdef PRELOAD_ACTIVATE - -#include -#define PRELOAD_FILE SHARE_PREFIX"/preload_list.txt" - -#define EFL_PREINIT_FUNC "elm_quicklaunch_init" -#define EFL_SHUTDOWN_FUNC "elm_quicklaunch_shutdown" - -static int preload_initialized = 0; -static int g_argc; -static char **g_argv; -static int max_cmdline_size = 0; - -static int (*dl_einit) () = NULL; -static int (*dl_efini) () = NULL; - -static inline void __preload_init(int argc, char **argv) -{ - void *handle = NULL; - char soname[MAX_LOCAL_BUFSZ]; - FILE *preload_list; - int (*func)() = NULL; - int i; - - g_argc = argc; - g_argv = argv; - for (i = 0; i < argc; i++) { - max_cmdline_size += (strlen(argv[i]) + 1); - } - _D("max_cmdline_size = %d", max_cmdline_size); - - preload_list = fopen(PRELOAD_FILE, "rt"); - if (preload_list == NULL) { - _E("no preload\n"); - return; - } - - while (fgets(soname, MAX_LOCAL_BUFSZ, preload_list) > 0) { - soname[strlen(soname) - 1] = 0; - handle = dlopen((const char *) soname, RTLD_NOW); - if (handle == NULL) - continue; - _D("preload %s# - handle : %x\n", soname, handle); - - func = dlsym(handle, EFL_PREINIT_FUNC); - if (func != NULL) { - _D("get pre-initialization function\n"); - dl_einit = func; - func = dlsym(handle, EFL_SHUTDOWN_FUNC); - if (func != NULL) { - _D("get shutdown function\n"); - dl_efini = func; - } - } - } - - fclose(preload_list); - preload_initialized = 1; -} - -static inline int preinit_init() -{ - if (dl_einit != NULL) - dl_einit(0, NULL); - _D("pre-initialzation on"); - return 0; -} - -static inline int preinit_fini() -{ - if (dl_efini != NULL) - dl_efini(); - _D("pre-initialization off"); - return 0; -} - -/* TODO : how to set cmdline gracefully ?? */ -static inline int __change_cmdline(char *cmdline) -{ - if (strlen(cmdline) > max_cmdline_size + 1) { - _E("cmdline exceed max size : %d", max_cmdline_size); - return -1; - } - - memset(g_argv[0], '\0', max_cmdline_size); - snprintf(g_argv[0], max_cmdline_size, "%s", cmdline); - - return 0; -} - -static inline void __preload_exec(int argc, char **argv) -{ - void *handle = NULL; - int (*dl_main) (int, char **); - - if (!preload_initialized) - return; - - handle = dlopen(argv[0], RTLD_LAZY | RTLD_GLOBAL); - if (handle == NULL) { - return; - } - - dl_main = dlsym(handle, "main"); - if (dl_main != NULL) { - if (__change_cmdline(argv[0]) < 0) { - _E("change cmdline fail"); - return; - } - dl_main(argc, argv); - } else { - _E("dlsym not founded. bad preloaded app - check fpie pie"); - } - - exit(0); -} - -#else - -static inline void __preload_init(); -static inline void __preload_exec(int argc, char **argv); - -#endif - diff --git a/src/gl.h b/include/security_util.h old mode 100755 new mode 100644 similarity index 61% rename from src/gl.h rename to include/security_util.h index dd59c97..61c2a56 --- a/src/gl.h +++ b/include/security_util.h @@ -1,9 +1,5 @@ /* - * debug-launchpad - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungmin Cho , Gwangho Hwang + * Copyright (c) 2015 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. @@ -16,17 +12,14 @@ * 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 __SECURITY_UTIL_H__ +#define __SECURITY_UTIL_H__ -#ifdef GL_ACTIVATE - -#define USE_ENGINE(engine) setenv("ELM_ENGINE", engine, 1); - -#else - -#define USE_ENGINE(engine) - -#endif +int _set_smack_access_label(const char *path, const char *label); +int _apply_smack_rules(const char *subject, const char *object, + const char *access_type); +int _set_access(const char *appid); +#endif /* __SECURITY_UTIL_H__ */ diff --git a/src/config.h b/include/signal_util.h old mode 100755 new mode 100644 similarity index 55% rename from src/config.h rename to include/signal_util.h index 894d6b6..8466ade --- a/src/config.h +++ b/include/signal_util.h @@ -1,9 +1,5 @@ /* - * debug-launchpad - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungmin Cho , Gwangho Hwang + * Copyright (c) 2015 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. @@ -16,15 +12,19 @@ * 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 __SIGNAL_UTIL_H__ +#define __SIGNAL_UTIL_H__ + +#include -#define LAUNCHPAD_LOG -#define DAC_ACTIVATE -#define PRELOAD_ACTIVATE -#define PREEXEC_ACTIVATE -/*#define GL_ACTIVATE*/ -/*#define HEAPDGB_ACTIVATE*/ -/*#define PERF_ACTIVATE*/ +int _send_app_dead_signal(int dead_pid); +int _send_app_launch_signal(int launch_pid); +void _debug_launchpad_sigchld(struct signalfd_siginfo *info); +int _signal_init(void); +int _signal_get_sigchld_fd(void); +int _signal_unblock_sigchld(void); +int _signal_fini(void); +#endif /* __SIGNAL_UTIL_H__ */ diff --git a/include/simple_util.h b/include/simple_util.h deleted file mode 100755 index 83f554d..0000000 --- a/include/simple_util.h +++ /dev/null @@ -1,90 +0,0 @@ -/* - * debug-launchpad - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungmin Cho , Gwangho Hwang - * - * 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 __SIMPLE_UTIL__ -#define __SIMPLE_UTIL__ - -#include -#include -#include - -#ifdef LAUNCHPAD_LOG -#undef LOG_TAG -#define LOG_TAG "AUL_PAD" -#else -#undef LOG_TAG -#define LOG_TAG "AUL" -#endif -#ifdef AMD_LOG -#undef LOG_TAG -#define LOG_TAG "AUL_AMD" -#endif - - -#define MAX_LOCAL_BUFSZ 128 -#define MAX_PID_STR_BUFSZ 20 - -#define _E(fmt, arg...) LOGE(fmt, ##arg) -#define _D(fmt, arg...) LOGD(fmt, ##arg) -#define _W(fmt, arg...) LOGW(fmt, ##arg) - -#define retvm_if(expr, val, fmt, arg...) do { \ - if (expr) { \ - _E(fmt, ##arg); \ - _E("(%s) -> %s() return", #expr, __FUNCTION__); \ - return (val); \ - } \ -} while (0) - -#define retv_if(expr, val) do { \ - if (expr) { \ - _E("(%s) -> %s() return", #expr, __FUNCTION__); \ - return (val); \ - } \ -} while (0) - -int __proc_iter_cmdline(int (*iterfunc) - (const char *dname, const char *cmdline, void *priv), - void *priv); -int __proc_iter_pgid(int pgid, int (*iterfunc) (int pid, void *priv), - void *priv); -char *__proc_get_cmdline_bypid(int pid); - -static inline const char *FILENAME(const char *filename) -{ - const char *p; - const char *r; - - if (!filename) - return NULL; - - r = p = filename; - while (*p) { - if (*p == '/') - r = p + 1; - p++; - } - - return r; -} - -#endif diff --git a/packaging/debug-launchpad.service b/packaging/debug-launchpad.service new file mode 100644 index 0000000..0b7d052 --- /dev/null +++ b/packaging/debug-launchpad.service @@ -0,0 +1,6 @@ +[Unit] +Description=Start the debug preload/preinit daemon +After=dbus.service ac.service + +[Service] +ExecStart=/usr/bin/debug_launchpad_preloading_preinitializing_daemon diff --git a/packaging/debug-launchpad.socket b/packaging/debug-launchpad.socket new file mode 100644 index 0000000..4c5d81f --- /dev/null +++ b/packaging/debug-launchpad.socket @@ -0,0 +1,9 @@ +[Unit] +Description=The debug preload/preinit daemon Socket + +[Socket] +ListenStream=/run/user/%U/.debug-launchpad-sock +DirectoryMode=0777 + +[Install] +WantedBy=sockets.target diff --git a/packaging/debug-launchpad.spec b/packaging/debug-launchpad.spec old mode 100644 new mode 100755 index 7ccda1f..85494a2 --- a/packaging/debug-launchpad.spec +++ b/packaging/debug-launchpad.spec @@ -3,8 +3,10 @@ Summary: Debug Launchpad Version: 0.0.12 Release: 1 Group: System Environment/Daemons -License: Apache License, Version 2.0 +License: Apache-2.0 Source0: %{name}-%{version}.tar.gz +Source1: debug-launchpad.service +Source2: debug-launchpad.socket BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) Requires(post): /sbin/ldconfig @@ -14,17 +16,29 @@ Requires(postun): /usr/bin/systemctl Requires(preun): /usr/bin/systemctl BuildRequires: cmake +BuildRequires: pkgconfig(glib-2.0) BuildRequires: pkgconfig(dbus-glib-1) -BuildRequires: pkgconfig(sqlite3) -BuildRequires: pkgconfig(x11) BuildRequires: pkgconfig(bundle) BuildRequires: pkgconfig(dlog) BuildRequires: pkgconfig(libprivilege-control) BuildRequires: pkgconfig(vconf) BuildRequires: pkgconfig(libsmack) -BuildRequires: pkgconfig(aul) -BuildRequires: libcap-devel +BuildRequires: pkgconfig(pkgmgr-info) +BuildRequires: pkgconfig(security-manager) +%if "%{?profile}" == "wearable" +BuildRequires: pkgconfig(libsystemd-daemon) +%define appfw_feature_socket_activation 1 +%else +%if "%{?profile}" == "mobile" +BuildRequires: pkgconfig(libsystemd-daemon) +%define appfw_feature_socket_activation 1 +%else +%if "%{?profile}" == "tv" +%define appfw_feature_socket_activation 0 +%endif +%endif +%endif %description Debug launchpad @@ -33,19 +47,26 @@ Debug launchpad %setup -q %build -%ifarch %{ix86} -cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DARCH=x86 -%else -cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DARCH=arm +%if 0%{?appfw_feature_socket_activation} +_APPFW_FEATURE_SOCKET_ACTIVATION=ON %endif + +cmake -DCMAKE_INSTALL_PREFIX=%{_prefix} \ + -D_APPFW_FEATURE_SOCKET_ACTIVATION:BOOL=${_APPFW_FEATURE_SOCKET_ACTIVATION} \ + . + make %{?jobs:-j%jobs} %install rm -rf %{buildroot} %make_install -mkdir -p %{buildroot}/usr/share/license -cp LICENSE.APLv2 %{buildroot}/usr/share/license/%{name} +%if 0%{?appfw_feature_socket_activation} +mkdir -p %{buildroot}%{_unitdir_user}/sockets.target.wants +install -m 0644 %{SOURCE1} %{buildroot}%{_unitdir_user}/debug-launchpad.service +install -m 0644 %{SOURCE2} %{buildroot}%{_unitdir_user}/debug-launchpad.socket +ln -s ../debug-launchpad.socket %{buildroot}%{_unitdir_user}/sockets.target.wants/debug-launchpad.socket +%endif %clean rm -rf %{buildroot} @@ -53,5 +74,11 @@ rm -rf %{buildroot} %post %files -%attr(0755, root, root) %{_bindir}/debug_launchpad_preloading_preinitializing_daemon -/usr/share/license/%{name} +%license LICENSE +%manifest debug-launchpad.manifest +%caps(cap_mac_admin,cap_mac_override,cap_setgid=ei) %{_bindir}/debug_launchpad_preloading_preinitializing_daemon +%if 0%{?appfw_feature_socket_activation} +%{_unitdir_user}/debug-launchpad.service +%{_unitdir_user}/debug-launchpad.socket +%{_unitdir_user}/sockets.target.wants/debug-launchpad.socket +%endif diff --git a/src/app_sock.c b/src/app_sock.c deleted file mode 100755 index 1029ab4..0000000 --- a/src/app_sock.c +++ /dev/null @@ -1,524 +0,0 @@ -/* - * debug-launchpad - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungmin Cho , Gwangho Hwang - * - * 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. - * - */ - - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "app_sock.h" -#include "simple_util.h" - -static int __connect_client_sock(int sockfd, const struct sockaddr *saptr, socklen_t salen, - int nsec); - - -static inline void __set_sock_option(int fd, int cli) -{ - int size; - struct timeval tv = { 3, 200 * 1000 }; /* 3.2 sec */ - - size = AUL_SOCK_MAXBUFF; - setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)); - setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)); - if (cli) - setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); -} - -int __create_server_sock(int pid) -{ - struct sockaddr_un saddr; - struct sockaddr_un p_saddr; - int fd; - mode_t orig_mask; - - /* Create basedir for our sockets */ - orig_mask = umask(0); - (void) mkdir(AUL_SOCK_PREFIX, S_IRWXU | S_IRWXG | S_IRWXO | S_ISVTX); - umask(orig_mask); - - fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); - /* support above version 2.6.27*/ - if (fd < 0) { - if (errno == EINVAL) { - fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (fd < 0) { - _E("second chance - socket create error"); - return -1; - } - } else { - _E("socket error"); - return -1; - } - } - - memset(&saddr, 0, sizeof(saddr)); - saddr.sun_family = AF_UNIX; - snprintf(saddr.sun_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, pid); - unlink(saddr.sun_path); - - /* labeling to socket for SMACK */ - if(getuid() == 0) { // this is meaningful iff current user is ROOT - if(smack_fsetlabel(fd, "@", SMACK_LABEL_IPOUT) != 0) { - /* in case of unsupported filesystem on 'socket' */ - /* or permission error by using 'emulator', bypass*/ - if((errno != EOPNOTSUPP) && (errno != EPERM)) { - _E("labeling to socket(IPOUT) error"); - close(fd); - return -1; - } - } - if(smack_fsetlabel(fd, "*", SMACK_LABEL_IPIN) != 0) { - /* in case of unsupported filesystem on 'socket' */ - /* or permission error by using 'emulator', bypass*/ - if((errno != EOPNOTSUPP) && (errno != EPERM)) { - _E("labeling to socket(IPIN) error"); - close(fd); - return -1; - } - } - } - - if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { - _E("bind error"); - close(fd); - return -1; - } - - if (chmod(saddr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) { - /* Flawfinder: ignore*/ - _E("failed to change the socket permission"); - close(fd); - return -1; - } - - __set_sock_option(fd, 0); - - if (listen(fd, 128) == -1) { - _E("listen error"); - close(fd); - return -1; - } - - /* support app launched by shell script */ - /*if (pid != LAUNCHPAD_PID) { - int pgid; - pgid = getpgid(pid); - if (pgid > 1) { - snprintf(p_saddr.sun_path, UNIX_PATH_MAX, "%s/%d", - AUL_SOCK_PREFIX, pgid); - if (link(saddr.sun_path, p_saddr.sun_path) < 0) { - if (errno == EEXIST) - _D("pg path - already exists"); - else - _E("pg path - unknown create error"); - } - } - }*/ - - return fd; -} - -int __create_client_sock(int pid) -{ - int fd = -1; - struct sockaddr_un saddr = { 0, }; - int retry = 1; - int ret = -1; - - fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); - /* support above version 2.6.27*/ - if (fd < 0) { - if (errno == EINVAL) { - fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (fd < 0) { - _E("second chance - socket create error"); - return -1; - } - } else { - _E("socket error"); - return -1; - } - } - - saddr.sun_family = AF_UNIX; - snprintf(saddr.sun_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, pid); - retry_con: - ret = __connect_client_sock(fd, (struct sockaddr *)&saddr, sizeof(saddr), - 100 * 1000); - if (ret < -1) { - _E("maybe peer not launched or peer daed\n"); - if (retry > 0) { - usleep(100 * 1000); - retry--; - goto retry_con; - } - } - if (ret < 0) { - close(fd); - return -1; - } - - __set_sock_option(fd, 1); - - return fd; -} - -static int __connect_client_sock(int fd, const struct sockaddr *saptr, socklen_t salen, - int nsec) -{ - int flags; - int ret; - int error; - socklen_t len; - fd_set readfds; - fd_set writefds; - struct timeval timeout; - - flags = fcntl(fd, F_GETFL, 0); - fcntl(fd, F_SETFL, flags | O_NONBLOCK); - - error = 0; - if ((ret = connect(fd, (struct sockaddr *)saptr, salen)) < 0) { - if (errno != EAGAIN && errno != EINPROGRESS) { - fcntl(fd, F_SETFL, flags); - return (-2); - } - } - - /* Do whatever we want while the connect is taking place. */ - if (ret == 0) - goto done; /* connect completed immediately */ - - FD_ZERO(&readfds); - FD_SET(fd, &readfds); - writefds = readfds; - timeout.tv_sec = 0; - timeout.tv_usec = nsec; - - if ((ret = select(fd + 1, &readfds, &writefds, NULL, - nsec ? &timeout : NULL)) == 0) { - close(fd); /* timeout */ - errno = ETIMEDOUT; - return (-1); - } - - if (FD_ISSET(fd, &readfds) || FD_ISSET(fd, &writefds)) { - len = sizeof(error); - if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &error, &len) < 0) - return (-1); /* Solaris pending error */ - } else - return (-1); /* select error: sockfd not set*/ - - done: - (void) fcntl(fd, F_SETFL, flags); - if (error) { - close(fd); - errno = error; - return (-1); - } - return (0); -} - -/** - * @brief Send data (in raw) to the process with 'pid' via socket - */ -int __app_send_raw(int pid, int cmd, unsigned char *kb_data, int datalen) -{ - int fd; - int len; - int ret; - int res = 0; - app_pkt_t *pkt = NULL; - - if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) { - _E("keybundle error\n"); - return -EINVAL; - } - - _D("pid(%d) : cmd(%d)", pid, cmd); - - fd = __create_client_sock(pid); - if (fd < 0) - return -ECOMM; - - pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF); - if (NULL == pkt) { - _E("Malloc Failed!"); - return -ENOMEM; - } - memset(pkt, 0, AUL_SOCK_MAXBUFF); - - pkt->cmd = cmd; - pkt->len = datalen; - memcpy(pkt->data, kb_data, datalen); - - if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) { - _E("sendto() failed - %d %d (errno %d)", len, datalen + 8, errno); - if(len > 0) { - while (len != datalen + 8) { - ret = send(fd, &pkt->data[len-8], datalen + 8 - len, 0); - if (ret < 0) { - _E("second sendto() failed - %d %d (errno %d)", ret, datalen + 8, errno); - if (errno == EPIPE) { - _E("pid:%d, fd:%d\n", pid, fd); - } - close(fd); - if (pkt) { - free(pkt); - pkt = NULL; - } - return -ECOMM; - } - len += ret; - _D("sendto() len - %d %d", len, datalen + 8); - } - } else { - if (errno == EPIPE) { - _E("pid:%d, fd:%d\n", pid, fd); - } - close(fd); - if (pkt) { - free(pkt); - pkt = NULL; - } - return -ECOMM; - } - } - if (pkt) { - free(pkt); - pkt = NULL; - } - - len = recv(fd, &res, sizeof(int), 0); - if (len == -1) { - if (errno == EAGAIN) { - _E("recv timeout \n"); - res = -EAGAIN; - } else { - _E("recv error\n"); - res = -ECOMM; - } - } - close(fd); - - return res; -} - -int __app_send_raw_with_noreply(int pid, int cmd, unsigned char *kb_data, int datalen) -{ - int fd; - int len; - int ret; - int res = 0; - app_pkt_t *pkt = NULL; - - if (kb_data == NULL || datalen > AUL_SOCK_MAXBUFF - 8) { - _E("keybundle error\n"); - return -EINVAL; - } - - _D("pid(%d) : cmd(%d)", pid, cmd); - - fd = __create_client_sock(pid); - if (fd < 0) - return -ECOMM; - - pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF); - if (NULL == pkt) { - _E("Malloc Failed!"); - return -ENOMEM; - } - memset(pkt, 0, AUL_SOCK_MAXBUFF); - - pkt->cmd = cmd; - pkt->len = datalen; - memcpy(pkt->data, kb_data, datalen); - - if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) { - _E("sendto() failed - %d %d (errno %d)", len, datalen + 8, errno); - if(len > 0) { - while (len != datalen + 8) { - ret = send(fd, &pkt->data[len-8], datalen + 8 - len, 0); - if (ret < 0) { - _E("second sendto() failed - %d %d (errno %d)", ret, datalen + 8, errno); - if (errno == EPIPE) { - _E("pid:%d, fd:%d\n", pid, fd); - } - close(fd); - if (pkt) { - free(pkt); - pkt = NULL; - } - return -ECOMM; - } - len += ret; - _D("sendto() len - %d %d", len, datalen + 8); - } - } else { - if (errno == EPIPE) { - _E("pid:%d, fd:%d\n", pid, fd); - } - close(fd); - if (pkt) { - free(pkt); - pkt = NULL; - } - return -ECOMM; - } - } - if (pkt) { - free(pkt); - pkt = NULL; - } - - close(fd); - - return res; -} - -app_pkt_t *__app_recv_raw(int fd, int *clifd, struct ucred *cr) -{ - int len; - int ret; - struct sockaddr_un aul_addr = { 0, }; - int sun_size; - app_pkt_t *pkt = NULL; - int cl = sizeof(struct ucred); - - sun_size = sizeof(struct sockaddr_un); - - if ((*clifd = accept(fd, (struct sockaddr *)&aul_addr, - (socklen_t *) &sun_size)) == -1) { - if (errno != EINTR) - _E("accept error"); - return NULL; - } - - if (getsockopt(*clifd, SOL_SOCKET, SO_PEERCRED, cr, - (socklen_t *) &cl) < 0) { - _E("peer information error"); - close(*clifd); - return NULL; - } - - pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF); - if(pkt == NULL) { - close(*clifd); - return NULL; - } - memset(pkt, 0, AUL_SOCK_MAXBUFF); - - __set_sock_option(*clifd, 1); - - retry_recv: - /* receive single packet from socket */ - len = recv(*clifd, pkt, AUL_SOCK_MAXBUFF, 0); - if (len < 0) - if (errno == EINTR) - goto retry_recv; - - if (len < 8) { - _E("recv error %d %d", len, pkt->len); - free(pkt); - close(*clifd); - return NULL; - } - - while( len != (pkt->len + 8) ) { - ret = recv(*clifd, &pkt->data[len-8], AUL_SOCK_MAXBUFF, 0); - if (ret < 0) { - _E("recv error %d %d", len, pkt->len); - free(pkt); - close(*clifd); - return NULL; - } - len += ret; - _D("recv len %d %d", len, pkt->len); - } - - return pkt; -} - -app_pkt_t *__app_send_cmd_with_result(int pid, int cmd, unsigned char *kb_data, int datalen) -{ - int fd; - int len; - app_pkt_t *pkt = NULL; - - fd = __create_client_sock(pid); - if (fd < 0) - return NULL; - - pkt = (app_pkt_t *) malloc(sizeof(char) * AUL_SOCK_MAXBUFF); - if (NULL == pkt) { - _E("Malloc Failed!"); - return NULL; - } - memset(pkt, 0, AUL_SOCK_MAXBUFF); - - pkt->cmd = cmd; - pkt->len = datalen; - if(kb_data) { - memcpy(pkt->data, kb_data, datalen); - } - - if ((len = send(fd, pkt, datalen + 8, 0)) != datalen + 8) { - _E("sendto() failed - %d", len); - if (errno == EPIPE) { - _E("pid:%d, fd:%d\n", pid, fd); - } - close(fd); - - free(pkt); - return NULL; - } - -retry_recv: - /* receive single packet from socket */ - len = recv(fd, pkt, AUL_SOCK_MAXBUFF, 0); - if (len == -1) { - if (errno == EAGAIN) { - _E("recv timeout \n"); - free(pkt); - close(fd); - return NULL; - } else if (errno == EINTR) { - goto retry_recv; - } else { - _E("recv error %s\n", strerror(errno)); - free(pkt); - close(fd); - return NULL; - } - } else - _D("recv result = %d", len); - close(fd); - - return pkt; -} - - diff --git a/src/common.c b/src/common.c new file mode 100644 index 0000000..a84ac6a --- /dev/null +++ b/src/common.c @@ -0,0 +1,759 @@ +/* + * Copyright (c) 2015 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 +#ifdef _APPFW_FEATURE_SOCKET_ACTIVATION +#include +#endif /* _APPFW_FEATURE_SOCKET_ACTIVATION */ + +#include "common.h" +#include "debug_util.h" +#include "defs.h" + +#define MAX_PATH_LEN 1024 +#define BINSH_NAME "/bin/sh" +#define BINSH_SIZE 7 +#define VALGRIND_NAME "/home/developer/sdk_tools/valgrind/usr/bin/valgrind" +#define VALGRIND_SIZE 51 +#define BASH_NAME "/bin/bash" +#define BASH_SIZE 9 +#define OPROFILE_NAME "/usr/bin/oprofile_command" +#define OPROFILE_SIZE 25 +#define OPTION_VALGRIND_NAME "valgrind" +#define OPTION_VALGRIND_SIZE 8 +#define MAX_CMD_BUFSZ 1024 +#define PATH_TMP "/tmp" +#define PATH_DATA "/data" +#define AUL_PKT_HEADER_SIZE (sizeof(int) + sizeof(int)) + +static void __set_sock_option(int fd, int cli) +{ + int size; + struct timeval tv = { 5, 200 * 1000 }; /* 5.2 sec */ + + size = AUL_SOCK_MAXBUFF; + setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)); + setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size)); + if (cli) + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); +} + +#ifdef _APPFW_FEATURE_SOCKET_ACTIVATION +static int __create_sock_activation(void) +{ + int listen_fds; + + listen_fds = sd_listen_fds(0); + if (listen_fds == 1) + return SD_LISTEN_FDS_START; + else if (listen_fds > 1) + _E("Too many file descriptors received."); + else + _E("There is no socket stream"); + + return -1; +} +#endif /* _APPFW_FEATURE_SOCKET_ACTIVATION */ + +static int __create_server_socket(void) +{ + struct sockaddr_un saddr; + int fd; + + fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0); + /* support above version 2.6.27 */ + if (fd < 0) { + if (errno == EINVAL) { + fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + _E("second chance - socket create error"); + return -1; + } + } else { + _E("socket error"); + return -1; + } + } + + memset(&saddr, 0, sizeof(saddr)); + saddr.sun_family = AF_UNIX; + snprintf(saddr.sun_path, sizeof(saddr.sun_path), + "%s/%d/.debug-launchpad-sock", + SOCKET_PATH, getuid()); + unlink(saddr.sun_path); + + if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { + _E("bind error"); + close(fd); + return -1; + } + + if (chmod(saddr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) { + /* Flawfinder: ignore */ + _E("Failed to change the socket permission"); + close(fd); + return -1; + } + + __set_sock_option(fd, 0); + + if (listen(fd, 128) == -1) { + _E("listen error"); + close(fd); + return -1; + } + + return fd; +} + +int _create_server_sock(void) +{ + int fd = -1; + +#ifdef _APPFW_FEATURE_SOCKET_ACTIVATION + fd = __create_sock_activation(); +#endif /* _APPFW_FEATURE_SOCKET_ACTIAVTION */ + if (fd < 0) { + fd = __create_server_socket(); + if (fd < 0) { + _E("server sock error %d", fd); + return -1; + } + } + + return fd; +} + +app_pkt_t *_recv_pkt_raw(int fd, int *clifd, struct ucred *cr) +{ + int len; + int ret; + struct sockaddr_un aul_addr = {0, }; + int sun_size; + app_pkt_t *pkt = NULL; + int cl = sizeof(struct ucred); + unsigned char buf[AUL_SOCK_MAXBUFF]; + int cmd; + int datalen; + + sun_size = sizeof(struct sockaddr_un); + + if ((*clifd = accept(fd, (struct sockaddr *)&aul_addr, + (socklen_t *)&sun_size)) == -1) { + if (errno != EINTR) + _E("accept error"); + return NULL; + } + + if (getsockopt(*clifd, SOL_SOCKET, SO_PEERCRED, cr, + (socklen_t *)&cl) < 0) { + _E("peer information error"); + close(*clifd); + return NULL; + } + + __set_sock_option(*clifd, 1); + +retry_recv: + /* receive header(cmd, datalen) */ + len = recv(*clifd, buf, AUL_PKT_HEADER_SIZE, 0); + if (len < 0) + if (errno == EINTR) + goto retry_recv; + + if (len < AUL_PKT_HEADER_SIZE) { + _E("recv error"); + close(*clifd); + return NULL; + } + memcpy(&cmd, buf, sizeof(int)); + memcpy(&datalen, buf + sizeof(int), sizeof(int)); + + /* allocate for a null byte */ + pkt = (app_pkt_t *)calloc(1, AUL_PKT_HEADER_SIZE + datalen + 1); + if (pkt == NULL) { + close(*clifd); + return NULL; + } + pkt->cmd = cmd; + pkt->len = datalen; + + len = 0; + while (len != pkt->len) { + ret = recv(*clifd, pkt->data + len, pkt->len - len, 0); + if (ret < 0) { + _E("recv error %d %d", len, pkt->len); + free(pkt); + close(*clifd); + return NULL; + } + len += ret; + _D("recv len %d %d", len, pkt->len); + } + + return pkt; +} + +int _send_pkt_raw(int client_fd, app_pkt_t *pkt) +{ + int send_ret = 0; + int pkt_size = 0; + + if (client_fd == -1 || pkt == NULL) { + _E("arguments error!"); + return -1; + } + + pkt_size = sizeof(pkt->cmd) + sizeof(pkt->len) + pkt->len; + + send_ret = send(client_fd, pkt, pkt_size, 0); + _D("send(%d) : %d / %d", client_fd, send_ret, pkt_size); + + if (send_ret == -1) { + _E("send error!"); + return -1; + } else if (send_ret != pkt_size) { + _E("send byte fail!"); + return -1; + } + + return 0; +} + +static char *__appinfo_get_app_path(appinfo_t *appinfo) +{ + int i = 0; + int path_len = -1; + char *tmp_app_path; + + if (appinfo == NULL || appinfo->app_path == NULL) + return NULL; + + while (appinfo->app_path[i] != 0) { + if (appinfo->app_path[i] == ' ' + || appinfo->app_path[i] == '\t') { + path_len = i; + break; + } + + i++; + } + + if (path_len == 0) { + free(appinfo->app_path); + appinfo->app_path = NULL; + } else if (path_len > 0) { + tmp_app_path = (char *)malloc(sizeof(char) * (path_len + 1)); + if (tmp_app_path == NULL) + return NULL; + + snprintf(tmp_app_path, path_len + 1, "%s", appinfo->app_path); + free(appinfo->app_path); + appinfo->app_path = tmp_app_path; + } + + return appinfo->app_path; +} + +appinfo_t *_appinfo_create(bundle *kb) +{ + appinfo_t *appinfo; + const char *ptr; + + appinfo = (appinfo_t *)calloc(1, sizeof(appinfo_t)); + if (appinfo == NULL) + return NULL; + + ptr = bundle_get_val(kb, AUL_K_APPID); + if (ptr) + appinfo->appid = strdup(ptr); + ptr = bundle_get_val(kb, AUL_K_PACKAGETYPE); + if (ptr) + appinfo->pkg_type = strdup(ptr); + ptr = bundle_get_val(kb, AUL_K_HWACC); + if (ptr) + appinfo->hwacc = strdup(ptr); + ptr = bundle_get_val(kb, AUL_K_PKGID); + if (ptr) + appinfo->debug_appid = strdup(ptr); + ptr = bundle_get_val(kb, AUL_K_TASKMANAGE); + if (ptr) + appinfo->taskmanage = strdup(ptr); + ptr = bundle_get_val(kb, AUL_K_COMP_TYPE); + if (ptr) + appinfo->comp_type = strdup(ptr); + ptr = bundle_get_val(kb, AUL_K_EXEC); + if (ptr) + appinfo->app_path = strdup(ptr); + if (appinfo->app_path) + appinfo->original_app_path = strdup(appinfo->app_path); + + if (__appinfo_get_app_path(appinfo) == NULL) { + _appinfo_free(appinfo); + return NULL; + } + + return appinfo; +} + +void _appinfo_free(appinfo_t *appinfo) +{ + if (appinfo == NULL) + return; + + if (appinfo->appid) + free(appinfo->appid); + if (appinfo->app_path) + free(appinfo->app_path); + if (appinfo->original_app_path) + free(appinfo->original_app_path); + if (appinfo->pkg_type) + free(appinfo->pkg_type); + if (appinfo->hwacc) + free(appinfo->hwacc); + if (appinfo->taskmanage) + free(appinfo->taskmanage); + if (appinfo->debug_appid) + free(appinfo->debug_appid); + if (appinfo->comp_type) + free(appinfo->comp_type); + + free(appinfo); +} + +static int __parse_app_path(const char *arg, char *out, int out_size) +{ + register int i; + int state = 1; + char *start_out = out; + + if (arg == NULL || out == NULL) + return 0; + + for (i = 0; out_size > 1; i++) { + switch (state) { + case 1: + switch (arg[i]) { + case ' ': + case '\t': + state = 5; + break; + case '\0': + state = 7; + break; + case '\"': + state = 2; + break; + case '\\': + state = 4; + break; + default: + *out = arg[i]; + out++; + out_size--; + break; + } + break; + case 2: /* escape start */ + switch (arg[i]) { + case '\0': + state = 6; + break; + case '\"': + state = 1; + break; + default: + *out = arg[i]; + out++; + out_size--; + break; + } + break; + case 4: /* character escape */ + if (arg[i] == '\0') + state = 6; + else { + *out = arg[i]; + out++; + out_size--; + state = 1; + } + break; + case 5: /* token */ + if (out != start_out) { + *out = '\0'; + out_size--; + return i; + } + i--; + state = 1; + break; + case 6: + return -1; /* error */ + case 7: /* terminate */ + *out = '\0'; + out_size--; + return 0; + default: + state = 6; + break; /* error */ + } + } + + if (out_size == 1) + *out = '\0'; + + /* Buffer overflow*/ + return -2; +} + +void _modify_bundle(bundle *kb, int caller_pid, appinfo_t *appinfo, int cmd) +{ + char *ptr; + char exe[MAX_PATH_LEN]; + int flag; + char key[256]; + char value[256]; + + bundle_del(kb, AUL_K_APPID); + bundle_del(kb, AUL_K_EXEC); + bundle_del(kb, AUL_K_PACKAGETYPE); + bundle_del(kb, AUL_K_HWACC); + bundle_del(kb, AUL_K_PKGID); + bundle_del(kb, AUL_K_TASKMANAGE); + bundle_del(kb, AUL_K_COMP_TYPE); + + /* Parse app_path to retrieve default bundle */ + if (cmd == PAD_CMD_LAUNCH) { + ptr = appinfo->original_app_path; + flag = __parse_app_path(ptr, exe, sizeof(exe)); + if (flag > 0) { + ptr += flag; + SECURE_LOGD("parsing app_path: EXEC - %s", exe); + + do { + flag = __parse_app_path(ptr, key, sizeof(key)); + if (flag <= 0) + break; + ptr += flag; + + flag = __parse_app_path(ptr, value, sizeof(value)); + if (flag < 0) + break; + ptr += flag; + + /* bundle_del(kb, key); */ + bundle_add(kb, key, value); + } while (flag > 0); + } else if (flag == 0) { + _D("parsing app_path: No arguments"); + } else { + _D("parsing app_path: Invalid argument"); + } + + } +} + +static void __set_sdk_env(const char *appid, const char *value) +{ + char buf[MAX_LOCAL_BUFSZ]; + char *token = NULL; + + _D("key: %s / value: %s", AUL_K_SDK, value); + /* http://gcc.gnu.org/onlinedocs/gcc/Cross_002dprofiling.html*/ + /* GCOV_PREFIX contains the prefix to add to the absolute paths */ + /* in the object file. Prefix can be absolute, or relative.*/ + /* The default is no prefix. */ + /* GCOV_PREFIX_STRIP indicates the how many initial directory names */ + /* to stripoff the hardwired absolute paths. Default value is 0. */ + if (strncmp(value, SDK_CODE_COVERAGE, strlen(value)) == 0) { + token = strrchr(appid, '.'); + if (token == NULL) + return; + token++; + + snprintf(buf, sizeof(buf), PATH_TMP"/%s"PATH_DATA, token); + setenv("GCOV_PREFIX", buf, 1); + setenv("GCOV_PREFIX_STRIP", "0", 1); + } else if (strncmp(value, SDK_DYNAMIC_ANALYSIS, strlen(value)) == 0) { + setenv("LD_PRELOAD", PATH_DA_SO, 1); + } +} + +void _set_env(appinfo_t *appinfo, bundle *kb) +{ + const char *str; + const char **str_array = NULL; + int len = 0; + int i; + + setenv("PKG_NAME", appinfo->appid, 1); + + str = bundle_get_val(kb, AUL_K_STARTTIME); + if (str) + setenv("APP_START_TIME", str, 1); + if (appinfo->hwacc) + setenv("HWACC", appinfo->hwacc, 1); + if (appinfo->taskmanage) + setenv("TASKMANAGE", appinfo->taskmanage, 1); + + if (bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) + str_array = bundle_get_str_array(kb, AUL_K_SDK, &len); + else { + str = bundle_get_val(kb, AUL_K_SDK); + if (str) { + str_array = &str; + len = 1; + } + } + + for (i = 0; i < len; i++) + __set_sdk_env(appinfo->appid, str_array[i]); +} + +static char **__add_arg(bundle * kb, char **argv, int *margc, const char *key) +{ + const char *str = NULL; + const char **str_array = NULL; + int len = 0; + int i; + char **new_argv = NULL; + + if (bundle_get_type(kb, key) & BUNDLE_TYPE_ARRAY) + str_array = bundle_get_str_array(kb, key, &len); + else { + str = bundle_get_val(kb, key); + if (str) { + str_array = &str; + len = 1; + } + } + + if (str_array) { + if (strncmp(key, DLP_K_DEBUG_ARG, strlen(key)) == 0 + || strncmp(key, DLP_K_VALGRIND_ARG, strlen(key)) == 0) { + new_argv = (char **)realloc(argv, + sizeof(char *) * (*margc + len + 2)); + if (new_argv == NULL) { + _E("Failed to realloc (key: %s)", key); + exit(-1); + } + + for (i = *margc + len + 1; i - (len + 1) >= 0; i--) + new_argv[i] = new_argv[i - (len + 1)]; + + /* need to add new_argv[0] */ + for (i = 0; i < len; i++) + new_argv[1 + i] = strdup(str_array[i]); + + len++; /* gdbserver or valgrind */ + } else if (strncmp(key, DLP_K_ATTACH_ARG, strlen(key)) == 0) { + new_argv = (char **)malloc((len + 2) * sizeof(char *)); + if (new_argv == NULL) { + _E("Failed to malloc (key: %s)", key); + exit(-1); + } + + for (i = 0; i < len; i++) + new_argv[1 + i] = strdup(str_array[i]); + + *margc = 0; + len = len + 1; + } else { + new_argv = (char **)realloc(argv, + sizeof(char *) * (*margc + len + 1)); + if (new_argv == NULL) { + _E("Failed to realloc (key: %s)", key); + exit(-1); + } + + for (i = 0; i < len; i++) + new_argv[*margc + i] = strdup(str_array[i]); + } + + new_argv[*margc + len] = NULL; + *margc += len; + } else { + if (strncmp(key, DLP_K_DEBUG_ARG, strlen(key)) == 0 + || strncmp(key, DLP_K_VALGRIND_ARG, strlen(key)) == 0) { + new_argv = (char **)realloc(argv, + sizeof(char *) * (*margc + 2)); + if (new_argv == NULL) { + _E("Failed to realloc (key: %s)", key); + exit(-1); + } + + for (i = *margc + 1; i - 1 >= 0; i--) + new_argv[i] = new_argv[i - 1]; + + /* need to add new_argv[0] */ + (*margc)++; + } + } + + if (new_argv == NULL) + return argv; + + return new_argv; +} + +char **_create_argc_argv(bundle *kb, int *margc, const char *app_path) +{ + char **argv = NULL; + char **new_argv = NULL; + int argc; + int i; + char buf[MAX_LOCAL_BUFSZ]; + const char *str; + const char **str_array = NULL; + int len = 0; + + argc = bundle_export_to_argv(kb, &argv); + if (argv) + argv[0] = strdup(app_path); + else { + _E("bundle_export_to_argv() is failed."); + return NULL; + } + + if (bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) + str_array = bundle_get_str_array(kb, AUL_K_SDK, &len); + else { + str = bundle_get_val(kb, AUL_K_SDK); + if (str) { + str_array = &str; + len = 1; + } + } + + for (i = 0; i < len; i++) { + if (str_array[i] == NULL) + break; + + if (strncmp(str_array[i], SDK_DEBUG, strlen(str_array[i])) == 0) { + if (argv[0]) + free(argv[0]); + snprintf(buf, sizeof(buf), "%s.exe", app_path); + /* this code is added because core app don't have '.exe' excutable */ + /* if '.exe' not exist then use app_path */ + if (access(buf, F_OK) != 0) + argv[0] = strdup(app_path); + else + argv[0] = strdup(buf); + + new_argv = __add_arg(kb, argv, &argc, DLP_K_DEBUG_ARG); + new_argv[0] = strdup(PATH_GDBSERVER); + argv = new_argv; + } else if (strncmp(str_array[i], SDK_VALGRIND, strlen(str_array[i])) == 0) { + new_argv = __add_arg(kb, argv, &argc, DLP_K_VALGRIND_ARG); + new_argv[0] = strdup(PATH_VALGRIND); + argv = new_argv; + } else if (strncmp(str_array[i], SDK_UNIT_TEST, strlen(str_array[i])) == 0) { + new_argv = __add_arg(kb, argv, &argc, DLP_K_UNIT_TEST_ARG); + argv = new_argv; + } else if (strncmp(str_array[i], SDK_ATTACH, strlen(str_array[i])) == 0) { + new_argv = __add_arg(kb, argv, &argc, DLP_K_ATTACH_ARG); + new_argv[0] = strdup(PATH_GDBSERVER); + argv = new_argv; + } + + } + + *margc = argc; + + return argv; +} + +static int __read_proc(const char *path, char *buf, int size) +{ + int fd; + int ret; + + if (buf == NULL || path == NULL) + return -1; + + fd = open(path, O_RDONLY); + if (fd < 0) + return -1; + + ret = read(fd, buf, size - 1); + if (ret <= 0) { + close(fd); + return -1; + } else + buf[ret] = 0; + + close(fd); + + return ret; +} + +char *_proc_get_cmdline_bypid(int pid) +{ + char buf[MAX_CMD_BUFSZ]; + int ret; + char* ptr = NULL; + + snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid); + ret = __read_proc(buf, buf, sizeof(buf)); + if (ret <= 0) + return NULL; + + /* support app launched by shell script*/ + if (strncmp(buf, BINSH_NAME, BINSH_SIZE) == 0) + return strdup(&buf[BINSH_SIZE + 1]); + else if (strncmp(buf, VALGRIND_NAME, VALGRIND_SIZE) == 0) { + /* buf comes with double null-terminated string */ + while (1) { + while (*ptr) + ptr++; + ptr++; + + if (!(*ptr)) + break; + + /* ignore trailing "--" */ + if (strncmp(ptr, "-", 1) != 0) + break; + } + + return strdup(ptr); + } else if (strncmp(buf, BASH_NAME, BASH_SIZE) == 0) { + if (strncmp(&buf[BASH_SIZE + 1], OPROFILE_NAME, OPROFILE_SIZE) == 0) { + if (strncmp(&buf[BASH_SIZE + OPROFILE_SIZE + 2], + OPTION_VALGRIND_NAME, OPTION_VALGRIND_SIZE) == 0) { + return strdup(&buf[BASH_SIZE + OPROFILE_SIZE + + OPTION_VALGRIND_SIZE + 3]); + } + } + } + + return strdup(buf); +} diff --git a/src/debug-launchpad.c b/src/debug-launchpad.c new file mode 100644 index 0000000..e951d4d --- /dev/null +++ b/src/debug-launchpad.c @@ -0,0 +1,578 @@ +/* + * Copyright (c) 2015 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 +#include +#include + +#include "common.h" +#include "signal_util.h" +#include "security_util.h" +#include "file_util.h" +#include "debug_util.h" +#include "perf.h" +#include "defs.h" + +#define AUL_PR_NAME 16 + +static int __real_send(int clifd, int ret) +{ + if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) { + if (errno == EPIPE) { + _E("send failed due to EPIPE.\n"); + close(clifd); + return -1; + } + + _E("send fail to client"); + } + + close(clifd); + + return 0; +} + +static void __send_result_to_caller(int clifd, int ret, const char* app_path) +{ + char *cmdline; + int wait_count; + int cmdline_changed = 0; + int cmdline_exist = 0; + char sock_path[PATH_MAX]; + + _W("Check app launching"); + + if (clifd == -1) + return; + + if (ret <= 1) { + _E("launching failed"); + __real_send(clifd, ret); + return; + } + + /* check normally was launched? */ + wait_count = 1; + do { + cmdline = _proc_get_cmdline_bypid(ret); + if (cmdline == NULL) { + _E("error founded when being launched with %d", ret); + if (cmdline_exist || cmdline_changed) { + _E("The app process might be terminated while we are wating %d", ret); + break; + } + } else if (strcmp(cmdline, app_path) == 0) { + /* Check app main loop is prepared or not */ + _D("-- now wait app mainloop creation --"); + free(cmdline); + cmdline_changed = 1; + + snprintf(sock_path, sizeof(sock_path), "%s/%d/%d", + SOCKET_PATH, getuid(), ret); + if (access(sock_path, F_OK) == 0) + break; + + } else { + _D("-- now wait cmdline changing --"); + cmdline_exist = 1; + free(cmdline); + } + + usleep(50 * 1000); /* 50ms sleep */ + wait_count++; + } while (wait_count <= 20); /* max 50*20ms will be sleep */ + + if ((!cmdline_exist) && (!cmdline_changed)) { + _E("abnormally launched"); + __real_send(clifd, -1); /* abnormally launched*/ + return; + } + + if (!cmdline_changed) + _E("process launched, but cmdline not changed"); + + if (__real_send(clifd, ret) < 0) { + if (kill(ret, SIGKILL) == -1) + _E("Failed to send SIGKILL: %d", errno); + } + + return; +} + +static int __prepare_exec(const char *appid, const char *app_path, + appinfo_t *appinfo, bundle *kb) +{ + char *file_name; + char process_name[AUL_PR_NAME]; + int ret; + const char *value; + + /* Set new session ID & new process group ID */ + /* In linux, child can set new session ID without check permission */ + setsid(); + + /* SET PRIVILEGES */ + value = bundle_get_val(kb, AUL_K_SDK); + if (value && strncmp(value, SDK_ATTACH, strlen(SDK_ATTACH) != 0)) { + _D("appid: %s / pkg_type: %s / app_path: %s", + appid, appinfo->pkg_type, app_path); + if ((ret = _set_access(appid)) != 0) { + _E("Failed to set privileges - check your package's credential: %d", ret); + return -1; + } + } + + /* SET DUMPABLE - for coredump */ + prctl(PR_SET_DUMPABLE, 1); + + /* SET PROCESS NAME */ + if (app_path == NULL) { + _D("app_path should not be NULL - check menu db"); + return -1; + } + + file_name = strrchr(app_path, '/') + 1; + if (file_name == NULL) { + _D("can't locate file name to execute"); + return -1; + } + + memset(process_name, '\0', AUL_PR_NAME); + snprintf(process_name, AUL_PR_NAME, "%s", file_name); + prctl(PR_SET_NAME, process_name); + + /* SET ENVIROMENT */ + _set_env(appinfo, kb); + + return 0; +} + +static int __prepare_fork(bundle *kb, const char *appid) +{ + const char *str = NULL; + const char **str_array = NULL; + int len = 0; + + if (bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) + str_array = bundle_get_str_array(kb, AUL_K_SDK, &len); + else { + str = bundle_get_val(kb, AUL_K_SDK); + if (str) { + str_array = &str; + len = 1; + } + } + + _prepare_debug_tool(kb, appid, str_array, len); + + return 0; +} + +static int __get_caller_pid(bundle *kb) +{ + const char *str; + int pid; + + str = bundle_get_val(kb, AUL_K_ORG_CALLER_PID); + if (str) + goto end; + + str = bundle_get_val(kb, AUL_K_CALLER_PID); + if (str == NULL) + return -1; + +end: + pid = atoi(str); + if (pid <= 1) + return -1; + + return pid; +} + +static int __redirect_stdfds(int caller_pid) +{ + char buf[PATH_MAX]; + int fd; + int ret = 0; + + /* stdout */ + snprintf(buf, sizeof(buf), "/proc/%d/fd/1", caller_pid); + fd = open(buf, O_WRONLY); + if (fd < 0) { + _E("Failed to open caller(%d) stdout", caller_pid); + ret = 1; + } else { + dup2(fd, 1); + close(fd); + } + + /* stderr */ + snprintf(buf, sizeof(buf), "/proc/%d/fd/2", caller_pid); + fd = open(buf, O_WRONLY); + if (fd < 0) { + _E("Failed to open caller(%d) stderr", caller_pid); + ret += 2; + } else { + dup2(fd, 2); + close(fd); + } + + return ret; +} + +static int __normal_fork_exec(int argc, char **argv) +{ + _D("start real fork and exec\n"); + + if (execv(argv[0], argv) < 0) { /* Flawfinder: ignore */ + if (errno == EACCES) + _E("such a file is no executable - %s", argv[0]); + else + _E("unknown executable error - %s", argv[0]); + + return -1; + } + + /* never reach */ + return 0; +} + +static void __real_launch(const char *app_path, bundle *kb) +{ + int app_argc; + char **app_argv; + int i; + + app_argv = _create_argc_argv(kb, &app_argc, app_path); + for (i = 0; i < app_argc; i++) + _D("input argument %d : %s##", i, app_argv[i]); + + PERF("setup argument done"); + + /* Temporary log: launch time checking */ + LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:launchpad:done]", app_path); + + __normal_fork_exec(app_argc, app_argv); +} + +static int __start_process(const char *appid, const char *app_path, + bundle *kb, appinfo_t *appinfo) +{ + char sock_path[PATH_MAX]; + int pid; + int max_fd; + int iter_fd; + + if (__prepare_fork(kb, appinfo->debug_appid) < 0) + return -1; + + pid = fork(); + if (pid == 0) { + PERF("fork done"); + _D("lock up test log(no error): fork done"); + + _signal_unblock_sigchld(); + _signal_fini(); + + max_fd = sysconf(_SC_OPEN_MAX); + for (iter_fd = 3; iter_fd <= max_fd; iter_fd++) + close(iter_fd); + + snprintf(sock_path, sizeof(sock_path), "%s/%d/%d", + SOCKET_PATH, getuid(), getpid()); + unlink(sock_path); + + if (__redirect_stdfds(__get_caller_pid(kb))) + _E("Failed to redirect caller fds"); + + PERF("prepare exec - fisrt done"); + _D("lock up test log(no error): prepare exec - first done"); + + if (__prepare_exec(appid, app_path, appinfo, kb) < 0) { + _E("preparing work fail to launch - can not launch %s", appid); + exit(-1); + } + + PERF("prepare exec - second done"); + _D("lock up test log(no error): prepare exec - second done"); + __real_launch(app_path, kb); + + exit(-1); + } + + _D("==> real launch pid: %d %s", pid, app_path); + + return pid; +} + +static gboolean __handle_sigchld(gpointer data) +{ + GPollFD *gpollfd = (GPollFD *)data; + int fd = gpollfd->fd; + struct signalfd_siginfo siginfo; + ssize_t s; + + do { + s = read(fd, &siginfo, sizeof(struct signalfd_siginfo)); + if (s == 0) + break; + + if (s != sizeof(struct signalfd_siginfo)) { + _E("error reading sigchld info"); + break; + } + + _debug_launchpad_sigchld(&siginfo); + } while (s > 0); + + return TRUE; +} + +static gboolean __handle_launch_event(gpointer data) +{ + GPollFD *gpollfd = (GPollFD *)data; + int fd = gpollfd->fd; + bundle *kb = NULL; + app_pkt_t *pkt = NULL; + appinfo_t *appinfo = NULL; + const char *app_path = NULL; + int pid = -1; + int clifd = -1; + struct ucred cr; + + pkt = _recv_pkt_raw(fd, &clifd, &cr); + if (pkt == NULL) { + _E("packet is NULL"); + return TRUE; + } + + kb = bundle_decode(pkt->data, pkt->len); + if (kb == NULL) { + _E("bundle decode error"); + goto end; + } + + INIT_PERF(kb); + PERF("packet processing start"); + + appinfo = _appinfo_create(kb); + if (appinfo == NULL) { + _E("_appinfo_create() is failed."); + goto end; + } + + app_path = appinfo->app_path; + if (app_path == NULL) { + _E("app_path is NULL"); + goto end; + } + + if (app_path[0] != '/') { + _E("app_path is not absolute path: %s", app_path); + goto end; + } + + _D("appid: %s", appinfo->appid); + _D("exec: %s", appinfo->app_path); + _D("debug appid: %s", appinfo->debug_appid); + _D("hwacc: %s", appinfo->hwacc); + + _modify_bundle(kb, cr.pid, appinfo, pkt->cmd); + if (appinfo->appid == NULL) { + _E("unable to get appid from appinfo"); + goto end; + } + + PERF("get package infomation & modify bundle done"); + + pid = __start_process(appinfo->appid, app_path, kb, appinfo); + +end: + __send_result_to_caller(clifd, pid, app_path); + + if (pid > 0) + _send_app_launch_signal(pid); + if (appinfo) + _appinfo_free(appinfo); + if (kb) + bundle_free(kb); + if (pkt) + free(pkt); + if (_get_valgrind_option()) + _wait_for_valgrind_output(); + + return TRUE; +} + +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 GSourceFuncs funcs = { + .prepare = __glib_prepare, + .check = __glib_check, + .dispatch = __glib_dispatch, + .finalize = NULL +}; + +static int __poll_fd(int fd, GSourceFunc callback) +{ + int r; + GPollFD *gpollfd; + GSource *src; + + src = g_source_new(&funcs, sizeof(GSource)); + if (src == NULL) { + _E("out of memory"); + return -1; + } + + gpollfd = (GPollFD *)g_malloc(sizeof(GPollFD)); + if (gpollfd == NULL) { + _E("out of memory"); + g_source_destroy(src); + return -1; + } + + gpollfd->fd = fd; + gpollfd->events = G_IO_IN; + + g_source_add_poll(src, gpollfd); + g_source_set_callback(src, callback, (gpointer)gpollfd, NULL); + 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 -1; + } + + return r; +} + +static int __init_sigchld_fd(void) +{ + int fd; + + fd = _signal_get_sigchld_fd(); + if (fd < 0) { + _E("Failed to get sigchld fd"); + return -1; + } + + if (__poll_fd(fd, (GSourceFunc)__handle_sigchld) < 0) { + close(fd); + return -1; + } + + return 0; +} + +static int __init_debug_launchpad_fd(int argc, char **argv) +{ + int fd; + + /* signal init */ + _signal_init(); + + /* create debug-launchpad socket */ + fd = _create_server_sock(); + if (fd < 0) { + _E("Failed to create server socket"); + return -1; + } + + if (__poll_fd(fd, (GSourceFunc)__handle_launch_event) < 0) { + close(fd); + return -1; + } + + return 0; +} + +static int __before_loop(int argc, char **argv) +{ + if (__init_sigchld_fd() < 0) { + _E("Failed to initialize sigchld fd."); + return -1; + } + + if (__init_debug_launchpad_fd(argc, argv) < 0) { + _E("Failed to initialize launchpad fd."); + return -1; + } + + return 0; +} + +int main(int argc, char **argv) +{ + GMainLoop *loop; + + loop = g_main_loop_new(NULL, FALSE); + if (loop == NULL) { + _E("Failed to create glib main loop."); + return -1; + } + + if (__before_loop(argc, argv) < 0) { + _E("Failed to initiailze debug-launchapd."); + return -1; + } + + g_main_loop_run(loop); + + return 0; +} diff --git a/src/debug_util.c b/src/debug_util.c new file mode 100644 index 0000000..5e9074e --- /dev/null +++ b/src/debug_util.c @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2015 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. + */ + +#include +#include +#include +#include +#include +#include + +#include "defs.h" +#include "common.h" +#include "file_util.h" +#include "security_util.h" +#include "debug_util.h" + +#define LABEL_SDBD "sdbd" +#define LABEL_NETWORK "system::debugging_network" + +#define POLL_VALGRIND_LOGFILE 0x00000001 +#define POLL_VALGRIND_XMLFILE 0x00000002 +#define POLL_VALGRIND_MASSIFFILE 0x00000004 + +static int gdbserver_pid = -1; +static int gdbserver_app_pid = -1; +static bool gdbserver = false; +static int valgrind_option = 0; + +bool _gdbserver_is_running(void) +{ + return gdbserver; +} + +int _get_gdbserver_pid(void) +{ + return gdbserver_pid; +} + +int _get_gdbserver_app_pid(void) +{ + return gdbserver_app_pid; +} + +int _get_valgrind_option(void) +{ + return valgrind_option; +} + +static int __check_pkginfo(const char *appid) +{ + int r; + bool preload = false; + char *storeclientid = NULL; + pkgmgrinfo_pkginfo_h handle; + + r = pkgmgrinfo_pkginfo_get_pkginfo(appid, &handle); + if (r != PMINFO_R_OK) { + _E("Failed to get pkginfo: %s", appid); + return -1; + } + + r = pkgmgrinfo_pkginfo_is_preload(handle, &preload); + if (r != PMINFO_R_OK) { + _E("Faield to check preload: %s", appid); + pkgmgrinfo_pkginfo_destroy_pkginfo(handle); + return -1; + } + + r = pkgmgrinfo_pkginfo_get_storeclientid(handle, &storeclientid); + if (r != PMINFO_R_OK) { + _E("Failed to get store client id: %s", appid); + pkgmgrinfo_pkginfo_destroy_pkginfo(handle); + return -1; + } + + if (preload == true || (storeclientid && storeclientid[0] != '\0')) { + _E("Debugging is not allowed"); + pkgmgrinfo_pkginfo_destroy_pkginfo(handle); + return -1; + } + + r = pkgmgrinfo_pkginfo_destroy_pkginfo(handle); + if (r != PMINFO_R_OK) { + _E("Failed to destroy pkginfo: %s", appid); + pkgmgrinfo_pkginfo_destroy_pkginfo(handle); + } + + return 0; +} + +static int __prepare_gdbserver(const char *appid) +{ + int r; + + r = __check_pkginfo(appid); + if (r < 0) + return -1; + + if (_apply_smack_rules(LABEL_SDBD, appid, "w")) + _E("Failed to apply smack rule %s %s w", LABEL_SDBD, appid); + + /* fixed debug-as fail issue (grant permission to use 10.0.2.2, 10.0.2.16) */ + if (_apply_smack_rules(appid, LABEL_NETWORK, "rw")) + _E("Failed to apply smack rule %s %s rw", appid, LABEL_NETWORK); + + if (_apply_smack_rules(LABEL_NETWORK, appid, "w")) + _E("Failed to apply smack rule %s %s w", LABEL_NETWORK, appid); + + r = dlp_chmod(PATH_GDBSERVER, S_IRUSR | S_IWUSR + | S_IXUSR | S_IRGRP | S_IXGRP + | S_IROTH | S_IXOTH, 1); + if (r != 0) + _W("Failed to set 755: %s", PATH_GDBSERVER); + + gdbserver = true; + + return 0; +} + +static int __prepare_valgrind(bundle *kb) +{ + const char *str; + const char **str_arr = NULL; + int len = 0; + int i; + + if (bundle_get_type(kb, DLP_K_VALGRIND_ARG) & BUNDLE_TYPE_ARRAY) + str_arr = bundle_get_str_array(kb, DLP_K_VALGRIND_ARG, &len); + else { + str = bundle_get_val(kb, DLP_K_VALGRIND_ARG); + if (str) { + str_arr = &str; + len = 1; + } + } + + for (i = 0; i < len; i++) { + if (str_arr[i] == NULL) + break; + + if (strncmp(str_arr[i], OPT_VALGRIND_LOGFILE_FIXED, + strlen(OPT_VALGRIND_LOGFILE_FIXED)) == 0) { + valgrind_option |= POLL_VALGRIND_LOGFILE; + if (access(PATH_VALGRIND_LOGFILE, F_OK) == 0) { + if (remove(PATH_VALGRIND_LOGFILE) != 0) + _W("Failed to remove %s", + PATH_VALGRIND_LOGFILE); + } + } else if (strncmp(str_arr[i], OPT_VALGRIND_XMLFILE_FIXED, + strlen(OPT_VALGRIND_XMLFILE_FIXED)) == 0) { + valgrind_option |= POLL_VALGRIND_XMLFILE; + if (access(PATH_VALGRIND_XMLFILE, F_OK) == 0) { + if (remove(PATH_VALGRIND_XMLFILE) != 0) + _W("Failed to remove %s", + PATH_VALGRIND_XMLFILE); + } + } else if (strncmp(str_arr[i], OPT_VALGRIND_MASSIFFILE_FIXED, + strlen(OPT_VALGRIND_MASSIFFILE_FIXED)) == 0) { + valgrind_option |= POLL_VALGRIND_MASSIFFILE; + if (access(PATH_VALGRIND_MASSIFFILE, F_OK) == 0) { + if (remove(PATH_VALGRIND_MASSIFFILE) != 0) + _W("Failed to remove %s", + PATH_VALGRIND_MASSIFFILE); + } + } + } + + return 0; +} + +int _prepare_debug_tool(bundle *kb, const char *appid, + const char **str_arr, int len) +{ + int i; + + if (appid == NULL || str_arr == NULL) + return -1; + + gdbserver = false; + gdbserver_pid = -1; + gdbserver_app_pid = -1; + valgrind_option = 0; + + for (i = 0; i < len; i++) { + if (str_arr[i] == NULL) + break; + + if (strncmp(str_arr[i], SDK_DEBUG, strlen(SDK_DEBUG)) == 0 + || strncmp(str_arr[i], SDK_ATTACH, strlen(SDK_ATTACH)) == 0) { + if (__prepare_gdbserver(appid) < 0) + return -1; + } else if (strncmp(str_arr[i], SDK_VALGRIND, strlen(SDK_VALGRIND)) == 0) { + __prepare_valgrind(kb); + } + } + + return 0; +} + +/* chmod and chsmack to read file without root privilege */ +void _change_file(const char *path) +{ + int r; + + r = dlp_chmod(path, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH, 0); + if (r) + _E("Failed to set 644: %s", path); + + r = _set_smack_access_label(path, "*"); + if (r) + _E("Failed to set smack label %s *", path); +} + +void _wait_for_valgrind_output(void) +{ + int wait_count = 1; + + do { + if (valgrind_option & POLL_VALGRIND_LOGFILE) { + if (access(PATH_VALGRIND_LOGFILE, F_OK) == 0) { + _change_file(PATH_VALGRIND_LOGFILE); + valgrind_option &= ~POLL_VALGRIND_LOGFILE; + } + } + + if (valgrind_option & POLL_VALGRIND_XMLFILE) { + if (access(PATH_VALGRIND_XMLFILE, F_OK) == 0) { + _change_file(PATH_VALGRIND_XMLFILE); + valgrind_option &= ~POLL_VALGRIND_XMLFILE; + } + } + + if (valgrind_option & POLL_VALGRIND_MASSIFFILE) { + if (access(PATH_VALGRIND_MASSIFFILE, F_OK) == 0) { + _change_file(PATH_VALGRIND_MASSIFFILE); + valgrind_option &= ~POLL_VALGRIND_MASSIFFILE; + } + } + + usleep(50 * 1000); /* 50ms */ + wait_count++; + } while (valgrind_option && wait_count <= 10); + + if (valgrind_option) + _E("Failed to wait for valgrind output file"); +} diff --git a/src/file_util.c b/src/file_util.c new file mode 100644 index 0000000..eb4cce9 --- /dev/null +++ b/src/file_util.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2015 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "file_util.h" + +static int recurse(const char *path, mode_t mode, + int (*fn)(const char *, mode_t, int)) +{ + struct stat st; + char dir[PATH_MAX]; + + if (path == NULL) + return -1; + + if (lstat(path, &st) == -1) + return -1; + + if (strrchr(path, '/') != NULL) { + int n = strlen(path)-strlen(strrchr(path, '/')); + if (n >= PATH_MAX) + return -1; + + strncpy(dir, path, n); + dir[n] = '\0'; + fn(dir, mode, 1); + return 0; + } + + return -1; +} + +int dlp_chmod(const char *path, mode_t mode, int recursive) +{ + int fd; + struct stat lstat_info; + struct stat fstat_info; +#ifdef HAVE_WIN32_PROC + fprintf(stderr, "error: dlp_chmod not implemented on Win32 (%s)\n", path); + return -1; +#else + + if (lstat(path, &lstat_info) == -1) + return -1; + + fd = open(path, O_WRONLY, S_IRWXU); + if (fd == -1) + return -1; + + if (fstat(fd, &fstat_info) == -1) { + close(fd); + return -1; + } + + /* this complex check is required because of 'chmod' security issue. */ + /* otherwise hacker can change other file's permission by using race condition and symbolic link. */ + if (lstat_info.st_mode == fstat_info.st_mode + && lstat_info.st_ino == fstat_info.st_ino + && lstat_info.st_dev == fstat_info.st_dev) { + if (fchmod(fd, mode) == -1) { + close(fd); + return -1; + } + } + + close(fd); + + if (recursive) + return recurse(path, mode, dlp_chmod); + + return 0; +#endif +} diff --git a/src/fileutils.c b/src/fileutils.c deleted file mode 100644 index 061d437..0000000 --- a/src/fileutils.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * debug-launchpad - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungmin Cho , Gwangho Hwang - * - * 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. - * - */ - -#include -#include -#include -#include -#include -#include - -static int recurse(const char *path, mode_t mode, int (*fn)(const char *,mode_t, int)) { - struct stat st; - char dir[PATH_MAX]; - - if (path == NULL) { - return -1; - } - if (lstat (path, &st) == -1) { - return -1; - } - if (strrchr(path, '/') != NULL) { - int n = strlen(path)-strlen(strrchr(path, '/')); - if (n >= PATH_MAX) { - return -1; - } - strncpy(dir, path, n); - dir[n] = '\0'; - fn(dir, mode,1); - return 0; - } - return -1; -} - -int dlp_chmod(const char *path, mode_t mode, int recursive) { -#ifdef HAVE_WIN32_PROC - fprintf(stderr, "error: dlp_chmod not implemented on Win32 (%s)\n", path); - return -1; -#else - struct stat st; - - if (stat (path, &st) == -1) - return -1; - - if (chmod (path, mode) == -1) { - return -1; - } - if (recursive) { - return recurse(path, mode, dlp_chmod); - } - return 0; -#endif -} diff --git a/src/heap_dbg.h b/src/heap_dbg.h deleted file mode 100755 index cc51fd8..0000000 --- a/src/heap_dbg.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * debug-launchpad - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungmin Cho , Gwangho Hwang - * - * 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. - * - */ - - -#include -#include -#include - -#ifdef HEAPDGB_ACTIVATE - -#define HOOK_RESET() \ -do {\ - __malloc_hook = old_malloc_hook; \ - __free_hook = old_free_hook; \ -} while (0); - -#define HOOK_SET() \ -do {\ - __malloc_hook = my_malloc; \ - __free_hook = my_free; \ -} while (0); - -static void *(*old_malloc_hook) (size_t size, const void *caller); -static void *(*old_realloc_hook) (void *ptr, size_t size, const void *caller); -static void (*old_free_hook) (void *ptr, const void *caller); - -static void *my_malloc(size_t size, const void *caller); -static void *my_realloc(void *ptr, size_t size, const void *caller); -static void my_free(void *ptr, const void *caller); - -static void my_free(void *ptr, const void *caller) -{ - void *callstack_addrs[20]; - char **callstack_strings; - int i; - - HOOK_RESET(); - - printf("%c[1;31m[FREE] %x %x", 27, ptr, caller); - printf("%c[0m\n", 27); - free(ptr); - - HOOK_SET(); - -} - -static void *my_malloc(size_t size, const void *caller) -{ - void *ptr; - - HOOK_RESET(); - - ptr = malloc(size); - printf("%c[1;31m[MALLOC] %x %x", 27, ptr, caller); - printf("%c[0m\n", 27); - - HOOK_SET(); - - return ptr; -} - -static void malloc_init(void) -{ - old_malloc_hook = __malloc_hook; - old_free_hook = __free_hook; - - HOOK_SET(); -} - -__attribute__ ((visibility("default"))) -void (*__malloc_initialize_hook) (void) = malloc_init; - -#else - -#endif diff --git a/src/launchpad.c b/src/launchpad.c deleted file mode 100755 index feb124f..0000000 --- a/src/launchpad.c +++ /dev/null @@ -1,1363 +0,0 @@ -/* - * debug-launchpad - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungmin Cho , Gwangho Hwang - * - * 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. - * - */ - -/* - * simple AUL daemon - launchpad - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "app_sock.h" -#include "aul.h" - -#include "config.h" - -#include "menu_db_util.h" -#include "simple_util.h" -#include "access_control.h" -#include "preload.h" -#include "preexec.h" -#include "perf.h" -#include "sigchild.h" -#include "aul_util.h" - -#include "heap_dbg.h" - -#include "gl.h" - -#include -#include -#include "fileutils.h" -#include - -#define _static_ static inline -#define POLLFD_MAX 1 -#define SQLITE_FLUSH_MAX (1048576) /* (1024*1024) */ -#define AUL_POLL_CNT 15 -#define AUL_PR_NAME 16 -#define APPID_LEN 10 -#define PATH_TMP "/tmp" -#define PATH_DATA "/data" - -#define SDK_CODE_COVERAGE "CODE_COVERAGE" -#define SDK_DEBUG "DEBUG" -#define SDK_DYNAMIC_ANALYSIS "DYNAMIC_ANALYSIS" -#define SDK_UNIT_TEST "UNIT_TEST" -#define SDK_VALGRIND "VALGRIND" -#define SDK_LD_FLAG "LD_FLAG" - -/* DLP is short for debug-launchpad */ -#define DLP_K_DEBUG_ARG "__DLP_DEBUG_ARG__" -#define DLP_K_UNIT_TEST_ARG "__DLP_UNIT_TEST_ARG__" -#define DLP_K_VALGRIND_ARG "__DLP_VALGRIND_ARG__" -#define DLP_K_LD_FLAG "__DLP_LD_FLAG__" - -#define PATH_GDBSERVER "/home/developer/sdk_tools/gdbserver/gdbserver" -#define PATH_VALGRIND "/home/developer/sdk_tools/valgrind/usr/bin/valgrind" -#define PATH_DA_SO "/usr/lib/da_probe_tizen.so" -#define PATH_NATIVE_APP "/opt/apps/" - -#if (ARCH==arm) -#define PATH_MEMCHECK "/opt/home/developer/sdk_tools/valgrind/usr/lib/valgrind/memcheck-arm-linux" -#elif (ARCH==x86) -#define PATH_MEMCHECK "/opt/home/developer/sdk_tools/valgrind/usr/lib/valgrind/memcheck-x86-linux" -#endif - -#define POLL_VALGRIND_LOGFILE 0x00000001 -#define POLL_VALGRIND_XMLFILE 0x00000002 - -#define CAPABILITY_SET_ORIGINAL 0 -#define CAPABILITY_SET_INHERITABLE 1 - -static int need_to_set_inh_cap_after_fork = 0; -static char *launchpad_cmdline; -static int initialized = 0; - -static int poll_outputfile = 0; -static int is_gdbserver_launched; - -void __set_oom(); -void __set_env(app_info_from_db * menu_info, bundle * kb); -int __prepare_exec(const char *pkg_name, - const char *app_path, app_info_from_db * menu_info, - bundle * kb); -int __fake_launch_app(int cmd, int pid, bundle * kb); -char **__create_argc_argv(bundle * kb, int *margc, const char *app_path); -int __normal_fork_exec(int argc, char **argv); -void __real_launch(const char *app_path, bundle * kb); -static inline int __parser(const char *arg, char *out, int out_size); -void __modify_bundle(bundle * kb, int caller_pid, - app_info_from_db * menu_info, int cmd); -int __send_to_sigkill(int pid); -int __term_app(int pid); -void __real_send(int clifd, int ret); -void __send_result_to_caller(int clifd, int ret); -void __launchpad_main_loop(int main_fd); -int __launchpad_pre_init(int argc, char **argv); -int __launchpad_post_init(); - -extern ail_error_e ail_db_close(void); - - - -void __set_oom() -{ - char buf[MAX_LOCAL_BUFSZ]; - FILE *fp; - - /* we should reset oomadj value as default because child - inherits from parent oom_adj*/ - snprintf(buf, MAX_LOCAL_BUFSZ, "/proc/%d/oom_adj", getpid()); - fp = fopen(buf, "w"); - if (fp == NULL) - return; - fprintf(fp, "%d", -16); - fclose(fp); -} - -void __set_sdk_env(app_info_from_db* menu_info, char* str, bundle * kb) { - char buf_pkgname[MAX_LOCAL_BUFSZ]; - char buf[MAX_LOCAL_BUFSZ]; - int ret; - - _D("key : %s / value : %s", AUL_K_SDK, str); - /* http://gcc.gnu.org/onlinedocs/gcc/Cross_002dprofiling.html*/ - /* GCOV_PREFIX contains the prefix to add to the absolute paths */ - /* in the object file. Prefix can be absolute, or relative.*/ - /* The default is no prefix. */ - /* GCOV_PREFIX_STRIP indicates the how many initial directory names */ - /* to stripoff the hardwired absolute paths. Default value is 0. */ - if (strncmp(str, SDK_CODE_COVERAGE, strlen(str)) == 0) { - strncpy(buf_pkgname,_get_pkgname(menu_info),MAX_LOCAL_BUFSZ-1); - buf_pkgname[MAX_LOCAL_BUFSZ-1]='\0'; - snprintf(buf, MAX_LOCAL_BUFSZ, PATH_TMP"/%s"PATH_DATA - , strtok(buf_pkgname,".")); - ret = setenv("GCOV_PREFIX", buf, 1); - _D("GCOV_PREFIX : %d", ret); - ret = setenv("GCOV_PREFIX_STRIP", "0", 1); - _D("GCOV_PREFIX_STRIP : %d", ret); - } - else if (strncmp(str, SDK_DYNAMIC_ANALYSIS, strlen(str)) == 0) - { - ret = setenv("LD_PRELOAD", PATH_DA_SO, 1); - _D("LD_PRELOAD : %d", ret); - } - else if (strncmp(str, SDK_LD_FLAG, strlen(str)) == 0) - { - const char *flag_str = NULL; - const char **flag_str_array = NULL; - int flag_len; - if(bundle_get_type(kb, DLP_K_LD_FLAG) & BUNDLE_TYPE_ARRAY) { - flag_str_array = bundle_get_str_array(kb, DLP_K_LD_FLAG, &flag_len); - } else { - flag_str = bundle_get_val(kb, DLP_K_LD_FLAG); - if(flag_str) { - flag_str_array = &flag_str; - flag_len = 1; - } - } - if(flag_str_array != NULL) { - int i; - char * f_name; - char * f_value; - for (i = 0; i < flag_len; i++) { - strncpy(buf,flag_str_array[i],MAX_LOCAL_BUFSZ); - f_name = strtok(buf,"="); - f_value = strtok(NULL,"="); - if(f_value) { - ret = setenv(f_name,f_value,1); - _D("LD_FLAG : %s %s %d",f_name,f_value,ret); - } else { - _E("LD_FLAG : Wrong option! %s", flag_str_array[i]); - } - } - } - - } -} - - -void __set_env(app_info_from_db * menu_info, bundle * kb) -{ - const char *str; - const char **str_array; - int len; - int i; - - setenv("PKG_NAME", _get_pkgname(menu_info), 1); - - USE_ENGINE("gl") - - str = bundle_get_val(kb, AUL_K_STARTTIME); - if (str != NULL) - setenv("APP_START_TIME", str, 1); - - if(bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) { - str_array = bundle_get_str_array(kb, AUL_K_SDK, &len); - if(str_array != NULL) { - for (i = 0; i < len; i++) { - _D("index : [%d]", i); - __set_sdk_env(menu_info, (char *)str_array[i], kb); - } - } - } else { - str = bundle_get_val(kb, AUL_K_SDK); - if(str != NULL) { - __set_sdk_env(menu_info, (char *)str, kb); - } - } - if (menu_info->hwacc != NULL) - setenv("HWACC", menu_info->hwacc, 1); -} - -int __prepare_exec(const char *pkg_name, - const char *app_path, app_info_from_db * menu_info, - bundle * kb) -{ - char *file_name; - char process_name[AUL_PR_NAME]; - int ret; - - /* 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(); - - __preexec_run(menu_info->pkg_type, pkg_name, app_path); - - /* SET OOM*/ - __set_oom(); - - /* SET PRIVILEGES*/ - if(bundle_get_val(kb, AUL_K_PRIVACY_APPID) == NULL) { - _D("pkg_name : %s / pkg_type : %s / app_path : %s ", pkg_name - , menu_info->pkg_type, app_path); - if ((ret = __set_access(pkg_name, menu_info->pkg_type - , app_path)) < 0) - { - _D("fail to set privileges - check your package's credential : %d\n" - , ret); - return -1; - } - } - /* SET DUMPABLE - for coredump*/ - prctl(PR_SET_DUMPABLE, 1); - - /* SET PROCESS NAME*/ - if (app_path == NULL) { - _D("app_path should not be NULL - check menu db"); - return -1; - } - file_name = strrchr(app_path, '/') + 1; - if (file_name == NULL) { - _D("can't locate file name to execute"); - return -1; - } - memset(process_name, '\0', AUL_PR_NAME); - snprintf(process_name, AUL_PR_NAME, "%s", file_name); - prctl(PR_SET_NAME, process_name); - - /* SET ENVIROMENT*/ - __set_env(menu_info, kb); - - return 0; -} - -int __fake_launch_app(int cmd, int pid, bundle * kb) -{ - int datalen; - int ret; - bundle_raw *kb_data; - - bundle_encode(kb, &kb_data, &datalen); - if ((ret = __app_send_raw(pid, cmd, kb_data, datalen)) < 0) - _E("error request fake launch - error code = %d", ret); - free(kb_data); - return ret; -} - -char** __add_arg(bundle * kb, char **argv, int *margc, const char *key) -{ - const char *str = NULL; - const char **str_array = NULL; - int len = 0; - int i; - char ** new_argv = NULL; - - if(bundle_get_type(kb, key) & BUNDLE_TYPE_ARRAY) { - str_array = bundle_get_str_array(kb, key, &len); - } else { - str = bundle_get_val(kb, key); - if(str) { - str_array = &str; - len = 1; - } - } - if(str_array != NULL) { - if(strncmp(key, DLP_K_DEBUG_ARG, strlen(key)) == 0 - || strncmp(key, DLP_K_VALGRIND_ARG, strlen(key)) == 0) - { - new_argv = (char **) realloc(argv - , sizeof(char *) * (*margc+len+2)); - if(!new_argv) { - _E("realloc fail (key = %s)", key); - exit(-1); - } - for(i=*margc+len+1; i-(len+1)>=0; i--) { - new_argv[i] = new_argv[i-(len+1)]; - } - // need to add new_argv[0] - for(i=0; i=0; i--) { - new_argv[i] = new_argv[i-1]; - } - // need to add new_argv[0] - (*margc)++; - } - } - - if(new_argv==NULL) return argv; - return new_argv; -} - -char **__create_argc_argv(bundle * kb, int *margc, const char *app_path) -{ - char **argv = NULL; - char **new_argv = NULL; - int argc; - - const char *str = NULL; - const char **str_array = NULL; - int len = 0; - int i; - - argc = bundle_export_to_argv(kb, &argv); - if (argv) { - for(i=1; i 1; i++) { - switch (state) { - case 1: - switch (arg[i]) { - case ' ': - case '\t': - state = 5; - break; - case '\0': - state = 7; - break; - case '\"': - state = 2; - break; - case '\\': - state = 4; - break; - default: - *out = arg[i]; - out++; - out_size--; - break; - } - break; - case 2: /* escape start*/ - switch (arg[i]) { - case '\0': - state = 6; - break; - case '\"': - state = 1; - break; - default: - *out = arg[i]; - out++; - out_size--; - break; - } - break; - case 4: /* character escape*/ - if (arg[i] == '\0') { - state = 6; - } else { - *out = arg[i]; - out++; - out_size--; - state = 1; - } - break; - case 5: /* token*/ - if (out != start_out) { - *out = '\0'; - out_size--; - return i; - } - i--; - state = 1; - break; - case 6: - return -1; /* error*/ - case 7: /* terminate*/ - *out = '\0'; - out_size--; - return 0; - default: - state = 6; - break; /* error*/ - } - } - - if (out_size == 1) { - *out = '\0'; - } - /* Buffer overflow*/ - return -2; -} - -void __modify_bundle(bundle * kb, int caller_pid, - app_info_from_db * menu_info, int cmd) -{ - bundle_del(kb, AUL_K_PKG_NAME); - bundle_del(kb, AUL_K_EXEC); - bundle_del(kb, AUL_K_PACKAGETYPE); - bundle_del(kb, AUL_K_HWACC); - - /* Parse app_path to retrieve default bundle*/ - if (cmd == APP_START || cmd == APP_START_RES || cmd == APP_OPEN - || cmd == APP_RESUME) - { - char *ptr; - char exe[MAX_PATH_LEN]; - int flag; - - ptr = _get_original_app_path(menu_info); - - flag = __parser(ptr, exe, sizeof(exe)); - if (flag > 0) { - char key[256]; - char value[256]; - - ptr += flag; - _D("parsing app_path: EXEC - %s\n", exe); - - do { - flag = __parser(ptr, key, sizeof(key)); - if (flag <= 0) - break; - ptr += flag; - - flag = __parser(ptr, value, sizeof(value)); - if (flag < 0) - break; - ptr += flag; - - /*bundle_del(kb, key);*/ - bundle_add(kb, key, value); - } while (flag > 0); - } else if (flag == 0) { - _D("parsing app_path: No arguments\n"); - } else { - _D("parsing app_path: Invalid argument\n"); - } - } -} - -int __send_to_sigkill(int pid) -{ - int pgid; - - pgid = getpgid(pid); - if (pgid <= 1) - return -1; - - if (killpg(pgid, SIGKILL) < 0) - return -1; - - return 0; -} - -int __term_app(int pid) -{ - int dummy; - if (__app_send_raw - (pid, APP_TERM_BY_PID, (unsigned char *)&dummy, sizeof(int)) < 0) { - _D("terminate packet send error - use SIGKILL"); - if (__send_to_sigkill(pid) < 0) { - _E("fail to killing - %d\n", pid); - return -1; - } - } - _D("term done\n"); - return 0; -} - -static int __get_caller_pid(bundle *kb) -{ - const char *pid_str; - int pid; - - pid_str = bundle_get_val(kb, AUL_K_ORG_CALLER_PID); - if(pid_str) - goto end; - - pid_str = bundle_get_val(kb, AUL_K_CALLER_PID); - if (pid_str == NULL) - return -1; - -end: - pid = atoi(pid_str); - if (pid <= 1) - return -1; - - return pid; -} - -int __foward_cmd(int cmd, bundle *kb, int cr_pid) -{ - int pid; - char tmp_pid[MAX_PID_STR_BUFSZ]; - int datalen; - bundle_raw *kb_data; - int res; - - if ((pid = __get_caller_pid(kb)) < 0) - return AUL_R_ERROR; - - snprintf(tmp_pid, MAX_PID_STR_BUFSZ, "%d", cr_pid); - - bundle_add(kb, AUL_K_CALLEE_PID, tmp_pid); - - bundle_encode(kb, &kb_data, &datalen); - if ((res = __app_send_raw_with_noreply(pid, cmd, kb_data, datalen)) < 0) - res = AUL_R_ERROR; - - free(kb_data); - - return res; -} - -void __real_send(int clifd, int ret) -{ - if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) { - if (errno == EPIPE) { - _E("send failed due to EPIPE.\n"); - } - _E("send fail to client"); - } - - close(clifd); -} - -void __send_result_to_caller(int clifd, int ret) -{ - char *cmdline; - int wait_count; - int cmdline_changed = 0; - int cmdline_exist = 0; - - if (clifd == -1) - return; - - if (ret <= 1) { - __real_send(clifd, ret); - return; - } - /* check normally was launched?*/ - wait_count = 1; - do { - cmdline = __proc_get_cmdline_bypid(ret); - if (cmdline == NULL) { - _E("error founded when being launched with %d", ret); - - } else if (strcmp(cmdline, launchpad_cmdline)) { - free(cmdline); - cmdline_changed = 1; - break; - } else { - cmdline_exist = 1; - free(cmdline); - } - - _D("-- now wait to change cmdline --"); - usleep(50 * 1000); /* 50ms sleep*/ - wait_count++; - } while (wait_count <= 20); /* max 50*20ms will be sleep*/ - - if ((!cmdline_exist) && (!cmdline_changed)) { - _E("abnormally launched"); - __real_send(clifd, -1); /* abnormally launched*/ - return; - } - - if (!cmdline_changed) - _E("process launched, but cmdline not changed"); - - __real_send(clifd, ret); - return; -} - -static app_info_from_db *_get_app_info_from_bundle_by_pkgname( - const char *pkgname, bundle *kb) -{ - app_info_from_db *menu_info; - - menu_info = calloc(1, sizeof(app_info_from_db)); - if (menu_info == NULL) { - return NULL; - } - - menu_info->pkg_name = strdup(pkgname); - menu_info->app_path = strdup(bundle_get_val(kb, AUL_K_EXEC)); - if (menu_info->app_path != NULL) - menu_info->original_app_path = strdup(menu_info->app_path); - menu_info->pkg_type = strdup(bundle_get_val(kb, AUL_K_PACKAGETYPE)); - menu_info->hwacc = strdup(bundle_get_val(kb, AUL_K_HWACC)); - - if (!_get_app_path(menu_info)) { - _free_app_info_from_db(menu_info); - return NULL; - } - - return menu_info; -} - -/** - * free after use it - */ -int get_native_appid(const char* app_path, char** appid) { - int rc = smack_lgetlabel(app_path, appid, SMACK_LABEL_ACCESS); - - if (rc != 0 || *appid == NULL) { - _E("smack_lgetlabel fail"); - return -1; - } - - if (strlen(*appid) != APPID_LEN) { - _E("wrong native appid : %s", *appid); - return -1; - } - - if (strlen(app_path) < sizeof(PATH_NATIVE_APP)+APPID_LEN-1) { - _E("wrong native app_path : %s", app_path); - return -1; - } - else if ( strncmp(app_path, PATH_NATIVE_APP, sizeof(PATH_NATIVE_APP)-1) - || strncmp(&app_path[sizeof(PATH_NATIVE_APP)-1] - , *appid,APPID_LEN) ) - { - _E("wrong native app_path : %s", app_path); - return -1; - } - - _D("get_appid return : %s", *appid); - return 0; -} - -int apply_smack_rules(const char* subject, const char* object - , const char* access_type) -{ - struct smack_accesses *rules = NULL; - - _D("apply_smack_rules : %s %s %s", subject, object, access_type); - - if (smack_accesses_new(&rules)) { - _E("smack_accesses_new fail"); - return -1; - } - - if (smack_accesses_add(rules, subject, object, access_type)) { - smack_accesses_free(rules); - _E("smack_accesses_add fail"); - return -1; - } - - if (smack_accesses_apply(rules)) { - smack_accesses_free(rules); - _E("smack_accesses_apply fail"); - return -1; - } - - smack_accesses_free(rules); - - return 0; -} - -int __prepare_valgrind_outputfile(bundle *kb) -{ - const char *str = NULL; - const char **str_array = NULL; - int len = 0; - int i; - - if(bundle_get_type(kb, DLP_K_VALGRIND_ARG) & BUNDLE_TYPE_ARRAY) { - str_array = bundle_get_str_array(kb, DLP_K_VALGRIND_ARG, &len); - } else { - str = bundle_get_val(kb, DLP_K_VALGRIND_ARG); - if(str) { - str_array = &str; - len = 1; - } - } - if(str_array == NULL) return 0; - - for (i = 0; i < len; i++) { - if(str_array[i] == NULL) break; - /* valgrind log file option */ - if (strncmp(str_array[i], OPT_VALGRIND_LOGFILE - , sizeof(OPT_VALGRIND_LOGFILE)-1) == 0) - { - if(strcmp(str_array[i], OPT_VALGRIND_LOGFILE_FIXED)) - { - _E("wrong valgrind option(%s). It should be %s" - , str_array[i] - , OPT_VALGRIND_LOGFILE_FIXED); - return -1; - }else{ - poll_outputfile |= POLL_VALGRIND_LOGFILE; - if(remove(PATH_VALGRIND_LOGFILE)){ - _D("cannot remove %s" - , PATH_VALGRIND_LOGFILE); - } - } - } - /* valgrind xml file option */ - else if (strncmp(str_array[i], OPT_VALGRIND_XMLFILE - , sizeof(OPT_VALGRIND_XMLFILE)-1) == 0) - { - if(strcmp(str_array[i], OPT_VALGRIND_XMLFILE_FIXED)) - { - _E("wrong valgrind option(%s). It should be %s" - , str_array[i] - , OPT_VALGRIND_XMLFILE_FIXED); - return -1; - }else{ - poll_outputfile |= POLL_VALGRIND_XMLFILE; - if(remove(PATH_VALGRIND_XMLFILE)){ - _D("cannot remove %s" - , PATH_VALGRIND_XMLFILE); - } - } - } - /* valgrind massif file option */ - else if (strncmp(str_array[i], OPT_VALGRIND_MASSIFFILE - , sizeof(OPT_VALGRIND_MASSIFFILE)-1) == 0) - { - if(strcmp(str_array[i], OPT_VALGRIND_MASSIFFILE_FIXED)) - { - _E("wrong valgrind option(%s). It should be %s" - , str_array[i] - , OPT_VALGRIND_MASSIFFILE_FIXED); - return -1; - }else{ - if(remove(PATH_VALGRIND_XMLFILE)){ - _D("cannot remove %s" - , PATH_VALGRIND_XMLFILE); - } - } - } - } - return 0; -} - -extern int capset(cap_user_header_t hdrp, const cap_user_data_t datap); - -int __adjust_process_capability(int sv) -{ - static struct __user_cap_header_struct h; - static struct __user_cap_data_struct ori_d[_LINUX_CAPABILITY_U32S_2]; - static struct __user_cap_data_struct inh_d[_LINUX_CAPABILITY_U32S_2]; - static int isinit = 0; - - if(isinit==0) { - h.version = _LINUX_CAPABILITY_VERSION_2; - h.pid = getpid(); - - capget(&h, ori_d); - capget(&h, inh_d); - - inh_d[CAP_TO_INDEX(CAP_NET_RAW)].inheritable |= - CAP_TO_MASK(CAP_NET_RAW); - inh_d[CAP_TO_INDEX(CAP_SYS_CHROOT)].inheritable |= - CAP_TO_MASK(CAP_SYS_CHROOT); - - isinit++; - - if(sv == CAPABILITY_SET_ORIGINAL) return 0; - } - - if(isinit==0) { - _E("__adjust_process_capability init failed"); - return -1; - } - - if(sv == CAPABILITY_SET_ORIGINAL) { - h.pid = getpid(); - if (capset(&h, ori_d) < 0) { - _E("Capability setting error"); - return -1; - } - } - else if (sv == CAPABILITY_SET_INHERITABLE) { - h.pid = getpid(); - if (capset(&h, inh_d) < 0) { - _E("Capability setting error"); - return -1; - } - } - - return 0; -} - -int __adjust_file_capability(const char * path) -{ - if(cap_set_file(path,cap_from_text("CAP_NET_RAW,CAP_SYS_CHROOT+i"))) { - _E("cap_set_file failed : %s", path); - return -1; - } - return 0; -} - -int __prepare_fork(bundle *kb, char *appid) -{ - const char *str = NULL; - const char **str_array = NULL; - int len = 0; - int i; - - need_to_set_inh_cap_after_fork=0; - poll_outputfile = 0; - if(bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) { - str_array = bundle_get_str_array(kb, AUL_K_SDK, &len); - } else { - str = bundle_get_val(kb, AUL_K_SDK); - if(str) { - str_array = &str; - len = 1; - } - } - if(str_array == NULL) return 0; - - is_gdbserver_launched = 0; - gdbserver_pid = -1; - gdbserver_app_pid = -1; - - for (i = 0; i < len; i++) { - if(str_array[i] == NULL) break; - /* gdbserver */ - if (strncmp(str_array[i], SDK_DEBUG, strlen(str_array[i])) == 0) - { - if(apply_smack_rules("sdbd",appid,"w")) { - _E("unable to set sdbd rules"); - return -1; - } - - // FIXME: set gdbfolder to 755 also - if(dlp_chmod(PATH_GDBSERVER - , S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP - |S_IROTH|S_IXOTH - , 1)) - { - _D("unable to set 755 to %s", PATH_GDBSERVER); - } - __adjust_file_capability(PATH_GDBSERVER); - need_to_set_inh_cap_after_fork++; - is_gdbserver_launched++; - } - /* valgrind */ - else if (strncmp(str_array[i], SDK_VALGRIND - , strlen(str_array[i])) == 0) - { - if (__prepare_valgrind_outputfile(kb) == -1) - return -1; - __adjust_file_capability(PATH_MEMCHECK); - } - } - return 0; -} - - -/* waiting for creating outputfile by child process */ -void __waiting_outputfile() -{ - int wait_count = 0; - while(poll_outputfile && wait_count<10) { - /* valgrind log file */ - if( (poll_outputfile & POLL_VALGRIND_LOGFILE) - && (access(PATH_VALGRIND_LOGFILE,F_OK)==0) ) - { - __chmod_chsmack_toread(PATH_VALGRIND_LOGFILE); - poll_outputfile &= ~POLL_VALGRIND_LOGFILE; - } - - /* valgrind xml file */ - if( (poll_outputfile & POLL_VALGRIND_XMLFILE) - && (access(PATH_VALGRIND_XMLFILE,F_OK)==0) ) - { - __chmod_chsmack_toread(PATH_VALGRIND_XMLFILE); - poll_outputfile &= ~POLL_VALGRIND_XMLFILE; - } - - if(poll_outputfile) { - _D("-- now wait for creating the file --"); - usleep(50 * 1000); /* 50ms sleep*/ - wait_count++; - } - } - - if(wait_count==10) _E("faild to waiting"); - return; -} - -int __stdout_stderr_redirection(int defpid) -{ - char defpath[UNIX_PATH_MAX]; - int deffd, result=0; - - /* stdout */ - snprintf(defpath, UNIX_PATH_MAX, "/proc/%d/fd/1", defpid); - deffd = open(defpath,O_WRONLY); - if(deffd < 0) { - _E("opening caller(%d) stdout failed due to %s" - , defpid, strerror(errno)); - result++; - }else{ - dup2(deffd, 1); - close(deffd); - } - - /* stderr */ - snprintf(defpath, UNIX_PATH_MAX, "/proc/%d/fd/2", defpid); - deffd = open(defpath,O_WRONLY); - if(deffd < 0) { - _E("opening caller(%d) stderr failed due to %s" - , defpid,strerror(errno)); - result+=2; - }else{ - dup2(deffd, 2); - close(deffd); - } - - return result; -} - -void __launchpad_main_loop(int main_fd) -{ - bundle *kb = NULL; - app_pkt_t *pkt = NULL; - app_info_from_db *menu_info = NULL; - - const char *pkg_name = NULL; - const char *app_path = NULL; - int pid = -1; - int clifd = -1; - struct ucred cr; - int is_real_launch = 0; - - char sock_path[UNIX_PATH_MAX] = {0,}; - char * appid = NULL; - - pkt = __app_recv_raw(main_fd, &clifd, &cr); - if (!pkt) { - _D("packet is NULL"); - goto end; - } - - kb = bundle_decode(pkt->data, pkt->len); - if (!kb) { - _D("bundle decode error"); - goto end; - } - - INIT_PERF(kb); - PERF("packet processing start"); - - pkg_name = bundle_get_val(kb, AUL_K_PKG_NAME); - _D("pkg name : %s\n", pkg_name); - - menu_info = _get_app_info_from_bundle_by_pkgname(pkg_name, kb); - if (menu_info == NULL) { - _D("such pkg no found"); - goto end; - } - - app_path = _get_app_path(menu_info); - if(app_path == NULL) { - _E("app_path is NULL"); - goto end; - } - if (app_path[0] != '/') { - _D("app_path is not absolute path"); - goto end; - } - - { - int rc = get_native_appid(app_path,&appid); - if(rc!=0 || appid==NULL) { - _E("unable to get native appid"); - if(appid){ - free(appid); - appid = NULL; - } - goto end; - } - } - - __modify_bundle(kb, cr.pid, menu_info, pkt->cmd); - pkg_name = _get_pkgname(menu_info); - - PERF("get package information & modify bundle done"); - - if(__prepare_fork(kb,appid) == -1) goto end; - - pid = fork(); - if (pid == 0) { - if(need_to_set_inh_cap_after_fork) { - __adjust_process_capability(CAPABILITY_SET_INHERITABLE); - } - PERF("fork done"); - _D("lock up test log(no error) : fork done"); - - close(clifd); - close(main_fd); - __signal_unset_sigchld(); - __signal_fini(); - - snprintf(sock_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX - , getpid()); - unlink(sock_path); - - if(__stdout_stderr_redirection(__get_caller_pid(kb))) { - _E("__stdout_stderr_redirection fail"); - } - - PERF("prepare exec - first done"); - _D("lock up test log(no error) : prepare exec - first done"); - - if (__prepare_exec(pkg_name, app_path, - menu_info, kb) < 0) { - _E("preparing work fail to launch - " - "can not launch %s\n", pkg_name); - exit(-1); - } - - PERF("prepare exec - second done"); - _D("lock up test log(no error) : prepare exec - second done"); - - __real_launch(app_path, kb); - - exit(-1); - } - - if(is_gdbserver_launched) { - char buf[MAX_LOCAL_BUFSZ]; - - usleep(100 * 1000); /* 100ms sleep */ - snprintf(buf, MAX_LOCAL_BUFSZ, "%s.exe", app_path); - gdbserver_app_pid = __proc_iter_cmdline(NULL, buf); - - if(gdbserver_app_pid == -1) { - _E("faild to get app pid"); - } else { - gdbserver_pid = pid; - pid = gdbserver_app_pid; - } - } - - _D("==> real launch pid : %d %s\n", pid, app_path); - is_real_launch = 1; - - end: - __send_result_to_caller(clifd, pid); - - if (pid > 0) { - if (is_real_launch) { - /*TODO: retry*/ - __signal_block_sigchld(); - __send_app_launch_signal(pid); - __signal_unblock_sigchld(); - } - } - - if (menu_info != NULL) - _free_app_info_from_db(menu_info); - - if (kb != NULL) - bundle_free(kb); - if (pkt != NULL) - free(pkt); - if (appid != NULL) - free(appid); - - /* Active Flusing for Daemon */ - if (initialized > AUL_POLL_CNT) { - sqlite3_release_memory(SQLITE_FLUSH_MAX); - malloc_trim(0); - initialized = 1; - } - - if(poll_outputfile) __waiting_outputfile(); -} - -int __launchpad_pre_init(int argc, char **argv) -{ - int fd; - - /* signal init*/ - __signal_init(); - - /* get my(launchpad) command line*/ - launchpad_cmdline = __proc_get_cmdline_bypid(getpid()); - if (launchpad_cmdline == NULL) { - _E("launchpad cmdline fail to get"); - return -1; - } - _D("launchpad cmdline = %s", launchpad_cmdline); - - /* create launchpad sock */ - fd = __create_server_sock(DEBUG_LAUNCHPAD_PID); - if (fd < 0) { - _E("server sock error"); - return -1; - } - - __preload_init(argc, argv); - - __preexec_init(argc, argv); - - return fd; -} - -int __launchpad_post_init() -{ - /* Setting this as a global variable to keep track - of launchpad poll cnt */ - /* static int initialized = 0;*/ - - if (initialized) { - initialized++; - return 0; - } - - if (__signal_set_sigchld() < 0) - return -1; - - initialized++; - - return 0; -} - -int main(int argc, char **argv) -{ - int main_fd; - struct pollfd pfds[POLLFD_MAX]; - int i; - - __adjust_process_capability(CAPABILITY_SET_ORIGINAL); - - /* init without concerning X & EFL*/ - main_fd = __launchpad_pre_init(argc, argv); - if (main_fd < 0) { - _E("launchpad pre init failed"); - exit(-1); - } - - pfds[0].fd = main_fd; - pfds[0].events = POLLIN; - pfds[0].revents = 0; - - while (1) { - if (poll(pfds, POLLFD_MAX, -1) < 0) - continue; - - /* init with concerning X & EFL (because of booting - sequence problem)*/ - if (__launchpad_post_init() < 0) { - _E("launcpad post init failed"); - exit(-1); - } - - for (i = 0; i < POLLFD_MAX; i++) { - if ((pfds[i].revents & POLLIN) != 0) { - __launchpad_main_loop(pfds[i].fd); - } - } - } -} - diff --git a/src/security_util.c b/src/security_util.c new file mode 100644 index 0000000..3269a9f --- /dev/null +++ b/src/security_util.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2015 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. + */ + +#include +#include +#include +#include + +#include "common.h" +#include "security_util.h" + +int _set_smack_access_label(const char *path, const char *label) +{ + return smack_setlabel(path, label, SMACK_LABEL_ACCESS); +} + +int _apply_smack_rules(const char *subject, const char *object, + const char *access_type) +{ + int r; + struct smack_accesses *rules = NULL; + + _D("%s %s %s", subject, object, access_type); + + r = smack_accesses_new(&rules); + if (r != 0) { + _E("smack_accesses_new() is failed."); + return -1; + } + + r = smack_accesses_add(rules, subject, object, access_type); + if (r != 0) { + _E("smack_accesses_add() is failed."); + smack_accesses_free(rules); + return -1; + } + + r = smack_accesses_apply(rules); + if (r != 0) { + _E("smack_accesses_apply() is failed."); + smack_accesses_free(rules); + return -1; + } + + smack_accesses_free(rules); + + return 0; +} + +int _set_access(const char *appid) +{ + return security_manager_prepare_app(appid); +} diff --git a/src/sigchild.h b/src/sigchild.h deleted file mode 100755 index 903d105..0000000 --- a/src/sigchild.h +++ /dev/null @@ -1,289 +0,0 @@ -/* - * debug-launchpad - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungmin Cho , Gwangho Hwang - * - * 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. - * - */ - - -#include -#include -#include "app_signal.h" - -static struct sigaction old_sigchild; -static DBusConnection *bus = NULL; -sigset_t oldmask; -static int gdbserver_pid; -static int gdbserver_app_pid; - -static inline void __socket_garbage_collector() -{ - DIR *dp; - struct dirent *dentry; - char tmp[MAX_LOCAL_BUFSZ]; - - dp = opendir(AUL_SOCK_PREFIX); - if (dp == NULL) - return; - - while ((dentry = readdir(dp)) != NULL) { - if (!isdigit(dentry->d_name[0])) - continue; - - snprintf(tmp, MAX_LOCAL_BUFSZ, "/proc/%s", dentry->d_name); - if (access(tmp, F_OK) < 0) { /* Flawfinder: ignore */ - snprintf(tmp, MAX_LOCAL_BUFSZ, "%s/%s", AUL_SOCK_PREFIX, - dentry->d_name); - unlink(tmp); - continue; - } - } - closedir(dp); -} - -static inline int __send_app_dead_signal(int dead_pid) -{ - DBusMessage *message; - - if (bus == NULL) - return -1; - - message = dbus_message_new_signal(AUL_DBUS_PATH, - AUL_DBUS_SIGNAL_INTERFACE, - AUL_DBUS_APPDEAD_SIGNAL); - - if (dbus_message_append_args(message, - DBUS_TYPE_UINT32, &dead_pid, - DBUS_TYPE_INVALID) == FALSE) { - _E("Failed to load data error"); - return -1; - } - - if (dbus_connection_send(bus, message, NULL) == FALSE) { - _E("dbus send error"); - return -1; - } - - dbus_connection_flush(bus); - dbus_message_unref(message); - - _D("send dead signal done\n"); - - return 0; -} - -static inline int __send_app_launch_signal(int launch_pid) -{ - DBusMessage *message; - - if (bus == NULL) - return -1; - - message = dbus_message_new_signal(AUL_DBUS_PATH, - AUL_DBUS_SIGNAL_INTERFACE, - AUL_DBUS_APPLAUNCH_SIGNAL); - - if (dbus_message_append_args(message, - DBUS_TYPE_UINT32, &launch_pid, - DBUS_TYPE_INVALID) == FALSE) { - _E("Failed to load data error"); - return -1; - } - - if (dbus_connection_send(bus, message, NULL) == FALSE) { - _E("dbus send error"); - return -1; - } - - dbus_connection_flush(bus); - dbus_message_unref(message); - - _D("send launch signal done\n"); - - return 0; -} - -/* chmod and chsmack to read file without root privilege */ -static void __chmod_chsmack_toread(const char * path) -{ - /* chmod */ - if(dlp_chmod(path, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, 0)) - { - _E("unable to set 644 to %s", path); - }else{ - _D("set 644 to %s", path); - } - - /* chsmack */ - if(smack_setlabel(path, "*", SMACK_LABEL_ACCESS)) - { - _E("failed chsmack -a \"*\" %s", path); - }else{ - _D("chsmack -a \"*\" %s", path); - } - - return; -} - -static int __sigchild_action(void *data) -{ - pid_t dead_pid; - char buf[MAX_LOCAL_BUFSZ]; - - dead_pid = (pid_t) data; - if (dead_pid <= 0) - goto end; - - /* send app pid instead of gdbserver pid */ - if(dead_pid == gdbserver_pid) - dead_pid = gdbserver_app_pid; - - /* valgrind xml file */ - if(access(PATH_VALGRIND_XMLFILE,F_OK)==0) - { - __chmod_chsmack_toread(PATH_VALGRIND_XMLFILE); - } - - __send_app_dead_signal(dead_pid); - - snprintf(buf, MAX_LOCAL_BUFSZ, "%s/%d", AUL_SOCK_PREFIX, dead_pid); - unlink(buf); - - __socket_garbage_collector(); - end: - return 0; -} - -static void __launchpad_sig_child(int signo, siginfo_t *info, void *data) -{ - int status; - pid_t child_pid; - pid_t child_pgid; - - child_pgid = getpgid(info->si_pid); - _D("dead_pid = %d pgid = %d", info->si_pid, child_pgid); - - while ((child_pid = waitpid(-1, &status, WNOHANG)) > 0) { - if (child_pid == child_pgid) - killpg(child_pgid, SIGKILL); - __sigchild_action((void *)child_pid); - } - - return; -} - -static inline int __signal_init(void) -{ - int i; - for (i = 0; i < _NSIG; i++) { - switch (i) { - /* controlled by sys-assert package*/ - case SIGQUIT: - case SIGILL: - case SIGABRT: - case SIGBUS: - case SIGFPE: - case SIGSEGV: - case SIGPIPE: - break; - default: - signal(i, SIG_DFL); - break; - } - } - - return 0; -} - -static inline int __signal_set_sigchld(void) -{ - struct sigaction act; - DBusError error; - - dbus_error_init(&error); - dbus_threads_init_default(); - bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error); - if (!bus) { - _E("Failed to connect to the D-BUS daemon: %s", error.message); - dbus_error_free(&error); - return -1; - } - /* TODO: if process stop mechanism is included, - should be modified (SA_NOCLDSTOP)*/ - act.sa_handler = NULL; - act.sa_sigaction = __launchpad_sig_child; - sigemptyset(&act.sa_mask); - act.sa_flags = SA_NOCLDSTOP | SA_SIGINFO; - - if (sigaction(SIGCHLD, &act, &old_sigchild) < 0) - return -1; - - return 0; -} - -static inline int __signal_unset_sigchld(void) -{ - struct sigaction dummy; - - if (bus == NULL) - return 0; - - dbus_connection_close(bus); - if (sigaction(SIGCHLD, &old_sigchild, &dummy) < 0) - return -1; - - return 0; -} - -static inline int __signal_block_sigchld(void) -{ - sigset_t newmask; - - sigemptyset(&newmask); - sigaddset(&newmask, SIGCHLD); - - if (sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0) { - _E("SIG_BLOCK error"); - return -1; - } - - _D("SIGCHLD blocked"); - - return 0; -} - -static inline int __signal_unblock_sigchld(void) -{ - if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) { - _E("SIG_SETMASK error"); - return -1; - } - - _D("SIGCHLD unblocked"); - return 0; -} - -static inline int __signal_fini(void) -{ -#ifndef PRELOAD_ACTIVATE - int i; - for (i = 0; i < _NSIG; i++) - signal(i, SIG_DFL); -#endif - return 0; -} - diff --git a/src/signal_util.c b/src/signal_util.c new file mode 100644 index 0000000..3a7cf74 --- /dev/null +++ b/src/signal_util.c @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2015 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. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "defs.h" +#include "common.h" +#include "file_util.h" +#include "debug_util.h" +#include "signal_util.h" + +#define AUL_DBUS_PATH "/aul/dbus_handler" +#define AUL_DBUS_SIGNAL_INTERFACE "org.tizen.aul.signal" +#define AUL_DBUS_APPDEAD_SIGNAL "app_dead" +#define AUL_DBUS_APPLAUNCH_SIGNAL "app_launch" + +static DBusConnection *bus = NULL; +static sigset_t oldmask; + +static void __socket_garbage_collector(void) +{ + DIR *dp; + struct dirent *dentry; + char path[PATH_MAX]; + + snprintf(path, sizeof(path), "%s/%d", SOCKET_PATH, getuid()); + dp = opendir(path); + if (dp == NULL) + return; + + while ((dentry = readdir(dp)) != NULL) { + if (!isdigit(dentry->d_name[0])) + continue; + + snprintf(path, sizeof(path), "/proc/%s", dentry->d_name); + if (access(path, F_OK) != 0) { /* Flawfinder: ignore */ + snprintf(path, sizeof(path), "%s/%d/%s", + SOCKET_PATH, getuid(), dentry->d_name); + unlink(path); + continue; + } + } + + closedir(dp); +} + +int _send_app_dead_signal(int dead_pid) +{ + DBusMessage *message; + + if (bus == NULL) + return -1; + + message = dbus_message_new_signal(AUL_DBUS_PATH, + AUL_DBUS_SIGNAL_INTERFACE, + AUL_DBUS_APPDEAD_SIGNAL); + + if (dbus_message_append_args(message, + DBUS_TYPE_UINT32, &dead_pid, + DBUS_TYPE_INVALID) == FALSE) { + _E("Failed to load data error"); + return -1; + } + + if (dbus_connection_send(bus, message, NULL) == FALSE) { + _E("dbus send error"); + return -1; + } + + dbus_connection_flush(bus); + dbus_message_unref(message); + + _D("send dead signal done\n"); + + return 0; +} + +int _send_app_launch_signal(int launch_pid) +{ + DBusMessage *message; + + if (bus == NULL) + return -1; + + message = dbus_message_new_signal(AUL_DBUS_PATH, + AUL_DBUS_SIGNAL_INTERFACE, + AUL_DBUS_APPLAUNCH_SIGNAL); + + if (dbus_message_append_args(message, + DBUS_TYPE_UINT32, &launch_pid, + DBUS_TYPE_INVALID) == FALSE) { + _E("Failed to load data error"); + return -1; + } + + if (dbus_connection_send(bus, message, NULL) == FALSE) { + _E("dbus send error"); + return -1; + } + + dbus_connection_flush(bus); + dbus_message_unref(message); + + _D("send launch signal done\n"); + + return 0; +} + +static int __sigchild_action(void *data) +{ + pid_t dead_pid; + char buf[MAX_LOCAL_BUFSZ]; + + dead_pid = (pid_t)(intptr_t)data; + if (dead_pid <= 0) + return -1; + + /* send app pid instead of gdbserver pid */ + if (dead_pid == _get_gdbserver_pid()) + dead_pid = _get_gdbserver_app_pid(); + + /* valgrind xml file */ + if (access(PATH_VALGRIND_XMLFILE, F_OK) == 0) + _change_file(PATH_VALGRIND_XMLFILE); + + _send_app_dead_signal(dead_pid); + + snprintf(buf, MAX_LOCAL_BUFSZ, "%s/%d/%d", SOCKET_PATH, getuid(), dead_pid); + unlink(buf); + + __socket_garbage_collector(); + + return 0; +} + +void _debug_launchpad_sigchld(struct signalfd_siginfo *info) +{ + int status; + pid_t child_pid; + pid_t child_pgid; + + child_pgid = getpgid(info->ssi_pid); + _D("dead pid = %d pgid = %d", info->ssi_pid, child_pgid); + + while ((child_pid = waitpid(-1, &status, WNOHANG)) > 0) { + if (child_pid == child_pgid) + killpg(child_pgid, SIGKILL); + __sigchild_action((void *)(intptr_t)child_pid); + } +} + +int _signal_init(void) +{ + int i; + DBusError error; + + dbus_error_init(&error); + dbus_threads_init_default(); + bus = dbus_bus_get_private(DBUS_BUS_SESSION, &error); + if (!bus) { + _E("Failed to connect to the D-BUS daemon: %s", error.message); + dbus_error_free(&error); + return -1; + } + + for (i = 0; i < _NSIG; i++) { + switch (i) { + /* controlled by sys-assert package*/ + case SIGQUIT: + case SIGILL: + case SIGABRT: + case SIGBUS: + case SIGFPE: + case SIGSEGV: + case SIGPIPE: + break; + default: + signal(i, SIG_DFL); + break; + } + } + + return 0; +} + +int _signal_get_sigchld_fd(void) +{ + sigset_t mask; + int sfd; + + sigemptyset(&mask); + sigaddset(&mask, SIGCHLD); + + if (sigprocmask(SIG_BLOCK, &mask, &oldmask) == -1) + _E("sigprocmask() is failed."); + + sfd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC); + if (sfd == -1) { + _E("Failed to create signal fd"); + return -1; + } + + return sfd; +} + +int _signal_unblock_sigchld(void) +{ + if (sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0) { + _E("SIG_SETMASK error"); + return -1; + } + + _D("SIGCHLD unblocked"); + + return 0; +} + +int _signal_fini(void) +{ + int i; + + if (bus) + dbus_connection_close(bus); + +#ifndef PRELOAD_ACTIVATE + for (i = 0; i < _NSIG; i++) + signal(i, SIG_DFL); +#endif + return 0; +} diff --git a/src/simple_util.c b/src/simple_util.c deleted file mode 100755 index dadc183..0000000 --- a/src/simple_util.c +++ /dev/null @@ -1,210 +0,0 @@ -/* - * debug-launchpad - * - * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved. - * - * Contact: Jungmin Cho , Gwangho Hwang - * - * 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. - * - */ - - -#include -#include -#include -#include -#include -#include -#include -#include "simple_util.h" - -#define BINSH_NAME "/bin/sh" -#define BINSH_SIZE 7 - -#define PROC_STAT_GID_POS 5 - - -static inline int __read_proc(const char *path, char *buf, int size); -static inline int __find_pid_by_cmdline(const char *dname, - const char *cmdline, void *priv); -static inline int __get_pgid_from_stat(int pid); - - -static inline int __read_proc(const char *path, char *buf, int size) -{ - int fd; - int ret; - - if (buf == NULL || path == NULL) - return -1; - - fd = open(path, O_RDONLY); - if (fd < 0) - return -1; - - ret = read(fd, buf, size - 1); - if (ret <= 0) { - close(fd); - return -1; - } else - buf[ret] = 0; - - close(fd); - - return ret; -} - -static inline int __find_pid_by_cmdline(const char *dname, - const char *cmdline, void *priv) -{ - char *apppath; - int pid = 0; - - apppath = (char *)priv; - if (strncmp(cmdline, apppath, MAX_LOCAL_BUFSZ-1) == 0) { - pid = atoi(dname); - if (pid != getpgid(pid)) - pid = 0; - } - - return pid; -} - -int __proc_iter_cmdline( - int (*iterfunc)(const char *dname, const char *cmdline, void *priv), - void *priv) -{ - DIR *dp; - struct dirent *dentry; - int pid; - int ret; - char buf[MAX_LOCAL_BUFSZ]; - - dp = opendir("/proc"); - if (dp == NULL) { - return -1; - } - - if (iterfunc == NULL) - iterfunc = __find_pid_by_cmdline; - - while ((dentry = readdir(dp)) != NULL) { - if (!isdigit(dentry->d_name[0])) - continue; - - snprintf(buf, sizeof(buf), "/proc/%s/cmdline", dentry->d_name); - ret = __read_proc(buf, buf, sizeof(buf)); - if (ret <= 0) - continue; - - /* support app launched by shell script*/ - if (strncmp(buf, BINSH_NAME, BINSH_SIZE) == 0) - pid = - iterfunc(dentry->d_name, &buf[BINSH_SIZE + 1], - priv); - else - pid = iterfunc(dentry->d_name, buf, priv); - - if (pid > 0) { - closedir(dp); - return pid; - } - } - - closedir(dp); - return -1; -} - -char *__proc_get_cmdline_bypid(int pid) -{ - char buf[MAX_LOCAL_BUFSZ]; - int ret; - - snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid); - ret = __read_proc(buf, buf, sizeof(buf)); - if (ret <= 0) - return NULL; - - /* support app launched by shell script*/ - if (strncmp(buf, BINSH_NAME, BINSH_SIZE) == 0) - return strdup(&buf[BINSH_SIZE + 1]); - else - return strdup(buf); -} - -static inline int __get_pgid_from_stat(int pid) -{ - char buf[MAX_LOCAL_BUFSZ]; - char *str; - int ret; - int i; - int count = 0; - - if (pid <= 1) - return -1; - - snprintf(buf, sizeof(buf), "/proc/%d/stat", pid); - ret = __read_proc(buf, buf, sizeof(buf)); - if (ret < 0) - return -1; - - for (i = 0; i < (ret - 1); i++) { - if (buf[i] == ' ') { - count++; - if (count == PROC_STAT_GID_POS - 1) - str = &(buf[i + 1]); - else if (count == PROC_STAT_GID_POS) { - buf[i] = 0; - break; - } - } - } - - if (count == PROC_STAT_GID_POS) - pid = atoi(str); - else - pid = -1; - - return pid; -} - -int __proc_iter_pgid(int pgid, int (*iterfunc) (int pid, void *priv), - void *priv) -{ - DIR *dp; - struct dirent *dentry; - int _pgid; - int ret = -1; - - dp = opendir("/proc"); - if (dp == NULL) { - return -1; - } - - while ((dentry = readdir(dp)) != NULL) { - if (!isdigit(dentry->d_name[0])) - continue; - - _pgid = __get_pgid_from_stat(atoi(dentry->d_name)); - if (pgid == _pgid) { - ret = iterfunc(atoi(dentry->d_name), priv); - if (ret >= 0) - break; - } - } - - closedir(dp); - return ret; -} -