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/"
90 #define OPT_VALGRIND_LOGFILE "--log-file="
91 #define OPT_VALGRIND_LOGFILE_FIXED "--log-file=/tmp/valgrind_result.txt"
92 #define PATH_VALGRIND_LOGFILE "/tmp/valgrind_result.txt"
93 #define OPT_VALGRIND_XMLFILE "--xml-file="
94 #define OPT_VALGRIND_XMLFILE_FIXED "--xml-file=/tmp/valgrind_result.xml"
95 #define PATH_VALGRIND_XMLFILE "/tmp/valgrind_result.xml"
96 #define OPT_VALGRIND_MASSIFFILE "--massif-out-file="
97 #define OPT_VALGRIND_MASSIFFILE_FIXED "--massif-out-file=/tmp/valgrind_result.xml"
100 #define PATH_MEMCHECK "/opt/home/developer/sdk_tools/valgrind/usr/lib/valgrind/memcheck-arm-linux"
102 #define PATH_MEMCHECK "/opt/home/developer/sdk_tools/valgrind/usr/lib/valgrind/memcheck-x86-linux"
105 #define POLL_VALGRIND_LOGFILE 0x00000001
106 #define POLL_VALGRIND_XMLFILE 0x00000002
108 #define CAPABILITY_SET_ORIGINAL 0
109 #define CAPABILITY_SET_INHERITABLE 1
111 static int need_to_set_inh_cap_after_fork = 0;
112 static char *launchpad_cmdline;
113 static int initialized = 0;
115 static int poll_outputfile = 0;
116 static int is_gdbserver_launched;
119 void __set_env(app_info_from_db * menu_info, bundle * kb);
120 int __prepare_exec(const char *pkg_name,
121 const char *app_path, app_info_from_db * menu_info,
123 int __fake_launch_app(int cmd, int pid, bundle * kb);
124 char **__create_argc_argv(bundle * kb, int *margc, const char *app_path);
125 int __normal_fork_exec(int argc, char **argv);
126 void __real_launch(const char *app_path, bundle * kb);
127 static inline int __parser(const char *arg, char *out, int out_size);
128 void __modify_bundle(bundle * kb, int caller_pid,
129 app_info_from_db * menu_info, int cmd);
130 int __send_to_sigkill(int pid);
131 int __term_app(int pid);
132 void __real_send(int clifd, int ret);
133 void __send_result_to_caller(int clifd, int ret);
134 void __launchpad_main_loop(int main_fd);
135 int __launchpad_pre_init(int argc, char **argv);
136 int __launchpad_post_init();
138 extern ail_error_e ail_db_close(void);
144 char buf[MAX_LOCAL_BUFSZ];
147 /* we should reset oomadj value as default because child
148 inherits from parent oom_adj*/
149 snprintf(buf, MAX_LOCAL_BUFSZ, "/proc/%d/oom_adj", getpid());
150 fp = fopen(buf, "w");
153 fprintf(fp, "%d", -16);
157 void __set_sdk_env(app_info_from_db* menu_info, char* str, bundle * kb) {
158 char buf_pkgname[MAX_LOCAL_BUFSZ];
159 char buf[MAX_LOCAL_BUFSZ];
162 _D("key : %s / value : %s", AUL_K_SDK, str);
163 /* http://gcc.gnu.org/onlinedocs/gcc/Cross_002dprofiling.html*/
164 /* GCOV_PREFIX contains the prefix to add to the absolute paths */
165 /* in the object file. Prefix can be absolute, or relative.*/
166 /* The default is no prefix. */
167 /* GCOV_PREFIX_STRIP indicates the how many initial directory names */
168 /* to stripoff the hardwired absolute paths. Default value is 0. */
169 if (strncmp(str, SDK_CODE_COVERAGE, strlen(str)) == 0) {
170 strncpy(buf_pkgname,_get_pkgname(menu_info),MAX_LOCAL_BUFSZ-1);
171 buf_pkgname[MAX_LOCAL_BUFSZ-1]='\0';
172 snprintf(buf, MAX_LOCAL_BUFSZ, PATH_TMP"/%s"PATH_DATA
173 , strtok(buf_pkgname,"."));
174 ret = setenv("GCOV_PREFIX", buf, 1);
175 _D("GCOV_PREFIX : %d", ret);
176 ret = setenv("GCOV_PREFIX_STRIP", "0", 1);
177 _D("GCOV_PREFIX_STRIP : %d", ret);
179 else if (strncmp(str, SDK_DYNAMIC_ANALYSIS, strlen(str)) == 0)
181 ret = setenv("LD_PRELOAD", PATH_DA_SO, 1);
182 _D("LD_PRELOAD : %d", ret);
184 else if (strncmp(str, SDK_LD_FLAG, strlen(str)) == 0)
186 const char *flag_str = NULL;
187 const char **flag_str_array = NULL;
189 if(bundle_get_type(kb, DLP_K_LD_FLAG) & BUNDLE_TYPE_ARRAY) {
190 flag_str_array = bundle_get_str_array(kb, DLP_K_LD_FLAG, &flag_len);
192 flag_str = bundle_get_val(kb, DLP_K_LD_FLAG);
194 flag_str_array = &flag_str;
198 if(flag_str_array != NULL) {
202 for (i = 0; i < flag_len; i++) {
203 strncpy(buf,flag_str_array[i],MAX_LOCAL_BUFSZ);
204 f_name = strtok(buf,"=");
205 f_value = strtok(NULL,"=");
207 ret = setenv(f_name,f_value,1);
208 _D("LD_FLAG : %s %s %d",f_name,f_value,ret);
210 _E("LD_FLAG : Wrong option! %s", flag_str_array[i]);
219 void __set_env(app_info_from_db * menu_info, bundle * kb)
222 const char **str_array;
226 setenv("PKG_NAME", _get_pkgname(menu_info), 1);
230 str = bundle_get_val(kb, AUL_K_STARTTIME);
232 setenv("APP_START_TIME", str, 1);
234 if(bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
235 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
236 if(str_array != NULL) {
237 for (i = 0; i < len; i++) {
238 _D("index : [%d]", i);
239 __set_sdk_env(menu_info, (char *)str_array[i], kb);
243 str = bundle_get_val(kb, AUL_K_SDK);
245 __set_sdk_env(menu_info, (char *)str, kb);
248 if (menu_info->hwacc != NULL)
249 setenv("HWACC", menu_info->hwacc, 1);
252 int __prepare_exec(const char *pkg_name,
253 const char *app_path, app_info_from_db * menu_info,
257 char process_name[AUL_PR_NAME];
260 /* Set new session ID & new process group ID*/
261 /* In linux, child can set new session ID without check permission */
262 /* TODO : should be add to check permission in the kernel*/
265 __preexec_run(menu_info->pkg_type, pkg_name, app_path);
271 if(bundle_get_val(kb, AUL_K_PRIVACY_APPID) == NULL) {
272 _D("pkg_name : %s / pkg_type : %s / app_path : %s ", pkg_name
273 , menu_info->pkg_type, app_path);
274 if ((ret = __set_access(pkg_name, menu_info->pkg_type
277 _D("fail to set privileges - check your package's credential : %d\n"
282 /* SET DUMPABLE - for coredump*/
283 prctl(PR_SET_DUMPABLE, 1);
285 /* SET PROCESS NAME*/
286 if (app_path == NULL) {
287 _D("app_path should not be NULL - check menu db");
290 file_name = strrchr(app_path, '/') + 1;
291 if (file_name == NULL) {
292 _D("can't locate file name to execute");
295 memset(process_name, '\0', AUL_PR_NAME);
296 snprintf(process_name, AUL_PR_NAME, "%s", file_name);
297 prctl(PR_SET_NAME, process_name);
300 __set_env(menu_info, kb);
305 int __fake_launch_app(int cmd, int pid, bundle * kb)
311 bundle_encode(kb, &kb_data, &datalen);
312 if ((ret = __app_send_raw(pid, cmd, kb_data, datalen)) < 0)
313 _E("error request fake launch - error code = %d", ret);
318 char** __add_arg(bundle * kb, char **argv, int *margc, const char *key)
320 const char *str = NULL;
321 const char **str_array = NULL;
324 char ** new_argv = NULL;
326 if(bundle_get_type(kb, key) & BUNDLE_TYPE_ARRAY) {
327 str_array = bundle_get_str_array(kb, key, &len);
329 str = bundle_get_val(kb, key);
335 if(str_array != NULL) {
336 if(strncmp(key, DLP_K_DEBUG_ARG, strlen(key)) == 0
337 || strncmp(key, DLP_K_VALGRIND_ARG, strlen(key)) == 0)
339 new_argv = (char **) realloc(argv
340 , sizeof(char *) * (*margc+len+2));
342 _E("realloc fail (key = %s)", key);
345 for(i=*margc+len+1; i-(len+1)>=0; i--) {
346 new_argv[i] = new_argv[i-(len+1)];
348 // need to add new_argv[0]
349 for(i=0; i<len; i++) {
350 new_argv[1+i] = strdup(str_array[i]);
352 len++; /* gdbserver or valgrind */
353 _D("uid : %d", getuid());
354 _D("euid : %d", geteuid());
355 _D("gid : %d", getgid());
356 _D("egid : %d", getegid());
358 new_argv = (char **) realloc(argv
359 , sizeof(char *) * (*margc+len+1));
361 _E("realloc fail (key = %s)", key);
364 for(i=0; i<len; i++) {
365 new_argv[*margc+i] = strdup(str_array[i]);
368 new_argv[*margc+len] = NULL;
371 if(strncmp(key, DLP_K_DEBUG_ARG, strlen(key)) == 0
372 || strncmp(key, DLP_K_VALGRIND_ARG, strlen(key)) == 0)
374 new_argv = (char **) realloc(argv
375 , sizeof(char *) * (*margc+2));
377 _E("realloc fail (key = %s)", key);
380 for(i=*margc+1; i-1>=0; i--) {
381 new_argv[i] = new_argv[i-1];
383 // need to add new_argv[0]
388 if(new_argv==NULL) return argv;
392 char **__create_argc_argv(bundle * kb, int *margc, const char *app_path)
395 char **new_argv = NULL;
398 const char *str = NULL;
399 const char **str_array = NULL;
403 argc = bundle_export_to_argv(kb, &argv);
405 for(i=1; i<argc; i++) {
406 argv[i] = strdup(argv[i]);
408 argv[0] = strdup(app_path);
410 _E("bundle_export_to_argv error");
414 if(bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
415 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
417 str = bundle_get_val(kb, AUL_K_SDK);
423 if(str_array == NULL) {
428 for (i = 0; i < len; i++) {
429 if(str_array[i] == NULL) break;
430 _D("index : [%d]", i);
432 if (strncmp(str_array[i], SDK_DEBUG, strlen(str_array[i])) == 0)
434 char buf[MAX_LOCAL_BUFSZ];
435 if (argv[0]) free(argv[0]);
436 snprintf(buf,MAX_LOCAL_BUFSZ,"%s.exe",app_path);
437 argv[0] = strdup(buf);
438 new_argv = __add_arg(kb, argv, &argc, DLP_K_DEBUG_ARG);
439 new_argv[0] = strdup(PATH_GDBSERVER);
443 else if (strncmp(str_array[i], SDK_VALGRIND
444 , strlen(str_array[i])) == 0)
446 new_argv = __add_arg(kb, argv, &argc
447 , DLP_K_VALGRIND_ARG);
448 new_argv[0] = strdup(PATH_VALGRIND);
452 else if (strncmp(str_array[i], SDK_UNIT_TEST
453 , strlen(str_array[i])) == 0)
455 new_argv = __add_arg(kb, argv, &argc
456 , DLP_K_UNIT_TEST_ARG);
462 if(new_argv==NULL) return argv;
466 int __normal_fork_exec(int argc, char **argv)
468 _D("start real fork and exec\n");
470 if (execv(argv[0], argv) < 0) { /* Flawfinder: ignore */
471 if (errno == EACCES) {
472 _E("such a file is no executable - %s", argv[0]);
474 _E("unknown executable error - %s", argv[0]);
482 void __real_launch(const char *app_path, bundle * kb)
488 app_argv = __create_argc_argv(kb, &app_argc, app_path);
490 for (i = 0; i < app_argc; i++)
491 _D("input argument %d : %s##", i, app_argv[i]);
493 PERF("setup argument done");
494 _D("lock up test log(no error) : setup argument done");
496 /* Temporary log: launch time checking */
497 LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:launchpad:done]", app_path);
499 __normal_fork_exec(app_argc, app_argv);
501 for(i=0; i<app_argc; i++) {
502 if(app_argv[i]) free(app_argv[i]);
509 * Parsing original app path to retrieve default bundle
511 * -1 : Invalid sequence
512 * -2 : Buffer overflow
515 static inline int __parser(const char *arg, char *out, int out_size)
519 char *start_out = out;
521 if (arg == NULL || out == NULL) {
522 /* Handles null buffer*/
526 for (i = 0; out_size > 1; i++) {
550 case 2: /* escape start*/
565 case 4: /* character escape*/
566 if (arg[i] == '\0') {
576 if (out != start_out) {
585 return -1; /* error*/
586 case 7: /* terminate*/
603 void __modify_bundle(bundle * kb, int caller_pid,
604 app_info_from_db * menu_info, int cmd)
606 bundle_del(kb, AUL_K_PKG_NAME);
607 bundle_del(kb, AUL_K_EXEC);
608 bundle_del(kb, AUL_K_PACKAGETYPE);
609 bundle_del(kb, AUL_K_HWACC);
611 /* Parse app_path to retrieve default bundle*/
612 if (cmd == APP_START || cmd == APP_START_RES || cmd == APP_OPEN
613 || cmd == APP_RESUME)
616 char exe[MAX_PATH_LEN];
619 ptr = _get_original_app_path(menu_info);
621 flag = __parser(ptr, exe, sizeof(exe));
627 _D("parsing app_path: EXEC - %s\n", exe);
630 flag = __parser(ptr, key, sizeof(key));
635 flag = __parser(ptr, value, sizeof(value));
640 /*bundle_del(kb, key);*/
641 bundle_add(kb, key, value);
643 } else if (flag == 0) {
644 _D("parsing app_path: No arguments\n");
646 _D("parsing app_path: Invalid argument\n");
651 int __send_to_sigkill(int pid)
659 if (killpg(pgid, SIGKILL) < 0)
665 int __term_app(int pid)
669 (pid, APP_TERM_BY_PID, (unsigned char *)&dummy, sizeof(int)) < 0) {
670 _D("terminate packet send error - use SIGKILL");
671 if (__send_to_sigkill(pid) < 0) {
672 _E("fail to killing - %d\n", pid);
680 static int __get_caller_pid(bundle *kb)
685 pid_str = bundle_get_val(kb, AUL_K_ORG_CALLER_PID);
689 pid_str = bundle_get_val(kb, AUL_K_CALLER_PID);
701 int __foward_cmd(int cmd, bundle *kb, int cr_pid)
704 char tmp_pid[MAX_PID_STR_BUFSZ];
709 if ((pid = __get_caller_pid(kb)) < 0)
712 snprintf(tmp_pid, MAX_PID_STR_BUFSZ, "%d", cr_pid);
714 bundle_add(kb, AUL_K_CALLEE_PID, tmp_pid);
716 bundle_encode(kb, &kb_data, &datalen);
717 if ((res = __app_send_raw_with_noreply(pid, cmd, kb_data, datalen)) < 0)
725 void __real_send(int clifd, int ret)
727 if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) {
728 if (errno == EPIPE) {
729 _E("send failed due to EPIPE.\n");
731 _E("send fail to client");
737 void __send_result_to_caller(int clifd, int ret)
741 int cmdline_changed = 0;
742 int cmdline_exist = 0;
748 __real_send(clifd, ret);
751 /* check normally was launched?*/
754 cmdline = __proc_get_cmdline_bypid(ret);
755 if (cmdline == NULL) {
756 _E("error founded when being launched with %d", ret);
758 } else if (strcmp(cmdline, launchpad_cmdline)) {
767 _D("-- now wait to change cmdline --");
768 usleep(50 * 1000); /* 50ms sleep*/
770 } while (wait_count <= 20); /* max 50*20ms will be sleep*/
772 if ((!cmdline_exist) && (!cmdline_changed)) {
773 _E("abnormally launched");
774 __real_send(clifd, -1); /* abnormally launched*/
778 if (!cmdline_changed)
779 _E("process launched, but cmdline not changed");
781 __real_send(clifd, ret);
785 static app_info_from_db *_get_app_info_from_bundle_by_pkgname(
786 const char *pkgname, bundle *kb)
788 app_info_from_db *menu_info;
790 menu_info = calloc(1, sizeof(app_info_from_db));
791 if (menu_info == NULL) {
795 menu_info->pkg_name = strdup(pkgname);
796 menu_info->app_path = strdup(bundle_get_val(kb, AUL_K_EXEC));
797 if (menu_info->app_path != NULL)
798 menu_info->original_app_path = strdup(menu_info->app_path);
799 menu_info->pkg_type = strdup(bundle_get_val(kb, AUL_K_PACKAGETYPE));
800 menu_info->hwacc = strdup(bundle_get_val(kb, AUL_K_HWACC));
802 if (!_get_app_path(menu_info)) {
803 _free_app_info_from_db(menu_info);
813 int get_native_appid(const char* app_path, char** appid) {
814 int rc = smack_lgetlabel(app_path, appid, SMACK_LABEL_ACCESS);
816 if (rc != 0 || *appid == NULL) {
817 _E("smack_lgetlabel fail");
821 if (strlen(*appid) != APPID_LEN) {
822 _E("wrong native appid : %s", *appid);
826 if (strlen(app_path) < sizeof(PATH_NATIVE_APP)+APPID_LEN-1) {
827 _E("wrong native app_path : %s", app_path);
830 else if ( strncmp(app_path, PATH_NATIVE_APP, sizeof(PATH_NATIVE_APP)-1)
831 || strncmp(&app_path[sizeof(PATH_NATIVE_APP)-1]
832 , *appid,APPID_LEN) )
834 _E("wrong native app_path : %s", app_path);
838 _D("get_appid return : %s", *appid);
842 int apply_smack_rules(const char* subject, const char* object
843 , const char* access_type)
845 struct smack_accesses *rules = NULL;
847 _D("apply_smack_rules : %s %s %s", subject, object, access_type);
849 if (smack_accesses_new(&rules)) {
850 _E("smack_accesses_new fail");
854 if (smack_accesses_add(rules, subject, object, access_type)) {
855 smack_accesses_free(rules);
856 _E("smack_accesses_add fail");
860 if (smack_accesses_apply(rules)) {
861 smack_accesses_free(rules);
862 _E("smack_accesses_apply fail");
866 smack_accesses_free(rules);
871 int __prepare_valgrind_outputfile(bundle *kb)
873 const char *str = NULL;
874 const char **str_array = NULL;
878 if(bundle_get_type(kb, DLP_K_VALGRIND_ARG) & BUNDLE_TYPE_ARRAY) {
879 str_array = bundle_get_str_array(kb, DLP_K_VALGRIND_ARG, &len);
881 str = bundle_get_val(kb, DLP_K_VALGRIND_ARG);
887 if(str_array == NULL) return 0;
889 for (i = 0; i < len; i++) {
890 if(str_array[i] == NULL) break;
891 /* valgrind log file option */
892 if (strncmp(str_array[i], OPT_VALGRIND_LOGFILE
893 , sizeof(OPT_VALGRIND_LOGFILE)-1) == 0)
895 if(strcmp(str_array[i], OPT_VALGRIND_LOGFILE_FIXED))
897 _E("wrong valgrind option(%s). It should be %s"
899 , OPT_VALGRIND_LOGFILE_FIXED);
902 poll_outputfile |= POLL_VALGRIND_LOGFILE;
903 if(remove(PATH_VALGRIND_LOGFILE)){
904 _D("cannot remove %s"
905 , PATH_VALGRIND_LOGFILE);
909 /* valgrind xml file option */
910 else if (strncmp(str_array[i], OPT_VALGRIND_XMLFILE
911 , sizeof(OPT_VALGRIND_XMLFILE)-1) == 0)
913 if(strcmp(str_array[i], OPT_VALGRIND_XMLFILE_FIXED))
915 _E("wrong valgrind option(%s). It should be %s"
917 , OPT_VALGRIND_XMLFILE_FIXED);
920 poll_outputfile |= POLL_VALGRIND_XMLFILE;
921 if(remove(PATH_VALGRIND_XMLFILE)){
922 _D("cannot remove %s"
923 , PATH_VALGRIND_XMLFILE);
927 /* valgrind massif file option */
928 else if (strncmp(str_array[i], OPT_VALGRIND_MASSIFFILE
929 , sizeof(OPT_VALGRIND_MASSIFFILE)-1) == 0)
931 if(strcmp(str_array[i], OPT_VALGRIND_MASSIFFILE_FIXED))
933 _E("wrong valgrind option(%s). It should be %s"
935 , OPT_VALGRIND_MASSIFFILE_FIXED);
938 poll_outputfile |= POLL_VALGRIND_XMLFILE;
939 if(remove(PATH_VALGRIND_XMLFILE)){
940 _D("cannot remove %s"
941 , PATH_VALGRIND_XMLFILE);
949 extern int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
951 int __adjust_process_capability(int sv)
953 static struct __user_cap_header_struct h;
954 static struct __user_cap_data_struct ori_d[_LINUX_CAPABILITY_U32S_2];
955 static struct __user_cap_data_struct inh_d[_LINUX_CAPABILITY_U32S_2];
956 static int isinit = 0;
959 h.version = _LINUX_CAPABILITY_VERSION_2;
965 inh_d[CAP_TO_INDEX(CAP_NET_RAW)].inheritable |=
966 CAP_TO_MASK(CAP_NET_RAW);
967 inh_d[CAP_TO_INDEX(CAP_SYS_CHROOT)].inheritable |=
968 CAP_TO_MASK(CAP_SYS_CHROOT);
972 if(sv == CAPABILITY_SET_ORIGINAL) return 0;
976 _E("__adjust_process_capability init failed");
980 if(sv == CAPABILITY_SET_ORIGINAL) {
982 if (capset(&h, ori_d) < 0) {
983 _E("Capability setting error");
987 else if (sv == CAPABILITY_SET_INHERITABLE) {
989 if (capset(&h, inh_d) < 0) {
990 _E("Capability setting error");
998 int __adjust_file_capability(const char * path)
1000 if(cap_set_file(path,cap_from_text("CAP_NET_RAW,CAP_SYS_CHROOT+i"))) {
1001 _E("cap_set_file failed : %s", path);
1007 int __prepare_fork(bundle *kb, char *appid)
1009 const char *str = NULL;
1010 const char **str_array = NULL;
1014 need_to_set_inh_cap_after_fork=0;
1015 poll_outputfile = 0;
1016 if(bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
1017 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
1019 str = bundle_get_val(kb, AUL_K_SDK);
1025 if(str_array == NULL) return 0;
1027 is_gdbserver_launched = 0;
1029 gdbserver_app_pid = -1;
1031 for (i = 0; i < len; i++) {
1032 if(str_array[i] == NULL) break;
1034 if (strncmp(str_array[i], SDK_DEBUG, strlen(str_array[i])) == 0)
1036 if(apply_smack_rules("sdbd",appid,"w")) {
1037 _E("unable to set sdbd rules");
1041 // FIXME: set gdbfolder to 755 also
1042 if(dlp_chmod(PATH_GDBSERVER
1043 , S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP
1047 _D("unable to set 755 to %s", PATH_GDBSERVER);
1049 __adjust_file_capability(PATH_GDBSERVER);
1050 need_to_set_inh_cap_after_fork++;
1051 is_gdbserver_launched++;
1054 else if (strncmp(str_array[i], SDK_VALGRIND
1055 , strlen(str_array[i])) == 0)
1057 if (__prepare_valgrind_outputfile(kb) == -1)
1059 __adjust_file_capability(PATH_MEMCHECK);
1065 /* chmod and chsmack to read file without root privilege */
1066 void __chmod_chsmack_toread(const char * path)
1069 if(dlp_chmod(path, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, 0))
1071 _E("unable to set 644 to %s", path);
1073 _D("set 644 to %s", path);
1077 if(smack_setlabel(path, "*", SMACK_LABEL_ACCESS))
1079 _E("failed chsmack -a \"*\" %s", path);
1081 _D("chsmack -a \"*\" %s", path);
1087 /* waiting for creating outputfile by child process */
1088 void __waiting_outputfile()
1091 while(poll_outputfile && wait_count<10) {
1092 /* valgrind log file */
1093 if( (poll_outputfile & POLL_VALGRIND_LOGFILE)
1094 && (access(PATH_VALGRIND_LOGFILE,F_OK)==0) )
1096 __chmod_chsmack_toread(PATH_VALGRIND_LOGFILE);
1097 poll_outputfile &= ~POLL_VALGRIND_LOGFILE;
1100 /* valgrind xml file */
1101 if( (poll_outputfile & POLL_VALGRIND_XMLFILE)
1102 && (access(PATH_VALGRIND_XMLFILE,F_OK)==0) )
1104 __chmod_chsmack_toread(PATH_VALGRIND_XMLFILE);
1105 poll_outputfile &= ~POLL_VALGRIND_XMLFILE;
1108 if(poll_outputfile) {
1109 _D("-- now wait for creating the file --");
1110 usleep(50 * 1000); /* 50ms sleep*/
1115 if(wait_count==10) _E("faild to waiting");
1119 int __stdout_stderr_redirection(int defpid)
1121 char defpath[UNIX_PATH_MAX];
1122 int deffd, result=0;
1125 snprintf(defpath, UNIX_PATH_MAX, "/proc/%d/fd/1", defpid);
1126 deffd = open(defpath,O_WRONLY);
1128 _E("opening caller(%d) stdout failed due to %s"
1129 , defpid, strerror(errno));
1137 snprintf(defpath, UNIX_PATH_MAX, "/proc/%d/fd/2", defpid);
1138 deffd = open(defpath,O_WRONLY);
1140 _E("opening caller(%d) stderr failed due to %s"
1141 , defpid,strerror(errno));
1151 void __launchpad_main_loop(int main_fd)
1154 app_pkt_t *pkt = NULL;
1155 app_info_from_db *menu_info = NULL;
1157 const char *pkg_name = NULL;
1158 const char *app_path = NULL;
1162 int is_real_launch = 0;
1164 char sock_path[UNIX_PATH_MAX] = {0,};
1165 char * appid = NULL;
1167 pkt = __app_recv_raw(main_fd, &clifd, &cr);
1169 _D("packet is NULL");
1173 kb = bundle_decode(pkt->data, pkt->len);
1175 _D("bundle decode error");
1180 PERF("packet processing start");
1182 pkg_name = bundle_get_val(kb, AUL_K_PKG_NAME);
1183 _D("pkg name : %s\n", pkg_name);
1185 menu_info = _get_app_info_from_bundle_by_pkgname(pkg_name, kb);
1186 if (menu_info == NULL) {
1187 _D("such pkg no found");
1191 app_path = _get_app_path(menu_info);
1192 if(app_path == NULL) {
1193 _E("app_path is NULL");
1196 if (app_path[0] != '/') {
1197 _D("app_path is not absolute path");
1202 int rc = get_native_appid(app_path,&appid);
1203 if(rc!=0 || appid==NULL) {
1204 _E("unable to get native appid");
1213 __modify_bundle(kb, cr.pid, menu_info, pkt->cmd);
1214 pkg_name = _get_pkgname(menu_info);
1216 PERF("get package information & modify bundle done");
1218 if(__prepare_fork(kb,appid) == -1) goto end;
1222 if(need_to_set_inh_cap_after_fork) {
1223 __adjust_process_capability(CAPABILITY_SET_INHERITABLE);
1226 _D("lock up test log(no error) : fork done");
1230 __signal_unset_sigchld();
1233 snprintf(sock_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX
1237 if(__stdout_stderr_redirection(__get_caller_pid(kb))) {
1238 _E("__stdout_stderr_redirection fail");
1241 PERF("prepare exec - first done");
1242 _D("lock up test log(no error) : prepare exec - first done");
1244 if (__prepare_exec(pkg_name, app_path,
1245 menu_info, kb) < 0) {
1246 _E("preparing work fail to launch - "
1247 "can not launch %s\n", pkg_name);
1251 PERF("prepare exec - second done");
1252 _D("lock up test log(no error) : prepare exec - second done");
1254 __real_launch(app_path, kb);
1259 if(is_gdbserver_launched) {
1260 char buf[MAX_LOCAL_BUFSZ];
1262 usleep(100 * 1000); /* 100ms sleep */
1263 snprintf(buf, MAX_LOCAL_BUFSZ, "%s.exe", app_path);
1264 gdbserver_app_pid = __proc_iter_cmdline(NULL, buf);
1266 if(gdbserver_app_pid == -1) {
1267 _E("faild to get app pid");
1269 gdbserver_pid = pid;
1270 pid = gdbserver_app_pid;
1274 _D("==> real launch pid : %d %s\n", pid, app_path);
1278 __send_result_to_caller(clifd, pid);
1281 if (is_real_launch) {
1283 __signal_block_sigchld();
1284 __send_app_launch_signal(pid);
1285 __signal_unblock_sigchld();
1289 if (menu_info != NULL)
1290 _free_app_info_from_db(menu_info);
1299 /* Active Flusing for Daemon */
1300 if (initialized > AUL_POLL_CNT) {
1301 sqlite3_release_memory(SQLITE_FLUSH_MAX);
1306 if(poll_outputfile) __waiting_outputfile();
1309 int __launchpad_pre_init(int argc, char **argv)
1316 /* get my(launchpad) command line*/
1317 launchpad_cmdline = __proc_get_cmdline_bypid(getpid());
1318 if (launchpad_cmdline == NULL) {
1319 _E("launchpad cmdline fail to get");
1322 _D("launchpad cmdline = %s", launchpad_cmdline);
1324 /* create launchpad sock */
1325 fd = __create_server_sock(DEBUG_LAUNCHPAD_PID);
1327 _E("server sock error");
1331 __preload_init(argc, argv);
1333 __preexec_init(argc, argv);
1338 int __launchpad_post_init()
1340 /* Setting this as a global variable to keep track
1341 of launchpad poll cnt */
1342 /* static int initialized = 0;*/
1349 if (__signal_set_sigchld() < 0)
1357 int main(int argc, char **argv)
1360 struct pollfd pfds[POLLFD_MAX];
1363 __adjust_process_capability(CAPABILITY_SET_ORIGINAL);
1365 /* init without concerning X & EFL*/
1366 main_fd = __launchpad_pre_init(argc, argv);
1368 _E("launchpad pre init failed");
1372 pfds[0].fd = main_fd;
1373 pfds[0].events = POLLIN;
1374 pfds[0].revents = 0;
1377 if (poll(pfds, POLLFD_MAX, -1) < 0)
1380 /* init with concerning X & EFL (because of booting
1382 if (__launchpad_post_init() < 0) {
1383 _E("launcpad post init failed");
1387 for (i = 0; i < POLLFD_MAX; i++) {
1388 if ((pfds[i].revents & POLLIN) != 0) {
1389 __launchpad_main_loop(pfds[i].fd);