--- /dev/null
+CMAKE_MINIMUM_REQUIRED(VERSION 2.6)
+SET (this_target launchpad)
+
+INCLUDE(FindPkgConfig)
+PKG_CHECK_MODULES(${this_target} REQUIRED
+ dlog
+ ecore
+ elementary
+ libsystemd-daemon
+ dbus-glib-1
+ vconf
+ security-manager
+ bundle
+ )
+
+FOREACH(flag ${${this_target}_CFLAGS})
+ SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} ${flag}")
+ENDFOREACH(flag)
+
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -Wl,-zdefs" )
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fvisibility=hidden")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fPIE")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -fdata-sections -ffunction-sections -Wl,--gc-sections")
+SET(EXTRA_CFLAGS "${EXTRA_CFLAGS} -D_FILE_OFFSET_BITS=64")
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${EXTRA_CFLAGS}")
+SET(CMAKE_C_FLAGS_DEBUG "-O0 -g")
+SET(CMAKE_C_FLAGS_RELEASE "-O2")
+SET(CMAKE_EXE_LINKER_FLAGS "-Wl,--as-needed")
+SET(CMAKE_SKIP_BUILD_RPATH TRUE)
+
+ADD_DEFINITIONS("-DSHARE_PREFIX=\"/usr/share/aul\"")
+IF(_APPFW_FEATURE_PRIORITY_CHANGE)
+ ADD_DEFINITIONS("-D_APPFW_FEATURE_PRIORITY_CHANGE")
+ENDIF(_APPFW_FEATURE_PRIORITY_CHANGE)
+
+ADD_DEFINITIONS("-DLAUNCHPAD_LOG")
+ADD_DEFINITIONS("-DPRELOAD_ACTIVATE")
+ADD_DEFINITIONS("-DPREEXEC_ACTIVATE")
+#ADD_DEFINITIONS("-DPERF_ACTIVATE")
+
+INCLUDE_DIRECTORIES(${CMAKE_SOURCE_DIR}/inc)
+
+SET(LAUNCHPAD_LOADER "launchpad-loader")
+SET(${LAUNCHPAD_LOADER}_SOURCE_FILES
+ src/launchpad_loader.c
+ src/launchpad_common.c
+ )
+ADD_EXECUTABLE(${LAUNCHPAD_LOADER} ${${LAUNCHPAD_LOADER}_SOURCE_FILES})
+
+TARGET_LINK_LIBRARIES(${LAUNCHPAD_LOADER} "-ldl")
+TARGET_LINK_LIBRARIES(${LAUNCHPAD_LOADER} ${${this_target}_LDFLAGS} "-pie")
+
+SET_TARGET_PROPERTIES(${LAUNCHPAD_LOADER}
+ PROPERTIES SKIP_BUILD_RPATH TRUE
+ ) # remove rpath option that is automatically generated by cmake.
+INSTALL(TARGETS ${LAUNCHPAD_LOADER} DESTINATION bin)
+
+SET(LAUNCHPAD_PROCESS_POOL "launchpad-process-pool")
+
+SET(${LAUNCHPAD_PROCESS_POOL}_SOURCE_FILES
+ src/launchpad.c
+ src/launchpad_common.c
+ )
+ADD_EXECUTABLE(${LAUNCHPAD_PROCESS_POOL} ${${LAUNCHPAD_PROCESS_POOL}_SOURCE_FILES})
+
+TARGET_LINK_LIBRARIES(${LAUNCHPAD_PROCESS_POOL} ${${this_target}_LDFLAGS} "-pie")
+
+SET_TARGET_PROPERTIES(${LAUNCHPAD_PROCESS_POOL}
+ PROPERTIES SKIP_BUILD_RPATH TRUE
+ ) # remove rpath option that is automatically generated by cmake.
+
+INSTALL(TARGETS ${LAUNCHPAD_PROCESS_POOL} DESTINATION bin)
+INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/packaging/launchpad-process-pool-preload-list.txt DESTINATION share/aul)
+
--- /dev/null
+
+ 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.
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __KEY_H__
+#define __KEY_H__
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define AUL_K_STARTTIME "__AUL_STARTTIME__"
+#define AUL_K_EXEC "__AUL_EXEC__"
+#define AUL_K_PACKAGETYPE "__AUL_PACKAGETYPE__"
+#define AUL_K_HWACC "__AUL_HWACC__"
+#define AUL_K_APPID "__AUL_APPID__"
+#define AUL_K_PID "__AUL_PID__"
+#define AUL_K_TASKMANAGE "__AUL_TASKMANAGE__"
+#define AUL_K_INTERNAL_POOL "__AUL_INTERNAL_POOL__"
+#define AUL_K_PKGID "__AUL_PKGID_"
+#define AUL_K_DEBUG "__AUL_DEBUG__"
+#define AUL_K_PRIVACY_APPID "__AUL_PRIVACY_APPID__"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __KEY_H__ */
+
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __LAUNCHPAD_COMMON__
+#define __LAUNCHPAD_COMMON__
+
+#include <unistd.h>
+#include <ctype.h>
+#include <dlog.h>
+#include <bundle_internal.h>
+#ifndef __USE_GNU
+ #define __USE_GNU
+#endif
+#include <sys/socket.h>
+#include <linux/un.h>
+
+#include "menu_db_util.h"
+
+#ifdef LAUNCHPAD_LOG
+#undef LOG_TAG
+#define LOG_TAG "LAUNCHPAD"
+#endif
+
+#define MAX_LOCAL_BUFSZ 128
+#define AUL_SOCK_MAXBUFF 65535
+
+#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)
+
+typedef struct _app_pkt_t {
+ int cmd;
+ int len;
+ unsigned char data[1];
+} app_pkt_t;
+
+enum LAUNCHPAD_TYPE {
+ LAUNCHPAD_TYPE_UNSUPPORTED = -1,
+ LAUNCHPAD_TYPE_COMMON,
+ LAUNCHPAD_TYPE_SW,
+ LAUNCHPAD_TYPE_HW,
+ LAUNCHPAD_TYPE_MAX
+};
+
+char *_proc_get_cmdline_bypid(int pid);
+app_info_from_db *_get_app_info_from_bundle_by_pkgname(const char *pkgname, bundle *kb);
+void _modify_bundle(bundle * kb, int caller_pid, app_info_from_db * menu_info, int cmd);
+
+int _create_server_sock(int pid);
+app_pkt_t *_recv_pkt_raw(int fd, int *clifd, struct ucred *cr);
+int _send_pkt_raw(int client_fd, app_pkt_t *pkt);
+int _listen_candidate_process(int type);
+int _connect_to_launchpad(int type);
+int _accept_candidate_process(int server_fd, int* out_client_fd, int* out_client_pid);
+void _refuse_candidate_process(int server_fd);
+void _set_oom(void);
+void _set_env(app_info_from_db * menu_info, bundle * kb);
+char** _create_argc_argv(bundle * kb, int *margc);
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __MENU_DB_UTIL_H_
+#define __MENU_DB_UTIL_H_
+
+#include <string.h>
+#include <stdio.h>
+#include <malloc.h>
+
+#define MAX_PATH_LEN 1024
+
+typedef struct {
+ char *pkg_name; /* appid */
+ char *app_path; /* exec */
+ char *original_app_path; /* exec */
+ char *pkg_type; /* x_slp_packagetype */
+ char *hwacc; /* hwacceleration */
+ char *taskmanage; /* taskmanage */
+ char *pkg_id;
+} 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_pkgid(app_info_from_db *menu_info)
+{
+ return menu_info ? menu_info->pkg_id : 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->pkg_type != NULL)
+ free(menu_info->pkg_type);
+ if (menu_info->hwacc != NULL)
+ free(menu_info->hwacc);
+ if (menu_info->taskmanage != NULL)
+ free(menu_info->taskmanage);
+ if (menu_info->pkg_id != NULL)
+ free(menu_info->pkg_id);
+ free(menu_info);
+ }
+}
+
+#endif
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __PERF_H__
+#define __PERF_H__
+
+#ifdef PERF_ACTIVATE
+
+#include <sys/time.h>
+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
+
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef PREEXEC_ACTIVATE
+
+#include <dlfcn.h>
+#include <glib.h>
+#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_GLOBAL | RTLD_LAZY);
+ 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 || !pkg_type)
+ 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
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#ifdef PRELOAD_ACTIVATE
+
+#include <dlfcn.h>
+#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 **);
+ char *error = NULL;
+
+ if (!preload_initialized)
+ return;
+
+ handle = dlopen(argv[0], RTLD_LAZY | RTLD_GLOBAL);
+ if (handle == NULL) {
+ _E("dlopen(\"%s\") failed", argv[0]);
+ if ((error = dlerror()) != NULL) {
+ _E("dlopen error: %s", error);
+ }
+ return;
+ }
+
+ dlerror();
+
+ dl_main = dlsym(handle, "main");
+ if (dl_main != NULL) {
+ if (__change_cmdline(argv[0]) < 0) {
+ _E("change cmdline fail");
+ dlclose(handle);
+ return;
+ }
+
+#ifdef _APPFW_FEATURE_PRIORITY_CHANGE
+ int res = setpriority(PRIO_PROCESS, 0, 0);
+ if (res == -1)
+ {
+ SECURE_LOGE("Setting process (%d) priority to 0 failed, errno: %d (%s)",
+ getpid(), errno, strerror(errno));
+ }
+#endif
+ dl_main(argc, argv);
+ } else {
+ _E("dlsym not founded. bad preloaded app - check fpie pie");
+ if ((error = dlerror()) != NULL) {
+ _E("dlsym error: %s", error);
+ }
+ dlclose(handle);
+ return;
+ }
+
+ exit(0);
+}
+
+#else
+
+static inline void __preload_init();
+static inline void __preload_exec(int argc, char **argv);
+
+#endif
+
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __PROCESS_POOL_PRELOAD_H__
+#define __PROCESS_POOL_PRELOAD_H__
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <dlfcn.h>
+
+#define PROCESS_POOL_PRELOAD_FILE SHARE_PREFIX"/launchpad-process-pool-preload-list.txt"
+
+static int g_dlopen_size = 5;
+static int g_dlopen_count = 0;
+static void** g_dlopen_handle_list = NULL;
+
+static inline int __preload_save_dlopen_handle(void *handle)
+{
+ if (!handle)
+ return 1;
+
+ if (g_dlopen_count == g_dlopen_size || !g_dlopen_handle_list) {
+ void** tmp =
+ realloc(g_dlopen_handle_list, 2 * g_dlopen_size * sizeof(void *));
+ if (NULL == tmp) {
+ _E("out of memory\n");
+ dlclose(handle);
+ return 1;
+ }
+ g_dlopen_size *= 2;
+ g_dlopen_handle_list = tmp;
+ }
+ g_dlopen_handle_list[g_dlopen_count++] = handle;
+ return 0;
+}
+
+static inline void __preload_fini_for_process_pool(void)
+{
+ int i = 0;
+ if (!g_dlopen_handle_list)
+ return;
+
+ for (i = 0; i < g_dlopen_count; ++i) {
+ void *handle = g_dlopen_handle_list[i];
+ if (handle) {
+ if (0 != dlclose(handle))
+ _E("dlclose failed\n");
+ }
+ }
+ free(g_dlopen_handle_list);
+ g_dlopen_handle_list = NULL;
+ g_dlopen_size = 5;
+ g_dlopen_count = 0;
+}
+
+static inline void __preload_init_for_process_pool(void)
+{
+ if (atexit(__preload_fini_for_process_pool) != 0)
+ _E("Cannot register atexit callback. Libraries will not be unloaded");
+
+ void *handle = NULL;
+ char soname[MAX_LOCAL_BUFSZ] = { 0, };
+ FILE *preload_list = NULL;
+
+ preload_list = fopen(PROCESS_POOL_PRELOAD_FILE, "rt");
+ if (preload_list == NULL) {
+ _E("no preload\n");
+ return;
+ }
+
+ while (fgets(soname, MAX_LOCAL_BUFSZ, preload_list) > 0) {
+ size_t len = strnlen(soname, MAX_LOCAL_BUFSZ);
+ if (len > 0)
+ soname[len - 1] = '\0';
+
+ handle = dlopen((const char *) soname, RTLD_NOW);
+ if (handle == NULL) {
+ _E("dlopen(\"%s\") was failed!", soname);
+ continue;
+ }
+
+ if (__preload_save_dlopen_handle(handle) != 0) {
+ _E("Cannot save handle, no more preloads");
+ break;
+ }
+ _D("preload %s# - handle : %x\n", soname, handle);
+ }
+
+ fclose(preload_list);
+}
+
+#endif //__PROCESS_POOL_PRELOAD_H__
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <dbus/dbus.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/signalfd.h>
+#include <dirent.h>
+
+#define AUL_DBUS_PATH "/aul/dbus_handler"
+#define AUL_DBUS_SIGNAL_INTERFACE "org.tizen.aul.signal"
+#define AUL_DBUS_APPDEAD_SIGNAL "app_dead"
+#define AUL_DBUS_APPLAUNCH_SIGNAL "app_launch"
+
+static DBusConnection *bus = NULL;
+static sigset_t oldmask;
+
+static inline void __socket_garbage_collector()
+{
+ DIR *dp;
+ struct dirent *dentry;
+ char tmp[MAX_LOCAL_BUFSZ];
+
+ snprintf(tmp, sizeof(tmp), "/run/user/%d", getuid());
+ dp = opendir(tmp);
+ 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, "/run/user/%d/%s", getuid(),
+ dentry->d_name);
+ unlink(tmp);
+ continue;
+ }
+ }
+ closedir(dp);
+}
+
+static inline int __send_app_dead_signal_dbus(int dead_pid)
+{
+ DBusMessage *message;
+
+ // send over session dbus for other applications
+ 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_app_dead_signal_dbus done (pid=%d)\n",dead_pid);
+
+ return 0;
+}
+
+static inline int __send_app_launch_signal_dbus(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_app_launch_signal_dbus done (pid=%d)",launch_pid);
+
+ return 0;
+}
+
+static int __sigchild_action(void *data)
+{
+ pid_t dead_pid;
+ char buf[MAX_LOCAL_BUFSZ];
+
+ dead_pid = (pid_t)(intptr_t)data;
+ if (dead_pid <= 0)
+ goto end;
+
+ __send_app_dead_signal_dbus(dead_pid);
+
+ snprintf(buf, MAX_LOCAL_BUFSZ, "/run/user/%d/%d", getuid(), dead_pid);
+ unlink(buf);
+
+ __socket_garbage_collector();
+ end:
+ return 0;
+}
+
+static void __launchpad_process_sigchld(struct signalfd_siginfo *info)
+{
+ int status;
+ pid_t child_pid;
+ pid_t child_pgid;
+
+ child_pgid = getpgid(info->ssi_pid);
+ _D("dead_pid = %d pgid = %d", info->ssi_pid, child_pgid);
+
+ while ((child_pid = waitpid(-1, &status, WNOHANG)) > 0) {
+ if (child_pid == child_pgid)
+ killpg(child_pgid, SIGKILL);
+ __sigchild_action((void *)(intptr_t)child_pid);
+ }
+
+ return;
+}
+
+static inline int __signal_init(void)
+{
+ int i;
+ DBusError error;
+
+ dbus_error_init(&error);
+ dbus_threads_init_default();
+ bus = dbus_bus_get_private(DBUS_BUS_SESSION, &error);
+ if (!bus) {
+ _E("Failed to connect to the D-BUS daemon: %s", error.message);
+ dbus_error_free(&error);
+ return -1;
+ }
+
+ for (i = 0; i < _NSIG; i++) {
+ switch (i) {
+ /* controlled by sys-assert package*/
+ case SIGQUIT:
+ case SIGILL:
+ case SIGABRT:
+ case SIGBUS:
+ case SIGFPE:
+ case SIGSEGV:
+ case SIGPIPE:
+ break;
+ default:
+ signal(i, SIG_DFL);
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static inline int __signal_get_sigchld_fd(void)
+{
+ sigset_t mask;
+ int sfd;
+
+ sigemptyset(&mask);
+ sigaddset(&mask, SIGCHLD);
+
+ if (sigprocmask(SIG_BLOCK, &mask, &oldmask) == -1)
+ _E("failed to sigprocmask");
+
+ sfd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC);
+ if (sfd == -1) {
+ _E("failed to create signal for SIGCHLD");
+ return -1;
+ }
+
+ return sfd;
+}
+
+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)
+{
+ if (bus)
+ dbus_connection_close(bus);
+
+#ifndef PRELOAD_ACTIVATE
+ int i;
+ for (i = 0; i < _NSIG; i++)
+ signal(i, SIG_DFL);
+#endif
+ return 0;
+}
+
--- /dev/null
+<manifest>
+ <request>
+ <domain name="_"/>
+ </request>
+</manifest>
--- /dev/null
+#
+# Systemd script to Launch AMD Session agent
+#
+
+[Unit]
+Description=Start the USER Access Control Agent
+
+[Service]
+ExecStart=/bin/sh -l -c "/usr/bin/launchpad-process-pool"
+Sockets=launchpad-process-pool.socket
--- /dev/null
+[Socket]
+ListenStream=/run/user/%U/-5
+ListenStream=/run/user/%U/.launchpad-type0
+ListenStream=/run/user/%U/.launchpad-type1
+ListenStream=/run/user/%U/.launchpad-type2
+
+Service=launchpad-process-pool.service
+
+[Install]
+WantedBy=sockets.target
--- /dev/null
+Name: launchpad
+Summary: Launchpad for launching applications
+Version: 0.2.3.14
+Release: 1
+Group: Application Framework/Daemons
+License: Apache-2.0
+Source0: %{name}-%{version}.tar.gz
+Source101: launchpad-process-pool.service
+Source102: launchpad-process-pool.socket
+
+
+BuildRequires: cmake
+BuildRequires: pkgconfig(bundle)
+BuildRequires: pkgconfig(dbus-glib-1)
+BuildRequires: pkgconfig(sqlite3)
+BuildRequires: pkgconfig(ecore)
+BuildRequires: pkgconfig(dlog)
+BuildRequires: pkgconfig(libsystemd-daemon)
+BuildRequires: pkgconfig(elementary)
+BuildRequires: pkgconfig(vconf)
+BuildRequires: pkgconfig(security-manager)
+
+Requires(post): /sbin/ldconfig
+Requires(post): /usr/bin/systemctl
+Requires(postun): /sbin/ldconfig
+Requires(postun): /usr/bin/systemctl
+Requires(preun): /usr/bin/systemctl
+
+%define appfw_feature_priority_change 0
+
+%description
+Launchpad for launching applications
+
+%package devel
+Summary: Launchpad for launching applications (devel)
+Group: Development/Libraries
+Requires: %{name} = %{version}-%{release}
+
+%description devel
+Launchpad for launching applications (devel)
+
+%prep
+%setup -q
+
+%build
+%if 0%{?sec_build_binary_debug_enable}
+export CFLAGS="$CFLAGS -DTIZEN_DEBUG_ENABLE"
+export CXXFLAGS="$CXXFLAGS -DTIZEN_DEBUG_ENABLE"
+export FFLAGS="$FFLAGS -DTIZEN_DEBUG_ENABLE"
+%endif
+%if 0%{?appfw_feature_priority_change}
+_APPFW_FEATURE_PRIORITY_CHANGE=ON
+%endif
+
+cmake -DCMAKE_INSTALL_PREFIX=%{_prefix} \
+ -D_APPFW_FEATURE_PRIORITY_CHANGE:BOOL=${_APPFW_FEATURE_PRIORITY_CHANGE}
+
+make %{?jobs:-j%jobs}
+
+%install
+rm -rf %{buildroot}
+
+%make_install
+mkdir -p %{buildroot}%{_unitdir_user}/default.target.wants
+mkdir -p %{buildroot}%{_unitdir_user}/sockets.target.wants
+install -m 0644 %SOURCE101 %{buildroot}%{_unitdir_user}/launchpad-process-pool.service
+install -m 0644 %SOURCE102 %{buildroot}%{_unitdir_user}/launchpad-process-pool.socket
+ln -sf ../launchpad-process-pool.socket %{buildroot}%{_unitdir_user}/sockets.target.wants/launchpad-process-pool.socket
+ln -sf ../launchpad-process-pool.service %{buildroot}%{_unitdir_user}/default.target.wants/launchpad-process-pool.service
+
+mkdir -p %{buildroot}/usr/share/license
+cp %{_builddir}/%{name}-%{version}/LICENSE %{buildroot}/usr/share/license/%{name}
+
+%post
+
+%files
+%manifest launchpad.manifest
+%{_prefix}/share/license/%{name}
+%{_prefix}/share/aul/launchpad-process-pool-preload-list.txt
+%{_unitdir_user}/launchpad-process-pool.service
+%{_unitdir_user}/launchpad-process-pool.socket
+%{_unitdir_user}/sockets.target.wants/launchpad-process-pool.socket
+%{_unitdir_user}/default.target.wants/launchpad-process-pool.service
+%caps(cap_mac_admin,cap_mac_override,cap_setgid=ei) %{_bindir}/launchpad-process-pool
+%caps(cap_mac_admin,cap_mac_override,cap_setgid=ei) %{_bindir}/launchpad-loader
+
--- /dev/null
+/usr/lib/libappcore-efl.so.1
+/usr/lib/libappcore-common.so.1
+/usr/lib/libcapi-appfw-application.so.0
+/usr/lib/ecore/immodules/libisf-imf-module.so
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <poll.h>
+#include <stdlib.h>
+#include <sys/prctl.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <malloc.h>
+#include <bundle_internal.h>
+#include <security-manager.h>
+#include <time.h>
+
+#include "perf.h"
+#include "launchpad_common.h"
+#include "sigchild.h"
+#include "key.h"
+
+#define AUL_PR_NAME 16
+#define AUL_POLL_CNT 15
+#define EXEC_CANDIDATE_EXPIRED 5
+#define EXEC_CANDIDATE_WAIT 1
+#define DIFF(a,b) (((a)>(b))?(a)-(b):(b)-(a))
+#define CANDIDATE_NONE 0
+#define PROCESS_POOL_LAUNCHPAD_PID -5
+
+typedef struct {
+ int pid;
+ int send_fd;
+ int last_exec_time;
+} candidate;
+
+enum {
+ LAUNCH_PAD = 0,
+ POOL_TYPE = 1,
+ CANDIDATE_TYPE = LAUNCHPAD_TYPE_MAX + 1,
+ SIGCHLD_FD = LAUNCHPAD_TYPE_MAX * 2 + 1,
+ POLLFD_MAX = LAUNCHPAD_TYPE_MAX * 2 + 2
+};
+
+static int initialized = 0;
+static candidate __candidate[LAUNCHPAD_TYPE_MAX] = {
+ { CANDIDATE_NONE, -1, 0 },
+ { CANDIDATE_NONE, -1, 0 }
+};
+static int launchpad_fd = -1;
+static int pool_fd[LAUNCHPAD_TYPE_MAX] = { -1, -1, -1 };
+
+static int __set_access(const char* appId, const char* pkg_type,
+ const char* app_path)
+{
+ return security_manager_prepare_app(appId) == SECURITY_MANAGER_SUCCESS ? 0 : -1;
+}
+
+static int __get_launchpad_type(const char* internal_pool, const char* hwacc)
+{
+ if (internal_pool && strncmp(internal_pool, "true", 4) == 0 && hwacc) {
+ if (strncmp(hwacc, "NOT_USE", 7) == 0) {
+ _D("[launchpad] launchpad type: S/W(%d)", LAUNCHPAD_TYPE_SW);
+ return LAUNCHPAD_TYPE_SW;
+ }
+ if (strncmp(hwacc, "USE", 3) == 0) {
+ _D("[launchpad] launchpad type: H/W(%d)", LAUNCHPAD_TYPE_HW);
+ return LAUNCHPAD_TYPE_HW;
+ }
+ /* TODO: FIXME
+ if (strncmp(hwacc, "SYS", 3) == 0) {
+ int r;
+ int sys_hwacc = -1;
+
+ r = vconf_get_int(VCONFKEY_SETAPPL_APP_HW_ACCELERATION, &sys_hwacc);
+ if (r != VCONF_OK)
+ _E("failed to get vconf int: %s", VCONFKEY_SETAPPL_APP_HW_ACCELERATION);
+
+ SECURE_LOGD("sys hwacc: %d", sys_hwacc);
+
+ if (sys_hwacc == SETTING_HW_ACCELERATION_ON) {
+ _D("[launchpad] launchpad type: H/W(%d)", LAUNCHPAD_TYPE_HW);
+ return LAUNCHPAD_TYPE_HW;
+ }
+ if (sys_hwacc == SETTING_HW_ACCELERATION_OFF) {
+ _D("[launchpad] launchpad type: S/W(%d)", LAUNCHPAD_TYPE_SW);
+ return LAUNCHPAD_TYPE_SW;
+ }
+ }*/
+ }
+
+ _D("[launchpad] launchpad type: COMMON(%d)", LAUNCHPAD_TYPE_COMMON);
+ return LAUNCHPAD_TYPE_COMMON;
+}
+
+static int __candidate_process_real_launch(int candidate_fd, app_pkt_t *pkt)
+{
+ return _send_pkt_raw(candidate_fd, pkt);
+}
+
+static int __real_send(int clifd, int ret)
+{
+ if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) {
+ if (errno == EPIPE) {
+ _E("send failed due to EPIPE.\n");
+ close(clifd);
+ return -1;
+ }
+ _E("send fail to client");
+ }
+
+ close(clifd);
+ return 0;
+}
+
+static void __send_result_to_caller(int clifd, int ret, const char* app_path)
+{
+ char *cmdline;
+ int wait_count;
+ int cmdline_changed = 0;
+ int cmdline_exist = 0;
+ int r;
+
+ _W("Check app launching");
+
+ if (clifd == -1)
+ return;
+
+ if (ret <= 1) {
+ _E("launching failed");
+ __real_send(clifd, ret);
+ return;
+ }
+ /* check normally was launched?*/
+ wait_count = 1;
+ do {
+ cmdline = _proc_get_cmdline_bypid(ret);
+ if (cmdline == NULL) {
+ _E("error founded when being launched with %d", ret);
+ if (cmdline_exist || cmdline_changed) {
+ _E("The app process might be terminated while we are wating %d", ret);
+ break;
+ }
+ } else if (strcmp(cmdline, app_path) == 0) {
+ /* Check app main loop is prepared or not */
+ _D("-- now wait app mainloop creation --");
+ free(cmdline);
+ cmdline_changed = 1;
+
+ char sock_path[UNIX_PATH_MAX] = { 0, };
+ snprintf(sock_path, UNIX_PATH_MAX, "/run/user/%d/%d", getuid(), ret);
+ if (access(sock_path, F_OK) == 0)
+ break;
+
+ } else {
+ _D("-- now wait cmdline changing --");
+ cmdline_exist = 1;
+ free(cmdline);
+ }
+ usleep(100 * 1000); /* 100ms sleep*/
+ wait_count++;
+
+ } while (wait_count <= 50); /* max 100*50ms will be sleep*/
+
+ if ((!cmdline_exist) && (!cmdline_changed)) {
+ __real_send(clifd, -1); /* abnormally launched*/
+ return;
+ }
+
+ if (!cmdline_changed)
+ _E("process launched, but cmdline not changed");
+
+ if (__real_send(clifd, ret) < 0) {
+ r = kill(ret, SIGKILL);
+ if (r == -1) {
+ char err_str[MAX_LOCAL_BUFSZ] = { 0, };
+
+ _E("send SIGKILL: %s", strerror_r(errno, err_str, sizeof(err_str)));
+ }
+ }
+
+ return;
+}
+
+static void __prepare_candidate_process(int type)
+{
+ int pid;
+
+ __candidate[type].last_exec_time = time(NULL);
+ pid = fork();
+
+ if (pid == 0) { /* child */
+ char type_str[2] = {0,};
+
+ /* execute with very long (1024 bytes) argument in order to prevent argv overflow caused by dlopen */
+ char *argv[] = {"/usr/bin/launchpad-loader", NULL,
+ " ", NULL
+ };
+ __signal_unblock_sigchld();
+
+ type_str[0] = '0' + type;
+ argv[1] = type_str;
+ if (execv(argv[0], argv) < 0)
+ _E("Failed to prepare candidate_process");
+ else
+ _D("Succeeded to prepare candidate_process");
+
+ exit(-1);
+ }
+}
+
+static void __sleep_safe(time_t sec)
+{
+ struct timespec delay, remain;
+ delay.tv_sec = sec;
+ delay.tv_nsec = 0;
+ remain.tv_sec = 0;
+ remain.tv_nsec = 0;
+
+ while (nanosleep(&delay, &remain)) {
+ if (errno == EINTR) {
+ delay.tv_sec = remain.tv_sec;
+ delay.tv_nsec = remain.tv_nsec;
+ } else {
+ char err_str[MAX_LOCAL_BUFSZ] = { 0, };
+
+ _D("nanosleep() failed, errno: %d (%s)", errno,
+ strerror_r(errno, err_str, sizeof(err_str)));
+ break;
+ }
+ }
+}
+
+static int __send_launchpad_loader(int type, app_pkt_t *pkt,
+ const char *app_path, int clifd)
+{
+ char sock_path[UNIX_PATH_MAX] = { 0, };
+ int pid = -1;
+
+ snprintf(sock_path, UNIX_PATH_MAX, "/run/user/%d/%d", getuid(),
+ __candidate[type].pid);
+ unlink(sock_path);
+
+ __candidate_process_real_launch(__candidate[type].send_fd, pkt);
+ SECURE_LOGD("Request to candidate process, pid: %d, bin path: %s",
+ __candidate[type].pid, app_path);
+
+ pid = __candidate[type].pid;
+ close(__candidate[type].send_fd);
+
+ __candidate[type].pid = CANDIDATE_NONE;
+ __candidate[type].send_fd = -1;
+
+ /* Temporary log: launch time checking */
+ //SECURE_LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:launchpad:done]", app_path);
+
+ __send_result_to_caller(clifd, pid, app_path); //to AMD
+
+ __sleep_safe(1); //1 sec
+ __prepare_candidate_process(type);
+
+ _D("Prepare another candidate process");
+ return pid;
+}
+
+static int __normal_fork_exec(int argc, char **argv)
+{
+ _D("start real fork and exec\n");
+
+ if (execv(argv[0], argv) < 0) { /* Flawfinder: ignore */
+ if (errno == EACCES)
+ _E("such a file is no executable - %s", argv[0]);
+ else
+ _E("unknown executable error - %s", argv[0]);
+ return -1;
+ }
+ /* never reach*/
+ return 0;
+}
+
+static void __real_launch(const char *app_path, bundle * kb)
+{
+ int app_argc;
+ char **app_argv;
+ int i;
+
+ if (bundle_get_val(kb, AUL_K_DEBUG) != NULL)
+ putenv("TIZEN_DEBUGGING_PORT=1");
+
+ app_argv = _create_argc_argv(kb, &app_argc);
+ app_argv[0] = strdup(app_path);
+
+ for (i = 0; i < app_argc; i++) {
+ if ((i % 2) == 1)
+ continue;
+ SECURE_LOGD("input argument %d : %s##", i, app_argv[i]);
+ }
+
+ PERF("setup argument done");
+ __normal_fork_exec(app_argc, app_argv);
+}
+
+static int __prepare_exec(const char *appId, 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();
+
+ /* SET OOM*/
+ _set_oom();
+
+ /* SET PRIVILEGES*/
+ if (bundle_get_val(kb, AUL_K_PRIVACY_APPID) == NULL) {
+ _D("appId: %s / pkg_type : %s / app_path : %s ", appId, menu_info->pkg_type,
+ app_path);
+ if ((ret = __set_access(appId, 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;
+}
+
+static int __launch_directly(const char *appid, const char *app_path, int clifd,
+ bundle* kb, app_info_from_db *menu_info)
+{
+ char sock_path[UNIX_PATH_MAX] = {0,};
+ int pid = fork();
+
+ if (pid == 0) {
+ PERF("fork done");
+ _D("lock up test log(no error) : fork done");
+
+ close(clifd);
+ __signal_unblock_sigchld();
+ __signal_fini();
+
+ snprintf(sock_path, UNIX_PATH_MAX, "/run/user/%d/%d", getuid(), getpid());
+ unlink(sock_path);
+
+ PERF("prepare exec - first done");
+ _D("lock up test log(no error) : prepare exec - first done");
+
+ if (__prepare_exec(appid, app_path,
+ menu_info, kb) < 0) {
+ SECURE_LOGE("preparing work fail to launch - "
+ "can not launch %s\n", appid);
+ exit(-1);
+ }
+
+ PERF("prepare exec - second done");
+ _D("lock up test log(no error) : prepare exec - second done");
+ __real_launch(app_path, kb);
+
+ exit(-1);
+ }
+ SECURE_LOGD("==> real launch pid : %d %s\n", pid, app_path);
+
+ return pid;
+}
+
+static void __launchpad_main_loop(int launchpad_fd, int *pool_fd)
+{
+ bundle *kb = NULL;
+ app_pkt_t *pkt = NULL;
+ app_info_from_db *menu_info = NULL;
+
+ const char *pkg_name = NULL;
+ const char *internal_pool = NULL;
+ const char *app_path = NULL;
+ int pid = -1;
+ int clifd = -1;
+ struct ucred cr;
+ int type = -1;
+
+ pkt = _recv_pkt_raw(launchpad_fd, &clifd, &cr);
+ if (!pkt) {
+ _E("packet is NULL");
+ goto end;
+ }
+
+ kb = bundle_decode(pkt->data, pkt->len);
+ if (!kb) {
+ _E("bundle decode error");
+ goto end;
+ }
+
+ INIT_PERF(kb);
+ PERF("packet processing start");
+
+ pkg_name = bundle_get_val(kb, AUL_K_APPID);
+ SECURE_LOGD("pkg name : %s\n", pkg_name);
+
+ menu_info = _get_app_info_from_bundle_by_pkgname(pkg_name, kb);
+ if (menu_info == NULL) {
+ _E("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] != '/') {
+ _E("app_path is not absolute path");
+ goto end;
+ }
+
+ if (menu_info->hwacc == NULL) {
+ _E("[launchpad] Failed to find H/W acceleration type");
+ goto end;
+ }
+
+ internal_pool = bundle_get_val(kb, AUL_K_EXEC);
+ SECURE_LOGD("exec : %s\n", internal_pool);
+ internal_pool = bundle_get_val(kb, AUL_K_INTERNAL_POOL);
+
+ SECURE_LOGD("internal pool : %s\n", internal_pool);
+ SECURE_LOGD("hwacc : %s\n", menu_info->hwacc);
+ type = __get_launchpad_type(internal_pool, menu_info->hwacc);
+ if (type < 0) {
+ _E("failed to get launchpad type");
+ goto end;
+ }
+
+ _modify_bundle(kb, cr.pid, menu_info, pkt->cmd);
+ pkg_name = _get_pkgname(menu_info);
+ if (pkg_name == NULL) {
+ _E("unable to get pkg_name from menu_info");
+ goto end;
+ }
+
+ PERF("get package information & modify bundle done");
+
+ if ((type >= 0) && (type < LAUNCHPAD_TYPE_MAX)
+ && (__candidate[type].pid != CANDIDATE_NONE)
+ && (DIFF(__candidate[type].last_exec_time, time(NULL)) > EXEC_CANDIDATE_WAIT)) {
+ _W("Launch on type-based process-pool");
+ pid = __send_launchpad_loader(type, pkt, app_path, clifd);
+ } else if ((__candidate[LAUNCHPAD_TYPE_COMMON].pid != CANDIDATE_NONE)
+ && (DIFF(__candidate[LAUNCHPAD_TYPE_COMMON].last_exec_time,
+ time(NULL)) > EXEC_CANDIDATE_WAIT)) {
+ _W("Launch on common type process-pool");
+ pid = __send_launchpad_loader(LAUNCHPAD_TYPE_COMMON, pkt, app_path, clifd);
+ } else {
+ _W("Candidate is not prepared");
+ pid = __launch_directly(pkg_name, app_path, clifd, kb, menu_info);
+ __send_result_to_caller(clifd, pid, app_path);
+ }
+ clifd = -1;
+
+end:
+ if (clifd != -1)
+ close(clifd);
+
+ if (pid > 0) {
+ __send_app_launch_signal_dbus(pid);
+ }
+
+ if (menu_info != NULL)
+ _free_app_info_from_db(menu_info);
+
+ if (kb != NULL)
+ bundle_free(kb);
+ if (pkt != NULL)
+ free(pkt);
+
+ /* Active Flusing for Daemon */
+ if (initialized > AUL_POLL_CNT) {
+ malloc_trim(0);
+ initialized = 1;
+ }
+}
+
+static int __launchpad_pre_init(int argc, char **argv)
+{
+ int fd;
+
+ /* signal init*/
+ __signal_init();
+
+ /* create launchpad sock */
+ fd = _create_server_sock(PROCESS_POOL_LAUNCHPAD_PID);
+ if (fd < 0) {
+ _E("server sock error %d", fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+static 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;
+ }
+
+ ++initialized;
+
+ return 0;
+}
+
+static int __init_pfds(struct pollfd *pfds, int argc, char **argv)
+{
+ int sigchld_fd = -1;
+ int i;
+
+ /* init without concerning X & EFL*/
+ launchpad_fd = __launchpad_pre_init(argc, argv);
+ if (launchpad_fd < 0) {
+ _E("launchpad pre init failed");
+ exit(-1);
+ }
+ pfds[LAUNCH_PAD].fd = launchpad_fd;
+ pfds[LAUNCH_PAD].events = POLLIN;
+ pfds[LAUNCH_PAD].revents = 0;
+
+ for (i = 0; i < LAUNCHPAD_TYPE_MAX; ++i) {
+ pool_fd[i] = _listen_candidate_process(i);
+ if (pool_fd[i] == -1) {
+ _E("[launchpad] Listening the socket to the type %d candidate process failed.",
+ i);
+ return -1;
+ }
+ pfds[POOL_TYPE + i].fd = pool_fd[i];
+ pfds[POOL_TYPE + i].events = POLLIN;
+ pfds[POOL_TYPE + i].revents = 0;
+ }
+
+ sigchld_fd = __signal_get_sigchld_fd();
+ if (sigchld_fd == -1) {
+ _E("failed to get sigchld fd");
+ return -1;
+ }
+ pfds[SIGCHLD_FD].fd = sigchld_fd;
+ pfds[SIGCHLD_FD].events = POLLIN;
+ pfds[SIGCHLD_FD].revents = 0;
+
+ return 0;
+}
+
+static int __loop_begin(struct pollfd *pfds)
+{
+ int i;
+
+ while (1) {
+ for (i = 0; i < LAUNCHPAD_TYPE_MAX; ++i) {
+ if (__candidate[i].pid == CANDIDATE_NONE) {
+ pfds[CANDIDATE_TYPE + i].fd = -1;
+ pfds[CANDIDATE_TYPE + i].events = 0;
+ pfds[CANDIDATE_TYPE + i].revents = 0;
+
+ if (DIFF(__candidate[i].last_exec_time, time(NULL)) > EXEC_CANDIDATE_EXPIRED)
+ __prepare_candidate_process(i);
+ }
+ }
+
+ if (poll(pfds, POLLFD_MAX, -1) < 0)
+ continue;
+
+ _D("pfds[LAUNCH_PAD].revent : 0x%x", pfds[LAUNCH_PAD].revents) ;
+ for (i = 0; i < LAUNCHPAD_TYPE_MAX; ++i) {
+ _D("pfds[POOL_TYPE + %d].revents : 0x%x", i, pfds[POOL_TYPE + i].revents) ;
+ _D("pfds[CANDIDATE_TYPE + %d].revents : 0x%x", i,
+ pfds[CANDIDATE_TYPE + i].revents);
+ }
+
+ /* init with concerning X & EFL (because of booting
+ * sequence problem)*/
+ if (__launchpad_post_init() < 0) {
+ _E("launcpad post init failed");
+ return -1;
+ }
+
+ if ((pfds[SIGCHLD_FD].revents & POLLIN) != 0) {
+ struct signalfd_siginfo siginfo;
+ ssize_t s;
+
+ do {
+ s = read(pfds[SIGCHLD_FD].fd, &siginfo, sizeof(struct signalfd_siginfo));
+ if (s == 0)
+ break;
+
+ if (s != sizeof(struct signalfd_siginfo)) {
+ _E("error reading sigchld info");
+ break;
+ }
+ __launchpad_process_sigchld(&siginfo);
+ } while (s > 0);
+ }
+
+ if ((pfds[LAUNCH_PAD].revents & POLLIN) != 0) {
+ _D("pfds[LAUNCH_PAD].revents & POLLIN");
+ __launchpad_main_loop(pfds[LAUNCH_PAD].fd, pool_fd);
+ }
+
+ for (i = 0; i < LAUNCHPAD_TYPE_MAX; ++i) {
+ if ((pfds[POOL_TYPE + i].revents & POLLIN) != 0) {
+ int server_fd, client_fd;
+ int client_pid;
+
+ server_fd = pfds[POOL_TYPE + i].fd;
+
+ _D("pfds[POOL_TYPE + %d].revents & POLLIN", i);
+
+ if (__candidate[i].pid == CANDIDATE_NONE) {
+ _accept_candidate_process(server_fd, &client_fd, &client_pid);
+
+ __candidate[i].pid = client_pid;
+ __candidate[i].send_fd = client_fd;
+
+ pfds[CANDIDATE_TYPE + i].fd = client_fd;
+ pfds[CANDIDATE_TYPE + i].events = POLLIN | POLLHUP;
+ pfds[CANDIDATE_TYPE + i].revents = 0;
+
+ SECURE_LOGD("Type %d candidate process was connected, pid: %d", i,
+ __candidate[i].pid);
+ } else {
+ _refuse_candidate_process(server_fd);
+ _E("Refused candidate process connection");
+ }
+ }
+
+ if ((pfds[CANDIDATE_TYPE + i].revents & (POLLHUP | POLLNVAL)) != 0) {
+ SECURE_LOGD("pfds[CANDIDATE_TYPE + %d].revents & (POLLHUP|POLLNVAL), pid: %d",
+ i, __candidate[i].pid);
+
+ if (pfds[CANDIDATE_TYPE + i].fd > -1)
+ close(pfds[CANDIDATE_TYPE + i].fd);
+
+ __candidate[i].pid = CANDIDATE_NONE;
+ __candidate[i].send_fd = -1;
+
+ pfds[CANDIDATE_TYPE + i].fd = -1;
+ pfds[CANDIDATE_TYPE + i].events = 0;
+ pfds[CANDIDATE_TYPE + i].revents = 0;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ int i;
+ struct pollfd pfds[POLLFD_MAX];
+
+ memset(pfds, 0x00, sizeof(pfds));
+ if (__init_pfds(pfds, argc, argv) != 0)
+ goto error;
+
+#ifdef _APPFW_FEATURE_PRIORITY_CHANGE
+ int res = setpriority(PRIO_PROCESS, 0, -12);
+ if (res == -1) {
+ char err_str[MAX_LOCAL_BUFSZ] = { 0, };
+
+ SECURE_LOGE("Setting process (%d) priority to -12 failed, errno: %d (%s)",
+ getpid(), errno, strerror_r(errno, err_str, sizeof(err_str)));
+ }
+#endif
+ if (__loop_begin(pfds) == 0)
+ return 0;
+
+error:
+ if (launchpad_fd != -1)
+ close(launchpad_fd);
+
+ for (i = 0; i < LAUNCHPAD_TYPE_MAX; ++i) {
+ if (pool_fd[i] != -1)
+ close(pool_fd[i]);
+ if (__candidate[i].send_fd != -1)
+ close(__candidate[i].send_fd);
+ }
+
+ return -1;
+}
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/xattr.h>
+#include <errno.h>
+#include <systemd/sd-daemon.h>
+
+#include "launchpad_common.h"
+#include "key.h"
+
+#define BINSH_NAME "/bin/sh"
+#define BINSH_SIZE 7
+#define VALGRIND_NAME "/home/developer/sdk_tools/valgrind/usr/bin/valgrind"
+#define VALGRIND_SIZE 51
+#define BASH_NAME "/bin/bash"
+#define BASH_SIZE 9
+#define OPROFILE_NAME "/usr/bin/oprofile_command"
+#define OPROFILE_SIZE 25
+#define OPTION_VALGRIND_NAME "valgrind"
+#define OPTION_VALGRIND_SIZE 8
+#define MAX_CMD_BUFSZ 1024
+
+#define SOCKET_PATH "/run/user"
+#define LAUNCHPAD_TYPE ".launchpad-type"
+#define MAX_PENDING_CONNECTIONS 10
+#define CONNECT_RETRY_TIME 100 * 1000
+#define CONNECT_RETRY_COUNT 3
+#define AUL_PKT_HEADER_SIZE (sizeof(int) + sizeof(int))
+
+#define APP_START 0
+#define APP_OPEN 1
+#define APP_RESUME 2
+#define APP_START_RES 3
+
+static int __read_proc(const char *path, char *buf, int size)
+{
+ int fd;
+ int ret;
+
+ if (buf == NULL || path == NULL)
+ return -1;
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0)
+ return -1;
+
+ ret = read(fd, buf, size - 1);
+ if (ret <= 0) {
+ close(fd);
+ return -1;
+ } else
+ buf[ret] = 0;
+
+ close(fd);
+
+ return ret;
+}
+
+static void __set_sock_option(int fd, int cli)
+{
+ int size;
+ struct timeval tv = { 5, 200 * 1000 }; /* 5.2 sec */
+
+ size = AUL_SOCK_MAXBUFF;
+ setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
+ setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
+ if (cli)
+ setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
+}
+
+static int __parse_app_path(const char *arg, char *out, int out_size)
+{
+ register int i;
+ int state = 1;
+ char *start_out = out;
+
+ if (arg == NULL || out == NULL) {
+ /* Handles null buffer*/
+ return 0;
+ }
+
+ for (i = 0; out_size > 1; i++) {
+ switch (state) {
+ case 1:
+ switch (arg[i]) {
+ case ' ':
+ case '\t':
+ state = 5;
+ break;
+ case '\0':
+ state = 7;
+ break;
+ case '\"':
+ state = 2;
+ break;
+ case '\\':
+ state = 4;
+ break;
+ default:
+ *out = arg[i];
+ out++;
+ out_size--;
+ break;
+ }
+ break;
+ case 2: /* escape start*/
+ switch (arg[i]) {
+ case '\0':
+ state = 6;
+ break;
+ case '\"':
+ state = 1;
+ break;
+ default:
+ *out = arg[i];
+ out++;
+ out_size--;
+ break;
+ }
+ break;
+ case 4: /* character escape*/
+ if (arg[i] == '\0') {
+ state = 6;
+ } else {
+ *out = arg[i];
+ out++;
+ out_size--;
+ state = 1;
+ }
+ break;
+ case 5: /* token*/
+ if (out != start_out) {
+ *out = '\0';
+ out_size--;
+ return i;
+ }
+ i--;
+ state = 1;
+ break;
+ case 6:
+ return -1; /* error*/
+ case 7: /* terminate*/
+ *out = '\0';
+ out_size--;
+ return 0;
+ default:
+ state = 6;
+ break; /* error*/
+ }
+ }
+
+ if (out_size == 1)
+ *out = '\0';
+
+ /* Buffer overflow*/
+ return -2;
+}
+
+int _create_server_sock(int pid)
+{
+ struct sockaddr_un saddr;
+ int fd;
+
+ fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ /* support above version 2.6.27*/
+ if (fd < 0) {
+ if (errno == EINVAL) {
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0) {
+ _E("second chance - socket create error");
+ return -1;
+ }
+ } else {
+ _E("socket error");
+ return -1;
+ }
+ }
+
+ memset(&saddr, 0, sizeof(saddr));
+ saddr.sun_family = AF_UNIX;
+ snprintf(saddr.sun_path, UNIX_PATH_MAX, "/run/user/%d/%d", getuid(), pid);
+ unlink(saddr.sun_path);
+
+ if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
+ _E("bind error");
+ close(fd);
+ return -1;
+ }
+
+ if (chmod(saddr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
+ /* Flawfinder: ignore*/
+ _E("failed to change the socket permission");
+ close(fd);
+ return -1;
+ }
+
+ __set_sock_option(fd, 0);
+
+ if (listen(fd, 128) == -1) {
+ _E("listen error");
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}
+
+app_pkt_t *_recv_pkt_raw(int fd, int *clifd, struct ucred *cr)
+{
+ int len;
+ int ret;
+ struct sockaddr_un aul_addr = { 0, };
+ int sun_size;
+ app_pkt_t *pkt = NULL;
+ int cl = sizeof(struct ucred);
+ unsigned char buf[AUL_SOCK_MAXBUFF];
+ int cmd;
+ int datalen;
+
+ sun_size = sizeof(struct sockaddr_un);
+
+ if ((*clifd = accept(fd, (struct sockaddr *)&aul_addr,
+ (socklen_t *) &sun_size)) == -1) {
+ if (errno != EINTR)
+ _E("accept error");
+ return NULL;
+ }
+
+ if (getsockopt(*clifd, SOL_SOCKET, SO_PEERCRED, cr,
+ (socklen_t *) &cl) < 0) {
+ _E("peer information error");
+ close(*clifd);
+ return NULL;
+ }
+
+ __set_sock_option(*clifd, 1);
+
+retry_recv:
+ /* receive header(cmd, datalen) */
+ len = recv(*clifd, buf, AUL_PKT_HEADER_SIZE, 0);
+ if (len < 0)
+ if (errno == EINTR)
+ goto retry_recv;
+
+ if (len < AUL_PKT_HEADER_SIZE) {
+ _E("recv error");
+ close(*clifd);
+ return NULL;
+ }
+ memcpy(&cmd, buf, sizeof(int));
+ memcpy(&datalen, buf + sizeof(int), sizeof(int));
+
+ /* allocate for a null byte */
+ pkt = (app_pkt_t *)calloc(1, AUL_PKT_HEADER_SIZE + datalen + 1);
+ if (pkt == NULL) {
+ close(*clifd);
+ return NULL;
+ }
+ pkt->cmd = cmd;
+ pkt->len = datalen;
+
+ len = 0;
+ while ( len != pkt->len ) {
+ ret = recv(*clifd, pkt->data + len, pkt->len - len, 0);
+ if (ret < 0) {
+ _E("recv error %d %d", len, pkt->len);
+ free(pkt);
+ close(*clifd);
+ return NULL;
+ }
+ len += ret;
+ _D("recv len %d %d", len, pkt->len);
+ }
+
+ return pkt;
+}
+
+int _send_pkt_raw(int client_fd, app_pkt_t *pkt)
+{
+ int send_ret = 0;
+ int pkt_size = 0;
+
+ if (client_fd == -1 || pkt == NULL) {
+ _E("arguments error!");
+ goto error;
+ }
+
+ pkt_size = sizeof(pkt->cmd) + sizeof(pkt->len) + pkt->len;
+
+ send_ret = send(client_fd, pkt, pkt_size, 0);
+ _D("send(%d) : %d / %d", client_fd, send_ret, pkt_size);
+
+ if (send_ret == -1) {
+ _E("send error!");
+ goto error;
+ } else if (send_ret != pkt_size) {
+ _E("send byte fail!");
+ goto error;
+ }
+
+ return 0;
+
+error:
+ return -1;
+}
+
+char *_proc_get_cmdline_bypid(int pid)
+{
+ char buf[MAX_CMD_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 if (strncmp(buf, VALGRIND_NAME, VALGRIND_SIZE) == 0) {
+ char* ptr = buf;
+
+ // buf comes with double null-terminated string
+ while (1) {
+ while (*ptr) {
+ ptr++;
+ }
+ ptr++;
+
+ if (!(*ptr))
+ break;
+
+ // ignore trailing "--"
+ if (strncmp(ptr, "-", 1) != 0)
+ break;
+ }
+
+ return strdup(ptr);
+ } else if (strncmp(buf, BASH_NAME, BASH_SIZE) == 0) {
+ if (strncmp(&buf[BASH_SIZE + 1], OPROFILE_NAME, OPROFILE_SIZE) == 0) {
+ if (strncmp(&buf[BASH_SIZE + OPROFILE_SIZE + 2], OPTION_VALGRIND_NAME,
+ OPTION_VALGRIND_SIZE) == 0) {
+ return strdup(&buf[BASH_SIZE + OPROFILE_SIZE + OPTION_VALGRIND_SIZE + 3]);
+ }
+ }
+ }
+
+ return strdup(buf);
+}
+
+app_info_from_db *_get_app_info_from_bundle_by_pkgname(const char *pkgname, bundle *kb)
+{
+ app_info_from_db *menu_info;
+ const char *ptr = NULL;
+
+ menu_info = calloc(1, sizeof(app_info_from_db));
+ if (menu_info == NULL)
+ return NULL;
+
+ menu_info->pkg_name = strdup(pkgname);
+ ptr = bundle_get_val(kb, AUL_K_EXEC);
+ if (ptr)
+ menu_info->app_path = strdup(ptr);
+ if (menu_info->app_path != NULL)
+ menu_info->original_app_path = strdup(menu_info->app_path);
+ ptr = bundle_get_val(kb, AUL_K_PACKAGETYPE);
+ if (ptr)
+ menu_info->pkg_type = strdup(ptr);
+ ptr = bundle_get_val(kb, AUL_K_HWACC);
+ if (ptr)
+ menu_info->hwacc = strdup(ptr);
+ ptr = bundle_get_val(kb, AUL_K_TASKMANAGE);
+ if (ptr)
+ menu_info->taskmanage = strdup(ptr);
+ ptr = bundle_get_val(kb, AUL_K_PKGID);
+ if (ptr)
+ menu_info->pkg_id = strdup(ptr);
+
+ if (!_get_app_path(menu_info)) {
+ _free_app_info_from_db(menu_info);
+ return NULL;
+ }
+
+ return menu_info;
+}
+
+void _modify_bundle(bundle * kb, int caller_pid, app_info_from_db * menu_info, int cmd)
+{
+ bundle_del(kb, AUL_K_APPID);
+ bundle_del(kb, AUL_K_EXEC);
+ bundle_del(kb, AUL_K_PACKAGETYPE);
+ bundle_del(kb, AUL_K_HWACC);
+ bundle_del(kb, AUL_K_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 = __parse_app_path(ptr, exe, sizeof(exe));
+ if (flag > 0) {
+ char key[256];
+ char value[256];
+
+ ptr += flag;
+ SECURE_LOGD("parsing app_path: EXEC - %s\n", exe);
+
+ do {
+ flag = __parse_app_path(ptr, key, sizeof(key));
+ if (flag <= 0)
+ break;
+ ptr += flag;
+
+ flag = __parse_app_path(ptr, value, sizeof(value));
+ if (flag < 0)
+ break;
+ ptr += flag;
+
+ /*bundle_del(kb, key);*/
+ bundle_add(kb, key, value);
+ } while (flag > 0);
+ } else if (flag == 0)
+ _D("parsing app_path: No arguments\n");
+ else
+ _D("parsing app_path: Invalid argument\n");
+ }
+}
+
+int _listen_candidate_process(int type)
+{
+ struct sockaddr_un addr;
+ int fd = -1;
+ int listen_fds = 0;
+ int i;
+
+ _D("[launchpad] enter, type: %d", type);
+
+ memset(&addr, 0x00, sizeof(struct sockaddr_un));
+ addr.sun_family = AF_UNIX;
+ snprintf(addr.sun_path, UNIX_PATH_MAX, "%s/%d/%s%d", SOCKET_PATH, getuid(),
+ LAUNCHPAD_TYPE, type);
+
+ listen_fds = sd_listen_fds(0);
+ if (listen_fds < 0) {
+ _E("Invalid systemd environment");
+ return -1;
+ } else if (listen_fds > 0) {
+ for (i = 0; i < listen_fds; i++) {
+ fd = SD_LISTEN_FDS_START + i;
+ if (sd_is_socket_unix(fd, SOCK_STREAM, 1, addr.sun_path, 0))
+ return fd;
+ }
+ _E("Socket not found: %s", addr.sun_path);
+ return -1;
+ }
+
+ fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ if (fd < 0) {
+ _E("Socket error");
+ goto error;
+ }
+
+ unlink(addr.sun_path);
+
+ _D("bind to %s", addr.sun_path);
+ if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ _E("bind error");
+ goto error;
+ }
+
+ _D("chmod %s", addr.sun_path);
+ if (chmod(addr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
+ _E("chmod error");
+ goto error;
+ }
+
+ _D("listen to %s", addr.sun_path);
+ if (listen(fd, MAX_PENDING_CONNECTIONS) == -1) {
+ _E("listen error");
+ goto error;
+ }
+
+ SECURE_LOGD("[launchpad] done, listen fd: %d", fd);
+ return fd;
+
+error:
+ if (fd != -1)
+ close(fd);
+
+ return -1;
+}
+
+int _connect_to_launchpad(int type)
+{
+ struct sockaddr_un addr;
+ int fd = -1;
+ int retry = CONNECT_RETRY_COUNT;
+ int send_ret = -1;
+ int client_pid = getpid();
+
+ _D("[launchpad] enter, type: %d", type);
+
+ fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
+ if (fd < 0) {
+ _E("socket error");
+ goto error;
+ }
+
+ memset(&addr, 0x00, sizeof(struct sockaddr_un));
+ addr.sun_family = AF_UNIX;
+ snprintf(addr.sun_path, UNIX_PATH_MAX, "%s/%d/%s%d", SOCKET_PATH, getuid(),
+ LAUNCHPAD_TYPE, type);
+
+ _D("connect to %s", addr.sun_path);
+ while (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ if (errno != ETIMEDOUT || retry <= 0) {
+ _E("connect error : %d", errno);
+ goto error;
+ }
+
+ usleep(CONNECT_RETRY_TIME);
+ --retry;
+ _D("re-connect to %s (%d)", addr.sun_path, retry);
+ }
+
+ send_ret = send(fd, &client_pid, sizeof(client_pid), 0);
+ _D("send(%d) : %d", client_pid, send_ret);
+
+ if (send_ret == -1) {
+ _E("send error");
+ goto error;
+ }
+
+ SECURE_LOGD("[launchpad] done, connect fd: %d", fd);
+ return fd;
+
+error:
+ if (fd != -1)
+ close(fd);
+
+ return -1;
+}
+
+int _accept_candidate_process(int server_fd, int* out_client_fd,
+ int* out_client_pid)
+{
+ int client_fd = -1, client_pid = 0, recv_ret = 0;
+
+ if (server_fd == -1 || out_client_fd == NULL || out_client_pid == NULL) {
+ _E("arguments error!");
+ goto error;
+ }
+
+ client_fd = accept(server_fd, NULL, NULL);
+
+ if (client_fd == -1) {
+ _E("accept error!");
+ goto error;
+ }
+
+ recv_ret = recv(client_fd, &client_pid, sizeof(client_pid), MSG_WAITALL);
+
+ if (recv_ret == -1) {
+ _E("recv error!");
+ goto error;
+ }
+
+ *out_client_fd = client_fd;
+ *out_client_pid = client_pid;
+
+ return *out_client_fd;
+
+error:
+ if (client_fd != -1)
+ close(client_fd);
+
+ return -1;
+}
+
+void _refuse_candidate_process(int server_fd)
+{
+ int client_fd = -1;
+
+ if (server_fd == -1) {
+ _E("arguments error!");
+ goto error;
+ }
+
+ client_fd = accept(server_fd, NULL, NULL);
+ if (client_fd == -1) {
+ _E("accept error!");
+ goto error;
+ }
+
+ close(client_fd);
+ _D("refuse connection!");
+
+error:
+ return;
+}
+
+void _set_oom(void)
+{
+ char buf[MAX_LOCAL_BUFSZ];
+ FILE *fp;
+
+ /* we should reset oomadj value as default because child
+ inherits from parent oom_adj*/
+ snprintf(buf, MAX_LOCAL_BUFSZ, "/proc/%d/oom_adj", getpid());
+ fp = fopen(buf, "w");
+ if (fp == NULL)
+ return;
+ fprintf(fp, "%d", -16);
+ fclose(fp);
+}
+
+void _set_env(app_info_from_db * menu_info, bundle * kb)
+{
+ const char *str;
+
+ str = bundle_get_val(kb, AUL_K_STARTTIME);
+ if (str != NULL)
+ setenv("APP_START_TIME", str, 1);
+
+ if (menu_info->hwacc != NULL)
+ setenv("HWACC", menu_info->hwacc, 1);
+ if (menu_info->taskmanage != NULL)
+ setenv("TASKMANAGE", menu_info->taskmanage, 1);
+}
+
+char** _create_argc_argv(bundle * kb, int *margc)
+{
+ char **argv;
+ int argc;
+
+ argc = bundle_export_to_argv(kb, &argv);
+
+ *margc = argc;
+ return argv;
+}
+
--- /dev/null
+/*
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the License);
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an AS IS BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <dlfcn.h>
+#include <poll.h>
+#include <sys/prctl.h>
+#include <sys/socket.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <grp.h>
+#include <pwd.h>
+#include <sqlite3.h>
+#include <Elementary.h>
+#include <Ecore.h>
+#include <bundle_internal.h>
+#include <dbus/dbus-glib-lowlevel.h>
+#include <security-manager.h>
+
+#include "menu_db_util.h"
+#include "launchpad_common.h"
+#include "preload.h"
+#include "process_pool_preload.h"
+#include "preexec.h"
+#include "key.h"
+
+#define AUL_PR_NAME 16
+#define LOWEST_PRIO 20
+
+static char *__appid;
+static char *__pkgid;
+static bundle *_s_bundle;
+
+static int __set_access(const char* appId, const char* pkg_type,
+ const char* app_path)
+{
+ return security_manager_prepare_app(appId) == SECURITY_MANAGER_SUCCESS ? 0 : -1;
+}
+
+static int __candidate_process_prepare_exec(const char *pkg_name,
+ const char *app_path, app_info_from_db *menu_info,
+ bundle *kb, int type)
+{
+ const char *file_name = NULL;
+ char process_name[AUL_PR_NAME] = { 0, };
+ int ret = 0;
+
+ __preexec_run(menu_info->pkg_type, pkg_name, app_path);
+
+ /* SET PRIVILEGES*/
+ SECURE_LOGD("[candidata] 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
+ * This dumpable flag should be set after calling perm_app_set_privilege()
+ */
+ 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;
+}
+
+static void __at_exit_to_release_bundle()
+{
+ if (_s_bundle) {
+ bundle_free(_s_bundle);
+ _s_bundle = NULL;
+ }
+}
+
+static void __release_appid_at_exit(void)
+{
+ if (__appid != NULL) {
+ free(__appid);
+ }
+ if (__pkgid != NULL) {
+ free(__pkgid);
+ }
+}
+
+static void __candidate_process_launchpad_main_loop(app_pkt_t* pkt,
+ char* out_app_path, int* out_argc, char ***out_argv,
+ int type)
+{
+ bundle *kb = NULL;
+ app_info_from_db *menu_info = NULL;
+
+ const char *app_id = NULL;
+ const char *app_path = NULL;
+ //const char *pkg_id = NULL;
+
+ kb = bundle_decode(pkt->data, pkt->len);
+ if (!kb) {
+ _E("bundle decode error");
+ exit(-1);
+ }
+
+ if (_s_bundle != NULL)
+ bundle_free(_s_bundle);
+
+ _s_bundle = kb;
+ atexit(__at_exit_to_release_bundle);
+
+ app_id = bundle_get_val(kb, AUL_K_APPID);
+ if (app_id == NULL) {
+ _E("Unable to get app_id");
+ exit(-1);
+ }
+
+ menu_info = _get_app_info_from_bundle_by_pkgname(app_id, kb);
+ if (menu_info == NULL) {
+ _D("such pkg no found");
+ exit(-1);
+ }
+
+ if (type < 0) {
+ _E("Invalid launchpad type: %d", type);
+ exit(-1);
+ }
+
+ SECURE_LOGD("app id: %s, launchpad type: %d", app_id, type);
+
+ app_path = _get_app_path(menu_info);
+ if (app_path == NULL) {
+ _E("app_path is NULL");
+ exit(-1);
+ }
+
+ if (app_path[0] != '/') {
+ _E("app_path is not absolute path");
+ exit(-1);
+ }
+
+ _modify_bundle(kb, /*cr.pid - unused parameter*/ 0, menu_info, pkt->cmd);
+
+ // caching appid
+ app_id = _get_pkgname(menu_info);
+ if (app_id == NULL) {
+ _E("unable to get app_id from menu_info");
+ exit(-1);
+ }
+ SECURE_LOGD("app id: %s", app_id);
+#if 0
+ //TODO : FIXME
+ __appid = strdup(app_id);
+ if (__appid == NULL) {
+ _E("Out of memory");
+ exit(-1);
+ }
+ //aul_set_preinit_appid(__appid); //TODO
+
+ // caching pkgid
+ pkg_id = _get_pkgid(menu_info);
+ if (pkg_id == NULL) {
+ _E("unable to get pkg_id from menu_info");
+ exit(-1);
+ }
+ SECURE_LOGD("pkg id: %s", pkg_id);
+
+ __pkgid = strdup(pkg_id);
+ if (__pkgid == NULL) {
+ _E("Out of memory");
+ exit(-1);
+ }
+ //aul_set_preinit_pkgid(__pkgid); //TODO
+#endif
+
+ atexit(__release_appid_at_exit);
+
+#ifdef _APPFW_FEATURE_PRIORITY_CHANGE
+ const char *high_priority = bundle_get_val(kb, AUL_K_HIGHPRIORITY);
+ _D("high_priority: %s", high_priority);
+
+ if (strncmp(high_priority, "true", 4) == 0) {
+ int res = setpriority(PRIO_PROCESS, 0, -10);
+ if (res == -1) {
+ char err_str[MAX_LOCAL_BUFSZ] = { 0, };
+
+ SECURE_LOGE("Setting process (%d) priority to -10 failed, errno: %d (%s)",
+ getpid(), errno, strerror_r(errno, err_str, sizeof(err_str)));
+ }
+ }
+ bundle_del(kb, AUL_K_HIGHPRIORITY);
+#endif
+
+ if (__candidate_process_prepare_exec(app_id, app_path, menu_info, kb,
+ type) < 0) {
+ _E("__candidate_process_prepare_exec() failed");
+ if (access(app_path, F_OK | R_OK)) {
+ char err_str[MAX_LOCAL_BUFSZ] = { 0, };
+
+ SECURE_LOGE("access() failed for file: \"%s\", error: %d (%s)",
+ app_path, errno, strerror_r(errno, err_str, sizeof(err_str)));
+ }
+ exit(-1);
+ }
+
+ if (out_app_path != NULL && out_argc != NULL && out_argv != NULL) {
+ int i = 0;
+
+ memset(out_app_path, '\0', strlen(out_app_path));
+ sprintf(out_app_path, "%s", app_path);
+
+ *out_argv = _create_argc_argv(kb, out_argc);
+ (*out_argv)[0] = out_app_path;
+
+ for (i = 0; i < *out_argc; i++)
+ SECURE_LOGD("input argument %d : %s##", i, (*out_argv)[i]);
+ } else
+ exit(-1);
+
+ if (menu_info != NULL)
+ _free_app_info_from_db(menu_info);
+}
+
+static Eina_Bool __candidate_proces_fd_handler(void* data,
+ Ecore_Fd_Handler *handler)
+{
+ int type = data ? *((int *)data) : LAUNCHPAD_TYPE_UNSUPPORTED;
+ int fd = ecore_main_fd_handler_fd_get(handler);
+
+ if (fd == -1) {
+ _D("[candidate] ECORE_FD_GET");
+ exit(-1);
+ }
+
+ if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR)) {
+ _D("[candidate] ECORE_FD_ERROR");
+ close(fd);
+ exit(-1);
+ }
+
+ if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ)) {
+ _D("[candidate] ECORE_FD_READ");
+ app_pkt_t* pkt = (app_pkt_t*) malloc(sizeof(char) * AUL_SOCK_MAXBUFF);
+ if (!pkt) {
+ _D("[candidate] out of memory1");
+ exit(-1);
+ }
+ memset(pkt, 0, AUL_SOCK_MAXBUFF);
+
+ int recv_ret = recv(fd, pkt, AUL_SOCK_MAXBUFF, 0);
+ close(fd);
+ if (recv_ret == -1) {
+ _D("[condidate] recv error!");
+ free(pkt);
+ exit(-1);
+ }
+ _D("[candidate] recv_ret: %d, pkt->len: %d", recv_ret, pkt->len);
+
+ ecore_main_fd_handler_del(handler);
+
+ __candidate_process_launchpad_main_loop(pkt, g_argv[0], &g_argc, &g_argv, type);
+ SECURE_LOGD("[candidate] real app argv[0]: %s, real app argc: %d", g_argv[0],
+ g_argc);
+ free(pkt);
+
+ ecore_main_loop_quit();
+ _D("[candidate] ecore main loop quit");
+ }
+
+ return ECORE_CALLBACK_CANCEL;
+}
+
+static void __init_window(void)
+{
+#if 0 //TODO : FIXME
+ Evas_Object *win = elm_win_add(NULL, "package_name", ELM_WIN_BASIC);
+ if (win) {
+ aul_set_preinit_window(win);
+
+ Evas_Object *bg = elm_bg_add(win);
+ if (bg) {
+ evas_object_size_hint_weight_set(bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_win_resize_object_add(win, bg);
+ aul_set_preinit_background(bg);
+ } else {
+ _E("[candidate] elm_bg_add() failed");
+ }
+
+ Evas_Object *conform = elm_conformant_add(win);
+ if (conform) {
+ evas_object_size_hint_weight_set(conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
+ elm_win_resize_object_add(win, conform);
+ aul_set_preinit_conformant(conform);
+ } else {
+ _E("elm_conformant_add() failed");
+ }
+ } else {
+ _E("[candidate] elm_win_add() failed");
+ }
+#endif
+}
+
+static void __init_theme(void)
+{
+ char *theme = elm_theme_list_item_path_get(eina_list_data_get(
+ elm_theme_list_get(NULL)), NULL);
+ Eina_Bool is_exist = edje_file_group_exists(theme, "*");
+ if (!is_exist)
+ _D("theme path: %s", theme);
+
+ if (theme)
+ free(theme);
+}
+
+static int __before_loop(int type, int argc, char **argv)
+{
+ int elm_init_cnt = 0;
+ Ecore_Fd_Handler *fd_handler = NULL;
+ int client_fd;
+
+ __preload_init(argc, argv);
+ __preload_init_for_process_pool();
+ __preexec_init(argc, argv);
+
+#ifdef _APPFW_FEATURE_BOOST_PRIORITY
+ res = setpriority(PRIO_PROCESS, 0, LOWEST_PRIO);
+ if (res == -1) {
+ char err_str[MAX_LOCAL_BUFSZ] = { 0, };
+
+ SECURE_LOGE("Setting process (%d) priority to %d failed, errno: %d (%s)",
+ getpid(), LOWEST_PRIO, errno, strerror_r(errno, err_str, sizeof(err_str)));
+ }
+#endif
+ _D("[candidate] Another candidate process was forked.");
+
+ /* 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();
+
+ /* SET OOM*/
+ _set_oom();
+
+ client_fd = _connect_to_launchpad(type);
+ if (client_fd == -1) {
+ _D("Connecting to candidate process was failed.");
+ return -1;
+ }
+
+ elm_init_cnt = elm_init(g_argc, g_argv);
+ _D("[candidate] elm init, returned: %d", elm_init_cnt);
+
+ switch (type) {
+ case LAUNCHPAD_TYPE_SW:
+ elm_config_accel_preference_set("none");
+ __init_window();
+ break;
+
+ case LAUNCHPAD_TYPE_HW:
+ elm_config_accel_preference_set("hw");
+ __init_window();
+ break;
+
+ case LAUNCHPAD_TYPE_COMMON:
+ __init_theme();
+ break;
+ }
+
+ fd_handler = ecore_main_fd_handler_add(client_fd,
+ (Ecore_Fd_Handler_Flags)(ECORE_FD_READ | ECORE_FD_ERROR),
+ __candidate_proces_fd_handler, &type, NULL, NULL);
+ if (fd_handler == NULL) {
+ _D("fd_handler is NULL");
+ return -1;
+ }
+
+ _D("[candidate] ecore handler add");
+#ifdef _APPFW_FEATURE_BOOST_PRIORITY
+ res = setpriority(PRIO_PGRP, 0, 0);
+ if (res == -1) {
+ char err_str[MAX_LOCAL_BUFSZ] = { 0, };
+
+ SECURE_LOGE("Setting process (%d) priority to 0 failed, errno: %d (%s)",
+ getpid(), errno, strerror_r(errno, err_str, sizeof(err_str)));
+ }
+#endif
+ return 0;
+}
+
+static int __after_loop(void)
+{
+ void *handle = NULL;
+ int res;
+ int (*dl_main)(int, char **);
+
+ SECURE_LOGD("[candidate] Launch real application (%s)", g_argv[0]);
+ handle = dlopen(g_argv[0], RTLD_LAZY | RTLD_GLOBAL);
+ if (handle == NULL) {
+ _E("dlopen failed(%s). Please complile with -fPIE and link with -pie flag",
+ dlerror());
+ goto do_exec;
+ }
+
+ dlerror();
+
+ dl_main = dlsym(handle, "main");
+ if (dl_main != NULL)
+ res = dl_main(g_argc, g_argv);
+ else {
+ _E("dlsym not founded(%s). Please export 'main' function", dlerror());
+ dlclose(handle);
+ goto do_exec;
+ }
+
+ dlclose(handle);
+ return res;
+
+do_exec:
+ if (access(g_argv[0], F_OK | R_OK)) {
+ char err_str[MAX_LOCAL_BUFSZ] = { 0, };
+
+ SECURE_LOGE("access() failed for file: \"%s\", error: %d (%s)",
+ g_argv[0], errno, strerror_r(errno, err_str, sizeof(err_str)));
+ } else {
+ SECURE_LOGD("[candidate] Exec application (%s)", g_argv[0]);
+ if (execv(g_argv[0], g_argv) < 0) {
+ char err_str[MAX_LOCAL_BUFSZ] = { 0, };
+
+ SECURE_LOGE("execv() failed for file: \"%s\", error: %d (%s)",
+ g_argv[0], errno, strerror_r(errno, err_str, sizeof(err_str)));
+ }
+ }
+
+ return -1;
+}
+
+int main(int argc, char **argv)
+{
+ static int type = LAUNCHPAD_TYPE_UNSUPPORTED;
+
+ if (argc < 2) {
+ _E("too few argument.");
+ return -1;
+ }
+
+ type = argv[1][0] - '0';
+ if (type < 0 || type >= LAUNCHPAD_TYPE_MAX) {
+ _E("invalid argument. (type: %d)", type);
+ return -1;
+ }
+
+ //temp - this requires some optimization.
+ sleep(1);
+ _D("sleeping 1 sec...");
+
+ if (__before_loop(type, argc, argv) != 0)
+ return -1;
+
+ _D("[candidate] ecore main loop begin");
+ ecore_main_loop_begin();
+
+ return __after_loop();
+}