From 29815ab3a277fc42f1dd7dbfd2fe6b53a242cda4 Mon Sep 17 00:00:00 2001 From: Sehong Na Date: Sat, 31 May 2014 12:35:35 +0900 Subject: [PATCH 1/1] Initialize Tizen 2.3 --- CMakeLists.txt | 88 +++ LICENSE | 202 +++++++ NOTICE | 3 + debug-launchpad.manifest | 8 + feature/preexec.h | 187 ++++++ include/access_control.h | 42 ++ include/app_signal.h | 35 ++ include/app_sock.h | 79 +++ include/aul_util.h | 51 ++ include/menu_db_util.h | 233 ++++++++ include/perf.h | 68 +++ include/preload.h | 146 +++++ include/simple_util.h | 90 +++ packaging/debug-launchpad.spec | 58 ++ src/app_sock.c | 524 ++++++++++++++++ src/config.h | 30 + src/fileutils.c | 70 +++ src/fileutils.h | 27 + src/gl.h | 32 + src/heap_dbg.h | 93 +++ src/launchpad.c | 1298 ++++++++++++++++++++++++++++++++++++++++ src/sigchild.h | 254 ++++++++ src/simple_util.c | 210 +++++++ 23 files changed, 3828 insertions(+) create mode 100755 CMakeLists.txt create mode 100755 LICENSE create mode 100755 NOTICE create mode 100644 debug-launchpad.manifest create mode 100755 feature/preexec.h create mode 100755 include/access_control.h create mode 100755 include/app_signal.h create mode 100755 include/app_sock.h create mode 100755 include/aul_util.h create mode 100755 include/menu_db_util.h create mode 100755 include/perf.h create mode 100755 include/preload.h create mode 100755 include/simple_util.h create mode 100755 packaging/debug-launchpad.spec create mode 100755 src/app_sock.c create mode 100755 src/config.h create mode 100644 src/fileutils.c create mode 100644 src/fileutils.h create mode 100755 src/gl.h create mode 100755 src/heap_dbg.h create mode 100755 src/launchpad.c create mode 100755 src/sigchild.h create mode 100755 src/simple_util.c diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100755 index 0000000..9a4a322 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,88 @@ +CMAKE_MINIMUM_REQUIRED(VERSION 2.6) +SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS true) + +PROJECT(debug-launchpad C) +SET(VERSION_MAJOR 0) +SET(VERSION "${VERSION_MAJOR}.1.0") + +### Global setting ### + +SET(PREFIX ${CMAKE_INSTALL_PREFIX}) +SET(EXEC_PREFIX "\${prefix}") + +# Build type : Release +IF("${CMAKE_BUILD_TYPE}" STREQUAL "") + SET(CMAKE_BUILD_TYPE "Release") +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 pkgmgr-info) + +FIND_LIBRARY(LIB_DL dl) + +FOREACH(flag ${pkgs_CFLAGS}) + SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}") +ENDFOREACH(flag) + +# Compiler flags +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/include) +INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/feature) +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wl,-zdefs" ) +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden") +SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fpic") +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 + ) + +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) + + diff --git a/LICENSE b/LICENSE new file mode 100755 index 0000000..d645695 --- /dev/null +++ b/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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. diff --git a/NOTICE b/NOTICE new file mode 100755 index 0000000..0aec949 --- /dev/null +++ b/NOTICE @@ -0,0 +1,3 @@ +Copyright (c) 2013 Samsung Electronics Co., Ltd. All rights reserved. +Except as noted, this software is licensed under Apache License, Version 2. +Please, see the LICENSE.APLv2 file for Apache License, Version 2 terms and conditions. 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 new file mode 100755 index 0000000..644c416 --- /dev/null +++ b/feature/preexec.h @@ -0,0 +1,187 @@ +/* + * 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 new file mode 100755 index 0000000..604b095 --- /dev/null +++ b/include/access_control.h @@ -0,0 +1,42 @@ +/* + * 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 new file mode 100755 index 0000000..03ccf14 --- /dev/null +++ b/include/app_signal.h @@ -0,0 +1,35 @@ +/* + * 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 "com.samsung.aul.signal" +#define AUL_DBUS_APPDEAD_SIGNAL "app_dead" +#define AUL_DBUS_APPLAUNCH_SIGNAL "app_launch" + +#endif diff --git a/include/app_sock.h b/include/app_sock.h new file mode 100755 index 0000000..a7544d5 --- /dev/null +++ b/include/app_sock.h @@ -0,0 +1,79 @@ +/* + * 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 +#define EHIDDENFORGUEST 8 + +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 new file mode 100755 index 0000000..c6ebb8f --- /dev/null +++ b/include/aul_util.h @@ -0,0 +1,51 @@ +/* + * 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/menu_db_util.h b/include/menu_db_util.h new file mode 100755 index 0000000..8737c11 --- /dev/null +++ b/include/menu_db_util.h @@ -0,0 +1,233 @@ +/* + * 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 */ + char *taskmanage; /* taskmanage */ +} 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 new file mode 100755 index 0000000..bec46e8 --- /dev/null +++ b/include/perf.h @@ -0,0 +1,68 @@ +/* + * 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 __PERF_H__ +#define __PERF_H__ + +#ifdef PERF_ACTIVATE + +#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); + +#else + +#define INIT_PERF(kb) +#define PERF(fmt, arg...) + +#endif + +#endif + diff --git a/include/preload.h b/include/preload.h new file mode 100755 index 0000000..b817375 --- /dev/null +++ b/include/preload.h @@ -0,0 +1,146 @@ +/* + * 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/include/simple_util.h b/include/simple_util.h new file mode 100755 index 0000000..83f554d --- /dev/null +++ b/include/simple_util.h @@ -0,0 +1,90 @@ +/* + * 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.spec b/packaging/debug-launchpad.spec new file mode 100755 index 0000000..dce9c6c --- /dev/null +++ b/packaging/debug-launchpad.spec @@ -0,0 +1,58 @@ +Name: debug-launchpad +Summary: Debug Launchpad +Version: 0.0.12 +Release: 1 +Group: System Environment/Daemons +License: Apache License, Version 2.0 +Source0: %{name}-%{version}.tar.gz +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) + +Requires(post): /sbin/ldconfig +Requires(post): /usr/bin/systemctl +Requires(postun): /sbin/ldconfig +Requires(postun): /usr/bin/systemctl +Requires(preun): /usr/bin/systemctl + +BuildRequires: cmake +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) + + +%description +Debug launchpad + +%prep +%setup -q + +%build +%ifarch %{ix86} +cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DARCH=x86 +%else +cmake . -DCMAKE_INSTALL_PREFIX=%{_prefix} -DARCH=arm +%endif +make %{?jobs:-j%jobs} + +%install +rm -rf %{buildroot} +mkdir -p %{buildroot}/usr/share/license +cp LICENSE %{buildroot}/usr/share/license/%{name} +%make_install + +%clean +rm -rf %{buildroot} + +%post + +%files +/usr/share/license/%{name} +%manifest debug-launchpad.manifest +%attr(0755, root, root) %{_bindir}/debug_launchpad_preloading_preinitializing_daemon diff --git a/src/app_sock.c b/src/app_sock.c new file mode 100755 index 0000000..1029ab4 --- /dev/null +++ b/src/app_sock.c @@ -0,0 +1,524 @@ +/* + * 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/config.h b/src/config.h new file mode 100755 index 0000000..894d6b6 --- /dev/null +++ b/src/config.h @@ -0,0 +1,30 @@ +/* + * 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. + * + */ + + +#define LAUNCHPAD_LOG +#define DAC_ACTIVATE +#define PRELOAD_ACTIVATE +#define PREEXEC_ACTIVATE +/*#define GL_ACTIVATE*/ +/*#define HEAPDGB_ACTIVATE*/ +/*#define PERF_ACTIVATE*/ + diff --git a/src/fileutils.c b/src/fileutils.c new file mode 100644 index 0000000..061d437 --- /dev/null +++ b/src/fileutils.c @@ -0,0 +1,70 @@ +/* + * 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/fileutils.h b/src/fileutils.h new file mode 100644 index 0000000..948c261 --- /dev/null +++ b/src/fileutils.h @@ -0,0 +1,27 @@ +/* + * 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 _FILEUTILS_H_ +#define _FILEUTILS_H_ + +int dlp_chmod(const char *path, mode_t mode, int recursive); +#endif + diff --git a/src/gl.h b/src/gl.h new file mode 100755 index 0000000..dd59c97 --- /dev/null +++ b/src/gl.h @@ -0,0 +1,32 @@ +/* + * 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 GL_ACTIVATE + +#define USE_ENGINE(engine) setenv("ELM_ENGINE", engine, 1); + +#else + +#define USE_ENGINE(engine) + +#endif + diff --git a/src/heap_dbg.h b/src/heap_dbg.h new file mode 100755 index 0000000..cc51fd8 --- /dev/null +++ b/src/heap_dbg.h @@ -0,0 +1,93 @@ +/* + * 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 new file mode 100755 index 0000000..b28c1e1 --- /dev/null +++ b/src/launchpad.c @@ -0,0 +1,1298 @@ +/* + * 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 "pkgmgr-info.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 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" + +/* 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 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/" + +#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" + +#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; + +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_sdk_env(app_info_from_db* menu_info, char* str) { + 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); + } +} + + +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]); + } + } + } else { + str = bundle_get_val(kb, AUL_K_SDK); + if(str != NULL) { + __set_sdk_env(menu_info, (char *)str); + } + } + if (menu_info->hwacc != NULL) + setenv("HWACC", menu_info->hwacc, 1); + if (menu_info->taskmanage != NULL) + setenv("TASKMANAGE", menu_info->taskmanage, 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 PRIVILEGES*/ + _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); + bundle_del(kb, AUL_K_TASKMANAGE); + + /* 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)); + menu_info->taskmanage = strdup(bundle_get_val(kb, AUL_K_TASKMANAGE)); + + 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; + } + + _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 + , strlen(OPT_VALGRIND_LOGFILE)) == 0) + { + if(strncmp(str_array[i], OPT_VALGRIND_LOGFILE_FIXED + , strlen(str_array[i]))) + { + _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 + , strlen(OPT_VALGRIND_XMLFILE)) == 0) + { + if(strncmp(str_array[i], OPT_VALGRIND_XMLFILE_FIXED + , strlen(str_array[i]))) + { + _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); + } + } + } + } + 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; + pkgmgrinfo_pkginfo_h handle; + bool bPreloaded; + char *storeclientid; + + 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; + + 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) + { + // because of security issue, prevent debugging(ptrace) for preloaded app and downloaded app + if(pkgmgrinfo_pkginfo_get_pkginfo(appid, &handle) == PMINFO_R_OK) + { + pkgmgrinfo_pkginfo_is_preload(handle, &bPreloaded); + pkgmgrinfo_pkginfo_get_storeclientid(handle, &storeclientid); + if(bPreloaded || (storeclientid[0] != '\0')) + { + _E("debugging is not allowed"); + return -1; + } + } + + 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++; + } + /* valgrind */ + else if (strncmp(str_array[i], SDK_VALGRIND + , strlen(str_array[i])) == 0) + { + if (__prepare_valgrind_outputfile(kb)) return 1; + __adjust_file_capability(PATH_MEMCHECK); + } + } + return 0; +} + +/* chmod and chsmack to read file without root privilege */ +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; +} + +/* 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)) 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); + } + + _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/sigchild.h b/src/sigchild.h new file mode 100755 index 0000000..8aa3238 --- /dev/null +++ b/src/sigchild.h @@ -0,0 +1,254 @@ +/* + * 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 "app_signal.h" + +static struct sigaction old_sigchild; +static DBusConnection *bus = NULL; +sigset_t oldmask; + +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; +} + +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_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/simple_util.c b/src/simple_util.c new file mode 100755 index 0000000..dadc183 --- /dev/null +++ b/src/simple_util.c @@ -0,0 +1,210 @@ +/* + * 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; +} + -- 2.7.4