4 * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
6 * Contact: Jungmin Cho <chivalry.cho@samsung.com>, Gwangho Hwang <gwang.hwang@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
23 * simple AUL daemon - launchpad
30 #include <sys/types.h>
37 #include <sys/prctl.h>
45 #include "menu_db_util.h"
46 #include "simple_util.h"
47 #include "access_control.h"
59 #include <sys/smack.h>
60 #include "fileutils.h"
61 #include <sys/capability.h>
63 #define _static_ static inline
65 #define SQLITE_FLUSH_MAX (1048576) /* (1024*1024) */
66 #define AUL_POLL_CNT 15
67 #define AUL_PR_NAME 16
69 #define PATH_TMP "/tmp"
70 #define PATH_DATA "/data"
72 #define SDK_CODE_COVERAGE "CODE_COVERAGE"
73 #define SDK_DEBUG "DEBUG"
74 #define SDK_DYNAMIC_ANALYSIS "DYNAMIC_ANALYSIS"
75 #define SDK_UNIT_TEST "UNIT_TEST"
76 #define SDK_VALGRIND "VALGRIND"
77 #define SDK_LD_FLAG "LD_FLAG"
79 /* DLP is short for debug-launchpad */
80 #define DLP_K_DEBUG_ARG "__DLP_DEBUG_ARG__"
81 #define DLP_K_UNIT_TEST_ARG "__DLP_UNIT_TEST_ARG__"
82 #define DLP_K_VALGRIND_ARG "__DLP_VALGRIND_ARG__"
83 #define DLP_K_LD_FLAG "__DLP_LD_FLAG__"
85 #define PATH_GDBSERVER "/home/developer/sdk_tools/gdbserver/gdbserver"
86 #define PATH_VALGRIND "/home/developer/sdk_tools/valgrind/usr/bin/valgrind"
87 #define PATH_DA_SO "/usr/lib/da_probe_tizen.so"
88 #define PATH_NATIVE_APP "/opt/apps/"
91 #define PATH_MEMCHECK "/opt/home/developer/sdk_tools/valgrind/usr/lib/valgrind/memcheck-arm-linux"
93 #define PATH_MEMCHECK "/opt/home/developer/sdk_tools/valgrind/usr/lib/valgrind/memcheck-x86-linux"
96 #define POLL_VALGRIND_LOGFILE 0x00000001
97 #define POLL_VALGRIND_XMLFILE 0x00000002
99 #define CAPABILITY_SET_ORIGINAL 0
100 #define CAPABILITY_SET_INHERITABLE 1
102 static int need_to_set_inh_cap_after_fork = 0;
103 static char *launchpad_cmdline;
104 static int initialized = 0;
106 static int poll_outputfile = 0;
107 static int is_gdbserver_launched;
110 void __set_env(app_info_from_db * menu_info, bundle * kb);
111 int __prepare_exec(const char *pkg_name,
112 const char *app_path, app_info_from_db * menu_info,
114 int __fake_launch_app(int cmd, int pid, bundle * kb);
115 char **__create_argc_argv(bundle * kb, int *margc, const char *app_path);
116 int __normal_fork_exec(int argc, char **argv);
117 void __real_launch(const char *app_path, bundle * kb);
118 static inline int __parser(const char *arg, char *out, int out_size);
119 void __modify_bundle(bundle * kb, int caller_pid,
120 app_info_from_db * menu_info, int cmd);
121 int __send_to_sigkill(int pid);
122 int __term_app(int pid);
123 void __real_send(int clifd, int ret);
124 void __send_result_to_caller(int clifd, int ret);
125 void __launchpad_main_loop(int main_fd);
126 int __launchpad_pre_init(int argc, char **argv);
127 int __launchpad_post_init();
129 extern ail_error_e ail_db_close(void);
135 char buf[MAX_LOCAL_BUFSZ];
138 /* we should reset oomadj value as default because child
139 inherits from parent oom_adj*/
140 snprintf(buf, MAX_LOCAL_BUFSZ, "/proc/%d/oom_adj", getpid());
141 fp = fopen(buf, "w");
144 fprintf(fp, "%d", -16);
148 void __set_sdk_env(app_info_from_db* menu_info, char* str, bundle * kb) {
149 char buf_pkgname[MAX_LOCAL_BUFSZ];
150 char buf[MAX_LOCAL_BUFSZ];
153 _D("key : %s / value : %s", AUL_K_SDK, str);
154 /* http://gcc.gnu.org/onlinedocs/gcc/Cross_002dprofiling.html*/
155 /* GCOV_PREFIX contains the prefix to add to the absolute paths */
156 /* in the object file. Prefix can be absolute, or relative.*/
157 /* The default is no prefix. */
158 /* GCOV_PREFIX_STRIP indicates the how many initial directory names */
159 /* to stripoff the hardwired absolute paths. Default value is 0. */
160 if (strncmp(str, SDK_CODE_COVERAGE, strlen(str)) == 0) {
161 strncpy(buf_pkgname,_get_pkgname(menu_info),MAX_LOCAL_BUFSZ-1);
162 buf_pkgname[MAX_LOCAL_BUFSZ-1]='\0';
163 snprintf(buf, MAX_LOCAL_BUFSZ, PATH_TMP"/%s"PATH_DATA
164 , strtok(buf_pkgname,"."));
165 ret = setenv("GCOV_PREFIX", buf, 1);
166 _D("GCOV_PREFIX : %d", ret);
167 ret = setenv("GCOV_PREFIX_STRIP", "0", 1);
168 _D("GCOV_PREFIX_STRIP : %d", ret);
170 else if (strncmp(str, SDK_DYNAMIC_ANALYSIS, strlen(str)) == 0)
172 ret = setenv("LD_PRELOAD", PATH_DA_SO, 1);
173 _D("LD_PRELOAD : %d", ret);
175 else if (strncmp(str, SDK_LD_FLAG, strlen(str)) == 0)
177 const char *flag_str = NULL;
178 const char **flag_str_array = NULL;
180 if(bundle_get_type(kb, DLP_K_LD_FLAG) & BUNDLE_TYPE_ARRAY) {
181 flag_str_array = bundle_get_str_array(kb, DLP_K_LD_FLAG, &flag_len);
183 flag_str = bundle_get_val(kb, DLP_K_LD_FLAG);
185 flag_str_array = &flag_str;
189 if(flag_str_array != NULL) {
193 for (i = 0; i < flag_len; i++) {
194 strncpy(buf,flag_str_array[i],MAX_LOCAL_BUFSZ);
195 f_name = strtok(buf,"=");
196 f_value = strtok(NULL,"=");
198 ret = setenv(f_name,f_value,1);
199 _D("LD_FLAG : %s %s %d",f_name,f_value,ret);
201 _E("LD_FLAG : Wrong option! %s", flag_str_array[i]);
210 void __set_env(app_info_from_db * menu_info, bundle * kb)
213 const char **str_array;
217 setenv("PKG_NAME", _get_pkgname(menu_info), 1);
221 str = bundle_get_val(kb, AUL_K_STARTTIME);
223 setenv("APP_START_TIME", str, 1);
225 if(bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
226 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
227 if(str_array != NULL) {
228 for (i = 0; i < len; i++) {
229 _D("index : [%d]", i);
230 __set_sdk_env(menu_info, (char *)str_array[i], kb);
234 str = bundle_get_val(kb, AUL_K_SDK);
236 __set_sdk_env(menu_info, (char *)str, kb);
239 if (menu_info->hwacc != NULL)
240 setenv("HWACC", menu_info->hwacc, 1);
243 int __prepare_exec(const char *pkg_name,
244 const char *app_path, app_info_from_db * menu_info,
248 char process_name[AUL_PR_NAME];
251 /* Set new session ID & new process group ID*/
252 /* In linux, child can set new session ID without check permission */
253 /* TODO : should be add to check permission in the kernel*/
256 __preexec_run(menu_info->pkg_type, pkg_name, app_path);
262 if(bundle_get_val(kb, AUL_K_PRIVACY_APPID) == NULL) {
263 _D("pkg_name : %s / pkg_type : %s / app_path : %s ", pkg_name
264 , menu_info->pkg_type, app_path);
265 if ((ret = __set_access(pkg_name, menu_info->pkg_type
268 _D("fail to set privileges - check your package's credential : %d\n"
273 /* SET DUMPABLE - for coredump*/
274 prctl(PR_SET_DUMPABLE, 1);
276 /* SET PROCESS NAME*/
277 if (app_path == NULL) {
278 _D("app_path should not be NULL - check menu db");
281 file_name = strrchr(app_path, '/') + 1;
282 if (file_name == NULL) {
283 _D("can't locate file name to execute");
286 memset(process_name, '\0', AUL_PR_NAME);
287 snprintf(process_name, AUL_PR_NAME, "%s", file_name);
288 prctl(PR_SET_NAME, process_name);
291 __set_env(menu_info, kb);
296 int __fake_launch_app(int cmd, int pid, bundle * kb)
302 bundle_encode(kb, &kb_data, &datalen);
303 if ((ret = __app_send_raw(pid, cmd, kb_data, datalen)) < 0)
304 _E("error request fake launch - error code = %d", ret);
309 char** __add_arg(bundle * kb, char **argv, int *margc, const char *key)
311 const char *str = NULL;
312 const char **str_array = NULL;
315 char ** new_argv = NULL;
317 if(bundle_get_type(kb, key) & BUNDLE_TYPE_ARRAY) {
318 str_array = bundle_get_str_array(kb, key, &len);
320 str = bundle_get_val(kb, key);
326 if(str_array != NULL) {
327 if(strncmp(key, DLP_K_DEBUG_ARG, strlen(key)) == 0
328 || strncmp(key, DLP_K_VALGRIND_ARG, strlen(key)) == 0)
330 new_argv = (char **) realloc(argv
331 , sizeof(char *) * (*margc+len+2));
333 _E("realloc fail (key = %s)", key);
336 for(i=*margc+len+1; i-(len+1)>=0; i--) {
337 new_argv[i] = new_argv[i-(len+1)];
339 // need to add new_argv[0]
340 for(i=0; i<len; i++) {
341 new_argv[1+i] = strdup(str_array[i]);
343 len++; /* gdbserver or valgrind */
344 _D("uid : %d", getuid());
345 _D("euid : %d", geteuid());
346 _D("gid : %d", getgid());
347 _D("egid : %d", getegid());
349 new_argv = (char **) realloc(argv
350 , sizeof(char *) * (*margc+len+1));
352 _E("realloc fail (key = %s)", key);
355 for(i=0; i<len; i++) {
356 new_argv[*margc+i] = strdup(str_array[i]);
359 new_argv[*margc+len] = NULL;
362 if(strncmp(key, DLP_K_DEBUG_ARG, strlen(key)) == 0
363 || strncmp(key, DLP_K_VALGRIND_ARG, strlen(key)) == 0)
365 new_argv = (char **) realloc(argv
366 , sizeof(char *) * (*margc+2));
368 _E("realloc fail (key = %s)", key);
371 for(i=*margc+1; i-1>=0; i--) {
372 new_argv[i] = new_argv[i-1];
374 // need to add new_argv[0]
379 if(new_argv==NULL) return argv;
383 char **__create_argc_argv(bundle * kb, int *margc, const char *app_path)
386 char **new_argv = NULL;
389 const char *str = NULL;
390 const char **str_array = NULL;
394 argc = bundle_export_to_argv(kb, &argv);
396 for(i=1; i<argc; i++) {
397 argv[i] = strdup(argv[i]);
399 argv[0] = strdup(app_path);
401 _E("bundle_export_to_argv error");
405 if(bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
406 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
408 str = bundle_get_val(kb, AUL_K_SDK);
414 if(str_array == NULL) {
419 for (i = 0; i < len; i++) {
420 if(str_array[i] == NULL) break;
421 _D("index : [%d]", i);
423 if (strncmp(str_array[i], SDK_DEBUG, strlen(str_array[i])) == 0)
425 char buf[MAX_LOCAL_BUFSZ];
426 if (argv[0]) free(argv[0]);
427 snprintf(buf,MAX_LOCAL_BUFSZ,"%s.exe",app_path);
428 argv[0] = strdup(buf);
429 new_argv = __add_arg(kb, argv, &argc, DLP_K_DEBUG_ARG);
430 new_argv[0] = strdup(PATH_GDBSERVER);
434 else if (strncmp(str_array[i], SDK_VALGRIND
435 , strlen(str_array[i])) == 0)
437 new_argv = __add_arg(kb, argv, &argc
438 , DLP_K_VALGRIND_ARG);
439 new_argv[0] = strdup(PATH_VALGRIND);
443 else if (strncmp(str_array[i], SDK_UNIT_TEST
444 , strlen(str_array[i])) == 0)
446 new_argv = __add_arg(kb, argv, &argc
447 , DLP_K_UNIT_TEST_ARG);
453 if(new_argv==NULL) return argv;
457 int __normal_fork_exec(int argc, char **argv)
459 _D("start real fork and exec\n");
461 if (execv(argv[0], argv) < 0) { /* Flawfinder: ignore */
462 if (errno == EACCES) {
463 _E("such a file is no executable - %s", argv[0]);
465 _E("unknown executable error - %s", argv[0]);
473 void __real_launch(const char *app_path, bundle * kb)
479 app_argv = __create_argc_argv(kb, &app_argc, app_path);
481 for (i = 0; i < app_argc; i++)
482 _D("input argument %d : %s##", i, app_argv[i]);
484 PERF("setup argument done");
485 _D("lock up test log(no error) : setup argument done");
487 /* Temporary log: launch time checking */
488 LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:launchpad:done]", app_path);
490 __normal_fork_exec(app_argc, app_argv);
492 for(i=0; i<app_argc; i++) {
493 if(app_argv[i]) free(app_argv[i]);
500 * Parsing original app path to retrieve default bundle
502 * -1 : Invalid sequence
503 * -2 : Buffer overflow
506 static inline int __parser(const char *arg, char *out, int out_size)
510 char *start_out = out;
512 if (arg == NULL || out == NULL) {
513 /* Handles null buffer*/
517 for (i = 0; out_size > 1; i++) {
541 case 2: /* escape start*/
556 case 4: /* character escape*/
557 if (arg[i] == '\0') {
567 if (out != start_out) {
576 return -1; /* error*/
577 case 7: /* terminate*/
594 void __modify_bundle(bundle * kb, int caller_pid,
595 app_info_from_db * menu_info, int cmd)
597 bundle_del(kb, AUL_K_PKG_NAME);
598 bundle_del(kb, AUL_K_EXEC);
599 bundle_del(kb, AUL_K_PACKAGETYPE);
600 bundle_del(kb, AUL_K_HWACC);
602 /* Parse app_path to retrieve default bundle*/
603 if (cmd == APP_START || cmd == APP_START_RES || cmd == APP_OPEN
604 || cmd == APP_RESUME)
607 char exe[MAX_PATH_LEN];
610 ptr = _get_original_app_path(menu_info);
612 flag = __parser(ptr, exe, sizeof(exe));
618 _D("parsing app_path: EXEC - %s\n", exe);
621 flag = __parser(ptr, key, sizeof(key));
626 flag = __parser(ptr, value, sizeof(value));
631 /*bundle_del(kb, key);*/
632 bundle_add(kb, key, value);
634 } else if (flag == 0) {
635 _D("parsing app_path: No arguments\n");
637 _D("parsing app_path: Invalid argument\n");
642 int __send_to_sigkill(int pid)
650 if (killpg(pgid, SIGKILL) < 0)
656 int __term_app(int pid)
660 (pid, APP_TERM_BY_PID, (unsigned char *)&dummy, sizeof(int)) < 0) {
661 _D("terminate packet send error - use SIGKILL");
662 if (__send_to_sigkill(pid) < 0) {
663 _E("fail to killing - %d\n", pid);
671 static int __get_caller_pid(bundle *kb)
676 pid_str = bundle_get_val(kb, AUL_K_ORG_CALLER_PID);
680 pid_str = bundle_get_val(kb, AUL_K_CALLER_PID);
692 int __foward_cmd(int cmd, bundle *kb, int cr_pid)
695 char tmp_pid[MAX_PID_STR_BUFSZ];
700 if ((pid = __get_caller_pid(kb)) < 0)
703 snprintf(tmp_pid, MAX_PID_STR_BUFSZ, "%d", cr_pid);
705 bundle_add(kb, AUL_K_CALLEE_PID, tmp_pid);
707 bundle_encode(kb, &kb_data, &datalen);
708 if ((res = __app_send_raw_with_noreply(pid, cmd, kb_data, datalen)) < 0)
716 void __real_send(int clifd, int ret)
718 if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) {
719 if (errno == EPIPE) {
720 _E("send failed due to EPIPE.\n");
722 _E("send fail to client");
728 void __send_result_to_caller(int clifd, int ret)
732 int cmdline_changed = 0;
733 int cmdline_exist = 0;
739 __real_send(clifd, ret);
742 /* check normally was launched?*/
745 cmdline = __proc_get_cmdline_bypid(ret);
746 if (cmdline == NULL) {
747 _E("error founded when being launched with %d", ret);
749 } else if (strcmp(cmdline, launchpad_cmdline)) {
758 _D("-- now wait to change cmdline --");
759 usleep(50 * 1000); /* 50ms sleep*/
761 } while (wait_count <= 20); /* max 50*20ms will be sleep*/
763 if ((!cmdline_exist) && (!cmdline_changed)) {
764 _E("abnormally launched");
765 __real_send(clifd, -1); /* abnormally launched*/
769 if (!cmdline_changed)
770 _E("process launched, but cmdline not changed");
772 __real_send(clifd, ret);
776 static app_info_from_db *_get_app_info_from_bundle_by_pkgname(
777 const char *pkgname, bundle *kb)
779 app_info_from_db *menu_info;
781 menu_info = calloc(1, sizeof(app_info_from_db));
782 if (menu_info == NULL) {
786 menu_info->pkg_name = strdup(pkgname);
787 menu_info->app_path = strdup(bundle_get_val(kb, AUL_K_EXEC));
788 if (menu_info->app_path != NULL)
789 menu_info->original_app_path = strdup(menu_info->app_path);
790 menu_info->pkg_type = strdup(bundle_get_val(kb, AUL_K_PACKAGETYPE));
791 menu_info->hwacc = strdup(bundle_get_val(kb, AUL_K_HWACC));
793 if (!_get_app_path(menu_info)) {
794 _free_app_info_from_db(menu_info);
804 int get_native_appid(const char* app_path, char** appid) {
805 int rc = smack_lgetlabel(app_path, appid, SMACK_LABEL_ACCESS);
807 if (rc != 0 || *appid == NULL) {
808 _E("smack_lgetlabel fail");
812 if (strlen(*appid) != APPID_LEN) {
813 _E("wrong native appid : %s", *appid);
817 if (strlen(app_path) < sizeof(PATH_NATIVE_APP)+APPID_LEN-1) {
818 _E("wrong native app_path : %s", app_path);
821 else if ( strncmp(app_path, PATH_NATIVE_APP, sizeof(PATH_NATIVE_APP)-1)
822 || strncmp(&app_path[sizeof(PATH_NATIVE_APP)-1]
823 , *appid,APPID_LEN) )
825 _E("wrong native app_path : %s", app_path);
829 _D("get_appid return : %s", *appid);
833 int apply_smack_rules(const char* subject, const char* object
834 , const char* access_type)
836 struct smack_accesses *rules = NULL;
838 _D("apply_smack_rules : %s %s %s", subject, object, access_type);
840 if (smack_accesses_new(&rules)) {
841 _E("smack_accesses_new fail");
845 if (smack_accesses_add(rules, subject, object, access_type)) {
846 smack_accesses_free(rules);
847 _E("smack_accesses_add fail");
851 if (smack_accesses_apply(rules)) {
852 smack_accesses_free(rules);
853 _E("smack_accesses_apply fail");
857 smack_accesses_free(rules);
862 int __prepare_valgrind_outputfile(bundle *kb)
864 const char *str = NULL;
865 const char **str_array = NULL;
869 if(bundle_get_type(kb, DLP_K_VALGRIND_ARG) & BUNDLE_TYPE_ARRAY) {
870 str_array = bundle_get_str_array(kb, DLP_K_VALGRIND_ARG, &len);
872 str = bundle_get_val(kb, DLP_K_VALGRIND_ARG);
878 if(str_array == NULL) return 0;
880 for (i = 0; i < len; i++) {
881 if(str_array[i] == NULL) break;
882 /* valgrind log file option */
883 if (strncmp(str_array[i], OPT_VALGRIND_LOGFILE
884 , sizeof(OPT_VALGRIND_LOGFILE)-1) == 0)
886 if(strcmp(str_array[i], OPT_VALGRIND_LOGFILE_FIXED))
888 _E("wrong valgrind option(%s). It should be %s"
890 , OPT_VALGRIND_LOGFILE_FIXED);
893 poll_outputfile |= POLL_VALGRIND_LOGFILE;
894 if(remove(PATH_VALGRIND_LOGFILE)){
895 _D("cannot remove %s"
896 , PATH_VALGRIND_LOGFILE);
900 /* valgrind xml file option */
901 else if (strncmp(str_array[i], OPT_VALGRIND_XMLFILE
902 , sizeof(OPT_VALGRIND_XMLFILE)-1) == 0)
904 if(strcmp(str_array[i], OPT_VALGRIND_XMLFILE_FIXED))
906 _E("wrong valgrind option(%s). It should be %s"
908 , OPT_VALGRIND_XMLFILE_FIXED);
911 poll_outputfile |= POLL_VALGRIND_XMLFILE;
912 if(remove(PATH_VALGRIND_XMLFILE)){
913 _D("cannot remove %s"
914 , PATH_VALGRIND_XMLFILE);
918 /* valgrind massif file option */
919 else if (strncmp(str_array[i], OPT_VALGRIND_MASSIFFILE
920 , sizeof(OPT_VALGRIND_MASSIFFILE)-1) == 0)
922 if(strcmp(str_array[i], OPT_VALGRIND_MASSIFFILE_FIXED))
924 _E("wrong valgrind option(%s). It should be %s"
926 , OPT_VALGRIND_MASSIFFILE_FIXED);
929 if(remove(PATH_VALGRIND_XMLFILE)){
930 _D("cannot remove %s"
931 , PATH_VALGRIND_XMLFILE);
939 extern int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
941 int __adjust_process_capability(int sv)
943 static struct __user_cap_header_struct h;
944 static struct __user_cap_data_struct ori_d[_LINUX_CAPABILITY_U32S_2];
945 static struct __user_cap_data_struct inh_d[_LINUX_CAPABILITY_U32S_2];
946 static int isinit = 0;
949 h.version = _LINUX_CAPABILITY_VERSION_2;
955 inh_d[CAP_TO_INDEX(CAP_NET_RAW)].inheritable |=
956 CAP_TO_MASK(CAP_NET_RAW);
957 inh_d[CAP_TO_INDEX(CAP_SYS_CHROOT)].inheritable |=
958 CAP_TO_MASK(CAP_SYS_CHROOT);
962 if(sv == CAPABILITY_SET_ORIGINAL) return 0;
966 _E("__adjust_process_capability init failed");
970 if(sv == CAPABILITY_SET_ORIGINAL) {
972 if (capset(&h, ori_d) < 0) {
973 _E("Capability setting error");
977 else if (sv == CAPABILITY_SET_INHERITABLE) {
979 if (capset(&h, inh_d) < 0) {
980 _E("Capability setting error");
988 int __adjust_file_capability(const char * path)
990 if(cap_set_file(path,cap_from_text("CAP_NET_RAW,CAP_SYS_CHROOT+i"))) {
991 _E("cap_set_file failed : %s", path);
997 int __prepare_fork(bundle *kb, char *appid)
999 const char *str = NULL;
1000 const char **str_array = NULL;
1004 need_to_set_inh_cap_after_fork=0;
1005 poll_outputfile = 0;
1006 if(bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
1007 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
1009 str = bundle_get_val(kb, AUL_K_SDK);
1015 if(str_array == NULL) return 0;
1017 is_gdbserver_launched = 0;
1019 gdbserver_app_pid = -1;
1021 for (i = 0; i < len; i++) {
1022 if(str_array[i] == NULL) break;
1024 if (strncmp(str_array[i], SDK_DEBUG, strlen(str_array[i])) == 0)
1026 if(apply_smack_rules("sdbd",appid,"w")) {
1027 _E("unable to set sdbd rules");
1031 // FIXME: set gdbfolder to 755 also
1032 if(dlp_chmod(PATH_GDBSERVER
1033 , S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP
1037 _D("unable to set 755 to %s", PATH_GDBSERVER);
1039 __adjust_file_capability(PATH_GDBSERVER);
1040 need_to_set_inh_cap_after_fork++;
1041 is_gdbserver_launched++;
1044 else if (strncmp(str_array[i], SDK_VALGRIND
1045 , strlen(str_array[i])) == 0)
1047 if (__prepare_valgrind_outputfile(kb) == -1)
1049 __adjust_file_capability(PATH_MEMCHECK);
1056 /* waiting for creating outputfile by child process */
1057 void __waiting_outputfile()
1060 while(poll_outputfile && wait_count<10) {
1061 /* valgrind log file */
1062 if( (poll_outputfile & POLL_VALGRIND_LOGFILE)
1063 && (access(PATH_VALGRIND_LOGFILE,F_OK)==0) )
1065 __chmod_chsmack_toread(PATH_VALGRIND_LOGFILE);
1066 poll_outputfile &= ~POLL_VALGRIND_LOGFILE;
1069 /* valgrind xml file */
1070 if( (poll_outputfile & POLL_VALGRIND_XMLFILE)
1071 && (access(PATH_VALGRIND_XMLFILE,F_OK)==0) )
1073 __chmod_chsmack_toread(PATH_VALGRIND_XMLFILE);
1074 poll_outputfile &= ~POLL_VALGRIND_XMLFILE;
1077 if(poll_outputfile) {
1078 _D("-- now wait for creating the file --");
1079 usleep(50 * 1000); /* 50ms sleep*/
1084 if(wait_count==10) _E("faild to waiting");
1088 int __stdout_stderr_redirection(int defpid)
1090 char defpath[UNIX_PATH_MAX];
1091 int deffd, result=0;
1094 snprintf(defpath, UNIX_PATH_MAX, "/proc/%d/fd/1", defpid);
1095 deffd = open(defpath,O_WRONLY);
1097 _E("opening caller(%d) stdout failed due to %s"
1098 , defpid, strerror(errno));
1106 snprintf(defpath, UNIX_PATH_MAX, "/proc/%d/fd/2", defpid);
1107 deffd = open(defpath,O_WRONLY);
1109 _E("opening caller(%d) stderr failed due to %s"
1110 , defpid,strerror(errno));
1120 void __launchpad_main_loop(int main_fd)
1123 app_pkt_t *pkt = NULL;
1124 app_info_from_db *menu_info = NULL;
1126 const char *pkg_name = NULL;
1127 const char *app_path = NULL;
1131 int is_real_launch = 0;
1133 char sock_path[UNIX_PATH_MAX] = {0,};
1134 char * appid = NULL;
1136 pkt = __app_recv_raw(main_fd, &clifd, &cr);
1138 _D("packet is NULL");
1142 kb = bundle_decode(pkt->data, pkt->len);
1144 _D("bundle decode error");
1149 PERF("packet processing start");
1151 pkg_name = bundle_get_val(kb, AUL_K_PKG_NAME);
1152 _D("pkg name : %s\n", pkg_name);
1154 menu_info = _get_app_info_from_bundle_by_pkgname(pkg_name, kb);
1155 if (menu_info == NULL) {
1156 _D("such pkg no found");
1160 app_path = _get_app_path(menu_info);
1161 if(app_path == NULL) {
1162 _E("app_path is NULL");
1165 if (app_path[0] != '/') {
1166 _D("app_path is not absolute path");
1171 int rc = get_native_appid(app_path,&appid);
1172 if(rc!=0 || appid==NULL) {
1173 _E("unable to get native appid");
1182 __modify_bundle(kb, cr.pid, menu_info, pkt->cmd);
1183 pkg_name = _get_pkgname(menu_info);
1185 PERF("get package information & modify bundle done");
1187 if(__prepare_fork(kb,appid) == -1) goto end;
1191 if(need_to_set_inh_cap_after_fork) {
1192 __adjust_process_capability(CAPABILITY_SET_INHERITABLE);
1195 _D("lock up test log(no error) : fork done");
1199 __signal_unset_sigchld();
1202 snprintf(sock_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX
1206 if(__stdout_stderr_redirection(__get_caller_pid(kb))) {
1207 _E("__stdout_stderr_redirection fail");
1210 PERF("prepare exec - first done");
1211 _D("lock up test log(no error) : prepare exec - first done");
1213 if (__prepare_exec(pkg_name, app_path,
1214 menu_info, kb) < 0) {
1215 _E("preparing work fail to launch - "
1216 "can not launch %s\n", pkg_name);
1220 PERF("prepare exec - second done");
1221 _D("lock up test log(no error) : prepare exec - second done");
1223 __real_launch(app_path, kb);
1228 if(is_gdbserver_launched) {
1229 char buf[MAX_LOCAL_BUFSZ];
1231 usleep(100 * 1000); /* 100ms sleep */
1232 snprintf(buf, MAX_LOCAL_BUFSZ, "%s.exe", app_path);
1233 gdbserver_app_pid = __proc_iter_cmdline(NULL, buf);
1235 if(gdbserver_app_pid == -1) {
1236 _E("faild to get app pid");
1238 gdbserver_pid = pid;
1239 pid = gdbserver_app_pid;
1243 _D("==> real launch pid : %d %s\n", pid, app_path);
1247 __send_result_to_caller(clifd, pid);
1250 if (is_real_launch) {
1252 __signal_block_sigchld();
1253 __send_app_launch_signal(pid);
1254 __signal_unblock_sigchld();
1258 if (menu_info != NULL)
1259 _free_app_info_from_db(menu_info);
1268 /* Active Flusing for Daemon */
1269 if (initialized > AUL_POLL_CNT) {
1270 sqlite3_release_memory(SQLITE_FLUSH_MAX);
1275 if(poll_outputfile) __waiting_outputfile();
1278 int __launchpad_pre_init(int argc, char **argv)
1285 /* get my(launchpad) command line*/
1286 launchpad_cmdline = __proc_get_cmdline_bypid(getpid());
1287 if (launchpad_cmdline == NULL) {
1288 _E("launchpad cmdline fail to get");
1291 _D("launchpad cmdline = %s", launchpad_cmdline);
1293 /* create launchpad sock */
1294 fd = __create_server_sock(DEBUG_LAUNCHPAD_PID);
1296 _E("server sock error");
1300 __preload_init(argc, argv);
1302 __preexec_init(argc, argv);
1307 int __launchpad_post_init()
1309 /* Setting this as a global variable to keep track
1310 of launchpad poll cnt */
1311 /* static int initialized = 0;*/
1318 if (__signal_set_sigchld() < 0)
1326 int main(int argc, char **argv)
1329 struct pollfd pfds[POLLFD_MAX];
1332 __adjust_process_capability(CAPABILITY_SET_ORIGINAL);
1334 /* init without concerning X & EFL*/
1335 main_fd = __launchpad_pre_init(argc, argv);
1337 _E("launchpad pre init failed");
1341 pfds[0].fd = main_fd;
1342 pfds[0].events = POLLIN;
1343 pfds[0].revents = 0;
1346 if (poll(pfds, POLLFD_MAX, -1) < 0)
1349 /* init with concerning X & EFL (because of booting
1351 if (__launchpad_post_init() < 0) {
1352 _E("launcpad post init failed");
1356 for (i = 0; i < POLLFD_MAX; i++) {
1357 if ((pfds[i].revents & POLLIN) != 0) {
1358 __launchpad_main_loop(pfds[i].fd);