enable to read valgrind outputfile without root on
[framework/appfw/debug-launchpad.git] / src / launchpad.c
1 /*
2  *  debug-launchpad
3  *
4  * Copyright (c) 2000 - 2011 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Contact: Jungmin Cho <chivalry.cho@samsung.com>, Gwangho Hwang <gwang.hwang@samsung.com>
7  *
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
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
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.
19  *
20  */
21
22 /*
23  * simple AUL daemon - launchpad 
24  */
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <dlfcn.h>
29 #include <X11/Xlib.h>
30 #include <sys/types.h>
31 #include <signal.h>
32 #include <dirent.h>
33 #include <fcntl.h>
34 #include <stdlib.h>
35 #include <sys/wait.h>
36 #include <poll.h>
37 #include <sys/prctl.h>
38 #include <malloc.h>
39
40 #include "app_sock.h"
41 #include "aul.h"
42
43 #include "config.h"
44
45 #include "menu_db_util.h"
46 #include "simple_util.h"
47 #include "access_control.h"
48 #include "preload.h"
49 #include "preexec.h"
50 #include "perf.h"
51 #include "sigchild.h"
52 #include "aul_util.h"
53
54 #include "heap_dbg.h"
55
56 #include "gl.h"
57
58 #include <sqlite3.h>
59 #include <sys/smack.h>
60 #include "fileutils.h"
61
62 #define _static_ static inline
63 #define POLLFD_MAX 1
64 #define SQLITE_FLUSH_MAX        (1048576)       /* (1024*1024) */
65 #define AUL_POLL_CNT            15
66 #define AUL_PR_NAME                     16
67 #define APPID_LEN       10
68 #define PATH_TMP "/tmp"
69 #define PATH_DATA "/data"
70
71 #define SDK_CODE_COVERAGE "CODE_COVERAGE"
72 #define SDK_DEBUG "DEBUG"
73 #define SDK_DYNAMIC_ANALYSIS "DYNAMIC_ANALYSIS"
74 #define SDK_UNIT_TEST "UNIT_TEST"
75 #define SDK_VALGRIND "VALGRIND"
76
77 /* DLP is short for debug-launchpad */
78 #define DLP_K_DEBUG_ARG "__DLP_DEBUG_ARG__"
79 #define DLP_K_UNIT_TEST_ARG "__DLP_UNIT_TEST_ARG__"
80 #define DLP_K_VALGRIND_ARG "__DLP_VALGRIND_ARG__"
81
82 #define PATH_GDBSERVER  "/home/developer/sdk_tools/gdbserver/gdbserver"
83 #define PATH_VALGRIND   "/home/developer/sdk_tools/valgrind/usr/bin/valgrind"
84 #define PATH_DA_SO      "/usr/lib/da_probe_osp.so"
85 #define PATH_NATIVE_APP "/opt/apps/"
86
87 #define OPT_VALGRIND_LOGFILE            "--log-file="
88 #define OPT_VALGRIND_LOGFILE_FIXED      "--log-file=/tmp/valgrind_result.txt"
89 #define PATH_VALGRIND_LOGFILE           "/tmp/valgrind_result.txt"
90 #define OPT_VALGRIND_XMLFILE            "--xml-file="
91 #define OPT_VALGRIND_XMLFILE_FIXED      "--xml-file=/tmp/valgrind_result.xml"
92 #define PATH_VALGRIND_XMLFILE           "/tmp/valgrind_result.xml"
93
94 #define POLL_VALGRIND_LOGFILE           0x00000001
95 #define POLL_VALGRIND_XMLFILE           0x00000002
96
97 static char *launchpad_cmdline;
98 static int initialized = 0;
99
100 static int poll_outputfile = 0;
101
102 void __set_oom();
103 void __set_env(app_info_from_db * menu_info, bundle * kb);
104 int __prepare_exec(const char *pkg_name,
105                             const char *app_path, app_info_from_db * menu_info,
106                             bundle * kb);
107 int __fake_launch_app(int cmd, int pid, bundle * kb);
108 char **__create_argc_argv(bundle * kb, int *margc, const char *app_path);
109 int __normal_fork_exec(int argc, char **argv);
110 void __real_launch(const char *app_path, bundle * kb);
111 static inline int __parser(const char *arg, char *out, int out_size);
112 void __modify_bundle(bundle * kb, int caller_pid,
113                             app_info_from_db * menu_info, int cmd);
114 int __send_to_sigkill(int pid);
115 int __term_app(int pid);
116 void __real_send(int clifd, int ret);
117 void __send_result_to_caller(int clifd, int ret);
118 void __launchpad_main_loop(int main_fd);
119 int __launchpad_pre_init(int argc, char **argv);
120 int __launchpad_post_init();
121
122 extern ail_error_e ail_db_close(void);
123
124
125
126 void __set_oom()
127 {
128         char buf[MAX_LOCAL_BUFSZ];
129         FILE *fp;
130
131         /* we should reset oomadj value as default because child 
132         inherits from parent oom_adj*/
133         snprintf(buf, MAX_LOCAL_BUFSZ, "/proc/%d/oom_adj", getpid());
134         fp = fopen(buf, "w");
135         if (fp == NULL)
136                 return;
137         fprintf(fp, "%d", -16);
138         fclose(fp);
139 }
140
141 void __set_sdk_env(app_info_from_db* menu_info, char* str) {
142         char buf_pkgname[MAX_LOCAL_BUFSZ];
143         char buf[MAX_LOCAL_BUFSZ];
144         int ret;
145
146         _D("key : %s / value : %s", AUL_K_SDK, str);
147         /* http://gcc.gnu.org/onlinedocs/gcc/Cross_002dprofiling.html*/
148         /* GCOV_PREFIX contains the prefix to add to the absolute paths */
149         /*      in the object file. Prefix can be absolute, or relative.*/
150         /*      The default is no prefix.  */
151         /* GCOV_PREFIX_STRIP indicates the how many initial directory names */
152         /*      to stripoff the hardwired absolute paths. Default value is 0. */
153         if (strncmp(str, SDK_CODE_COVERAGE, strlen(str)) == 0) {
154                 strncpy(buf_pkgname,_get_pkgname(menu_info),MAX_LOCAL_BUFSZ-1);
155                 buf_pkgname[MAX_LOCAL_BUFSZ-1]='\0';
156                 snprintf(buf, MAX_LOCAL_BUFSZ, PATH_TMP"/%s"PATH_DATA
157                         , strtok(buf_pkgname,"."));
158                 ret = setenv("GCOV_PREFIX", buf, 1);
159                 _D("GCOV_PREFIX : %d", ret);
160                 ret = setenv("GCOV_PREFIX_STRIP", "0", 1);
161                 _D("GCOV_PREFIX_STRIP : %d", ret);
162         } else if (strncmp(str, SDK_DYNAMIC_ANALYSIS, strlen(str)) == 0) {
163                 ret = setenv("LD_PRELOAD", PATH_DA_SO, 1);
164                 _D("LD_PRELOAD : %d", ret);
165         }
166 }
167
168
169 void __set_env(app_info_from_db * menu_info, bundle * kb)
170 {
171         const char *str;
172         const char **str_array;
173         int len;
174         int i;
175
176         setenv("PKG_NAME", _get_pkgname(menu_info), 1);
177
178         USE_ENGINE("gl")
179
180         str = bundle_get_val(kb, AUL_K_STARTTIME);
181         if (str != NULL)
182                 setenv("APP_START_TIME", str, 1);
183
184         if(bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
185                 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
186                 if(str_array != NULL) {
187                         for (i = 0; i < len; i++) {
188                                 _D("index : [%d]", i);
189                                 __set_sdk_env(menu_info, (char *)str_array[i]);
190                         }
191                 }
192         } else {
193                 str = bundle_get_val(kb, AUL_K_SDK);
194                 if(str != NULL) {
195                         __set_sdk_env(menu_info, (char *)str);
196                 }
197         }
198         if (menu_info->hwacc != NULL)
199                 setenv("HWACC", menu_info->hwacc, 1);
200 }
201
202 int __prepare_exec(const char *pkg_name,
203                             const char *app_path, app_info_from_db * menu_info,
204                             bundle * kb)
205 {
206         char *file_name;
207         char process_name[AUL_PR_NAME];
208         int ret;
209
210         /* Set new session ID & new process group ID*/
211         /* In linux, child can set new session ID without check permission */
212         /* TODO : should be add to check permission in the kernel*/
213         setsid();
214
215         __preexec_run(menu_info->pkg_type, pkg_name, app_path);
216
217         /* SET OOM*/
218         __set_oom();
219
220         /* SET PRIVILEGES*/
221         if(bundle_get_val(kb, AUL_K_PRIVACY_APPID) == NULL) {
222                 _D("pkg_name : %s / pkg_type : %s / app_path : %s ", pkg_name
223                         , menu_info->pkg_type, app_path);
224                 if ((ret = __set_access(pkg_name, menu_info->pkg_type
225                         , app_path)) < 0) 
226                 {
227                          _D("fail to set privileges - check your package's credential : %d\n"
228                                 , ret);
229                         return -1;
230                 }
231         }
232         /* SET DUMPABLE - for coredump*/
233         prctl(PR_SET_DUMPABLE, 1);
234
235         /* SET PROCESS NAME*/
236         if (app_path == NULL) {
237                 _D("app_path should not be NULL - check menu db");
238                 return -1;
239         }
240         file_name = strrchr(app_path, '/') + 1;
241         if (file_name == NULL) {
242                 _D("can't locate file name to execute");
243                 return -1;
244         }
245         memset(process_name, '\0', AUL_PR_NAME);
246         snprintf(process_name, AUL_PR_NAME, "%s", file_name);
247         prctl(PR_SET_NAME, process_name);
248
249         /* SET ENVIROMENT*/
250         __set_env(menu_info, kb);
251
252         return 0;
253 }
254
255 int __fake_launch_app(int cmd, int pid, bundle * kb)
256 {
257         int datalen;
258         int ret;
259         bundle_raw *kb_data;
260
261         bundle_encode(kb, &kb_data, &datalen);
262         if ((ret = __app_send_raw(pid, cmd, kb_data, datalen)) < 0)
263                 _E("error request fake launch - error code = %d", ret);
264         free(kb_data);
265         return ret;
266 }
267
268 char** __add_arg(bundle * kb, char **argv, int *margc, const char *key)
269 {
270         const char *str = NULL;
271         const char **str_array = NULL;
272         int len = 0;
273         int i;
274         char ** new_argv = NULL;
275
276         if(bundle_get_type(kb, key) & BUNDLE_TYPE_ARRAY) {
277                 str_array = bundle_get_str_array(kb, key, &len);
278         } else {
279                 str = bundle_get_val(kb, key);
280                 if(str) {
281                         str_array = &str;
282                         len = 1;
283                 }
284         }
285         if(str_array != NULL) {
286                 if(strncmp(key, DLP_K_DEBUG_ARG, strlen(key)) == 0
287                         || strncmp(key, DLP_K_VALGRIND_ARG, strlen(key)) == 0)
288                 {
289                         new_argv = (char **) realloc(argv
290                                 , sizeof(char *) * (*margc+len+2));
291                         if(!new_argv) {
292                                 _E("realloc fail (key = %s)", key);
293                                 exit(-1);
294                         }
295                         for(i=*margc+len+1; i-(len+1)>=0; i--) {
296                                 new_argv[i] = new_argv[i-(len+1)];
297                         }
298                         // need to add new_argv[0]
299                         for(i=0; i<len; i++) {
300                                 new_argv[1+i] = strdup(str_array[i]);
301                         }
302                         len++;  /* gdbserver or valgrind */
303                         _D("uid : %d", getuid());
304                         _D("euid : %d", geteuid());
305                         _D("gid : %d", getgid());
306                         _D("egid : %d", getegid());
307                 } else {
308                         new_argv = (char **) realloc(argv
309                                 , sizeof(char *) * (*margc+len+1));
310                         if(!new_argv) {
311                                 _E("realloc fail (key = %s)", key);
312                                 exit(-1);
313                         }
314                         for(i=0; i<len; i++) {
315                                 new_argv[*margc+i] = strdup(str_array[i]);
316                         }
317                 }
318                 new_argv[*margc+len] = NULL;
319                 *margc += len;
320         } else {
321                 if(strncmp(key, DLP_K_DEBUG_ARG, strlen(key)) == 0
322                         || strncmp(key, DLP_K_VALGRIND_ARG, strlen(key)) == 0)
323                 {
324                         new_argv = (char **) realloc(argv
325                                 , sizeof(char *) * (*margc+2));
326                         if(!new_argv) {
327                                 _E("realloc fail (key = %s)", key);
328                                 exit(-1);
329                         }
330                         for(i=*margc+1; i-1>=0; i--) {
331                                 new_argv[i] = new_argv[i-1];
332                         }
333                         // need to add new_argv[0]
334                         *margc++;
335                 }
336         }
337
338         if(new_argv==NULL) return argv;
339         return new_argv;
340 }
341
342 char **__create_argc_argv(bundle * kb, int *margc, const char *app_path)
343 {
344         char **argv = NULL;
345         char **new_argv = NULL;
346         int argc;
347
348         const char *str = NULL;
349         const char **str_array = NULL;
350         int len = 0;
351         int i;
352
353         argc = bundle_export_to_argv(kb, &argv);
354         if (argv) {
355                 argv[0] = strdup(app_path);
356         } else {
357                 _E("bundle_export_to_argv error");
358                 exit(-1);
359         }
360
361         if(bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
362                 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
363         } else {
364                 str = bundle_get_val(kb, AUL_K_SDK);
365                 if(str) {
366                         str_array = &str;
367                         len = 1;
368                 }
369         }
370         if(str_array == NULL) {
371                 *margc = argc;
372                 return argv;
373         }
374
375         for (i = 0; i < len; i++) {
376                 if(str_array[i] == NULL) break;
377                 _D("index : [%d]", i);
378                 /* gdbserver */
379                 if (strncmp(str_array[i], SDK_DEBUG, strlen(str_array[i])) == 0)
380                 {
381                         char buf[MAX_LOCAL_BUFSZ];
382                         if (argv[0]) free(argv[0]);
383                         sprintf(buf,"%s.exe",app_path);
384                         argv[0] = strdup(buf);
385                         new_argv = __add_arg(kb, argv, &argc, DLP_K_DEBUG_ARG);
386                         new_argv[0] = strdup(PATH_GDBSERVER);
387                 }
388                 /* valgrind */
389                 else if (strncmp(str_array[i], SDK_VALGRIND
390                         , strlen(str_array[i])) == 0)
391                 {
392                         new_argv = __add_arg(kb, argv, &argc
393                                 , DLP_K_VALGRIND_ARG);
394                         new_argv[0] = strdup(PATH_VALGRIND);
395                 }
396                 /* unit test */
397                 else if (strncmp(str_array[i], SDK_UNIT_TEST
398                         , strlen(str_array[i])) == 0)
399                 {
400                         new_argv = __add_arg(kb, argv, &argc
401                                 , DLP_K_UNIT_TEST_ARG);
402                 }
403         }
404
405         *margc = argc;
406         if(new_argv==NULL) return argv;
407         return new_argv;
408 }
409
410 int __normal_fork_exec(int argc, char **argv)
411 {
412         _D("start real fork and exec\n");
413
414         if (execv(argv[0], argv) < 0) { /* Flawfinder: ignore */
415                 if (errno == EACCES) {
416                         _E("such a file is no executable - %s", argv[0]);
417                 } else {
418                         _E("unknown executable error - %s", argv[0]);
419                 }
420                 return -1;
421         }
422         /* never reach */
423         return 0;
424 }
425
426 void __real_launch(const char *app_path, bundle * kb)
427 {
428         int app_argc;
429         char **app_argv;
430         int i;
431
432         app_argv = __create_argc_argv(kb, &app_argc, app_path);
433
434         for (i = 0; i < app_argc; i++)
435                 _D("input argument %d : %s##", i, app_argv[i]);
436
437         PERF("setup argument done");
438         _D("lock up test log(no error) : setup argument done");
439
440         /* Temporary log: launch time checking */
441         LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:launchpad:done]", app_path);
442
443         __normal_fork_exec(app_argc, app_argv);
444
445         for(i=0; i<app_argc; i++) {
446                 if(app_argv[i]) free(app_argv[i]);
447         }
448         free(app_argv);
449 }
450
451
452 /*
453  * Parsing original app path to retrieve default bundle
454  *
455  * -1 : Invalid sequence
456  * -2 : Buffer overflow
457  *
458  */
459 static inline int __parser(const char *arg, char *out, int out_size)
460 {
461         register int i;
462         int state = 1;
463         char *start_out = out;
464
465         if (arg == NULL || out == NULL) {
466                 /* Handles null buffer*/
467                 return 0;
468         }
469
470         for (i = 0; out_size > 1; i++) {
471                 switch (state) {
472                 case 1:
473                         switch (arg[i]) {
474                         case ' ':
475                         case '\t':
476                                 state = 5;
477                                 break;
478                         case '\0':
479                                 state = 7;
480                                 break;
481                         case '\"':
482                                 state = 2;
483                                 break;
484                         case '\\':
485                                 state = 4;
486                                 break;
487                         default:
488                                 *out = arg[i];
489                                 out++;
490                                 out_size--;
491                                 break;
492                         }
493                         break;
494                 case 2: /* escape start*/
495                         switch (arg[i]) {
496                         case '\0':
497                                 state = 6;
498                                 break;
499                         case '\"':
500                                 state = 1;
501                                 break;
502                         default:
503                                 *out = arg[i];
504                                 out++;
505                                 out_size--;
506                                 break;
507                         }
508                         break;
509                 case 4: /* character escape*/
510                         if (arg[i] == '\0') {
511                                 state = 6;
512                         } else {
513                                 *out = arg[i];
514                                 out++;
515                                 out_size--;
516                                 state = 1;
517                         }
518                         break;
519                 case 5: /* token*/
520                         if (out != start_out) {
521                                 *out = '\0';
522                                 out_size--;
523                                 return i;
524                         }
525                         i--;
526                         state = 1;
527                         break;
528                 case 6:
529                         return -1;      /* error*/
530                 case 7: /* terminate*/
531                         *out = '\0';
532                         out_size--;
533                         return 0;
534                 default:
535                         state = 6;
536                         break;  /* error*/
537                 }
538         }
539
540         if (out_size == 1) {
541                 *out = '\0';
542         }
543         /* Buffer overflow*/
544         return -2;
545 }
546
547 void __modify_bundle(bundle * kb, int caller_pid,
548                             app_info_from_db * menu_info, int cmd)
549 {
550         bundle_del(kb, AUL_K_PKG_NAME);
551         bundle_del(kb, AUL_K_EXEC);
552         bundle_del(kb, AUL_K_PACKAGETYPE);
553         bundle_del(kb, AUL_K_HWACC);
554
555         /* Parse app_path to retrieve default bundle*/
556         if (cmd == APP_START || cmd == APP_START_RES || cmd == APP_OPEN
557                 || cmd == APP_RESUME)
558         {
559                 char *ptr;
560                 char exe[MAX_PATH_LEN];
561                 int flag;
562
563                 ptr = _get_original_app_path(menu_info);
564
565                 flag = __parser(ptr, exe, sizeof(exe));
566                 if (flag > 0) {
567                         char key[256];
568                         char value[256];
569
570                         ptr += flag;
571                         _D("parsing app_path: EXEC - %s\n", exe);
572
573                         do {
574                                 flag = __parser(ptr, key, sizeof(key));
575                                 if (flag <= 0)
576                                         break;
577                                 ptr += flag;
578
579                                 flag = __parser(ptr, value, sizeof(value));
580                                 if (flag < 0)
581                                         break;
582                                 ptr += flag;
583
584                                 /*bundle_del(kb, key);*/
585                                 bundle_add(kb, key, value);
586                         } while (flag > 0);
587                 } else if (flag == 0) {
588                         _D("parsing app_path: No arguments\n");
589                 } else {
590                         _D("parsing app_path: Invalid argument\n");
591                 }
592         }
593 }
594
595 int __send_to_sigkill(int pid)
596 {
597         int pgid;
598
599         pgid = getpgid(pid);
600         if (pgid <= 1)
601                 return -1;
602
603         if (killpg(pgid, SIGKILL) < 0)
604                 return -1;
605
606         return 0;
607 }
608
609 int __term_app(int pid)
610 {
611         int dummy;
612         if (__app_send_raw
613             (pid, APP_TERM_BY_PID, (unsigned char *)&dummy, sizeof(int)) < 0) {
614                 _D("terminate packet send error - use SIGKILL");
615                 if (__send_to_sigkill(pid) < 0) {
616                         _E("fail to killing - %d\n", pid);
617                         return -1;
618                 }
619         }
620         _D("term done\n");
621         return 0;
622 }
623
624 static int __get_caller_pid(bundle *kb)
625 {
626         const char *pid_str;
627         int pid;
628
629         pid_str = bundle_get_val(kb, AUL_K_ORG_CALLER_PID);
630         if(pid_str)
631                 goto end;
632
633         pid_str = bundle_get_val(kb, AUL_K_CALLER_PID);
634         if (pid_str == NULL)
635                 return -1;
636
637 end:
638         pid = atoi(pid_str);
639         if (pid <= 1)
640                 return -1;
641
642         return pid;
643 }
644
645 int __foward_cmd(int cmd, bundle *kb, int cr_pid)
646 {
647         int pid;
648         char tmp_pid[MAX_PID_STR_BUFSZ];
649         int datalen;
650         bundle_raw *kb_data;
651         int res;
652
653         if ((pid = __get_caller_pid(kb)) < 0)
654                         return AUL_R_ERROR;
655
656         snprintf(tmp_pid, MAX_PID_STR_BUFSZ, "%d", cr_pid);
657
658         bundle_add(kb, AUL_K_CALLEE_PID, tmp_pid);
659
660         bundle_encode(kb, &kb_data, &datalen);
661         if ((res = __app_send_raw_with_noreply(pid, cmd, kb_data, datalen)) < 0)
662                 res = AUL_R_ERROR;
663
664         free(kb_data);
665
666         return res;
667 }
668
669 void __real_send(int clifd, int ret)
670 {
671         if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) {
672                 if (errno == EPIPE) {
673                         _E("send failed due to EPIPE.\n");
674                 }
675                 _E("send fail to client");
676         }
677
678         close(clifd);
679 }
680
681 void __send_result_to_caller(int clifd, int ret)
682 {
683         char *cmdline;
684         int wait_count;
685         int cmdline_changed = 0;
686         int cmdline_exist = 0;
687
688         if (clifd == -1)
689                 return;
690
691         if (ret <= 1) {
692                 __real_send(clifd, ret);
693                 return;
694         }
695         /* check normally was launched?*/
696         wait_count = 1;
697         do {
698                 cmdline = __proc_get_cmdline_bypid(ret);
699                 if (cmdline == NULL) {
700                         _E("error founded when being launched with %d", ret);
701
702                 } else if (strcmp(cmdline, launchpad_cmdline)) {
703                         free(cmdline);
704                         cmdline_changed = 1;
705                         break;
706                 } else {
707                         cmdline_exist = 1;
708                         free(cmdline);
709                 }
710
711                 _D("-- now wait to change cmdline --");
712                 usleep(50 * 1000);      /* 50ms sleep*/
713                 wait_count++;
714         } while (wait_count <= 20);     /* max 50*20ms will be sleep*/
715
716         if ((!cmdline_exist) && (!cmdline_changed)) {
717                 _E("abnormally launched");
718                 __real_send(clifd, -1); /* abnormally launched*/
719                 return;
720         }
721
722         if (!cmdline_changed)
723                 _E("process launched, but cmdline not changed");
724
725         __real_send(clifd, ret);
726         return;
727 }
728
729 static app_info_from_db *_get_app_info_from_bundle_by_pkgname(
730         const char *pkgname, bundle *kb)
731 {
732         app_info_from_db *menu_info;
733
734         menu_info = calloc(1, sizeof(app_info_from_db));
735         if (menu_info == NULL) {
736                 return NULL;
737         }
738
739         menu_info->pkg_name = strdup(pkgname);
740         menu_info->app_path = strdup(bundle_get_val(kb, AUL_K_EXEC));
741         if (menu_info->app_path != NULL)
742                 menu_info->original_app_path = strdup(menu_info->app_path);
743         menu_info->pkg_type = strdup(bundle_get_val(kb, AUL_K_PACKAGETYPE));
744         menu_info->hwacc = strdup(bundle_get_val(kb, AUL_K_HWACC));
745
746         if (!_get_app_path(menu_info)) {
747                 _free_app_info_from_db(menu_info);
748                 return NULL;
749         }
750
751         return menu_info;
752 }
753
754 /**
755  * free after use it
756  */
757 int get_native_appid(const char* app_path, char** appid) {
758         int rc = smack_lgetlabel(app_path, appid, SMACK_LABEL_ACCESS);
759
760         if (rc != 0 || *appid == NULL) {
761                 _E("smack_lgetlabel fail");
762                 return -1;
763         }
764
765         if (strlen(*appid) != APPID_LEN) {
766                 _E("wrong native appid : %s", *appid);
767                 return -1;
768         }
769
770         if (strlen(app_path) < sizeof(PATH_NATIVE_APP)+APPID_LEN-1) {
771                 _E("wrong native app_path : %s", app_path);
772                 return -1;
773         }
774         else if ( strncmp(app_path, PATH_NATIVE_APP, sizeof(PATH_NATIVE_APP)-1)
775                 || strncmp(&app_path[sizeof(PATH_NATIVE_APP)-1]
776                 , *appid,APPID_LEN) )
777         {
778                 _E("wrong native app_path : %s", app_path);
779                 return -1;
780         }
781         
782         _D("get_appid return : %s", *appid);
783         return 0;
784 }
785
786 int apply_smack_rules(const char* subject, const char* object
787         , const char* access_type)
788 {
789         struct smack_accesses *rules = NULL;
790
791         _D("apply_smack_rules : %s %s %s", subject, object, access_type);
792
793         if (smack_accesses_new(&rules)) {
794                 _E("smack_accesses_new fail");
795                 return -1;
796         }
797
798         if (smack_accesses_add(rules, subject, object, access_type)) {
799                 smack_accesses_free(rules);
800                 _E("smack_accesses_add fail");
801                 return -1;
802         }
803
804         if (smack_accesses_apply(rules)) {
805                 smack_accesses_free(rules);
806                 _E("smack_accesses_apply fail");
807                 return -1;
808         }
809
810         smack_accesses_free(rules);
811
812         return 0;
813 }
814
815 int __prepare_valgrind_outputfile(bundle *kb)
816 {
817         const char *str = NULL;
818         const char **str_array = NULL;
819         int len = 0;
820         int i;
821
822         if(bundle_get_type(kb, DLP_K_VALGRIND_ARG) & BUNDLE_TYPE_ARRAY) {
823                 str_array = bundle_get_str_array(kb, DLP_K_VALGRIND_ARG, &len);
824         } else {
825                 str = bundle_get_val(kb, DLP_K_VALGRIND_ARG);
826                 if(str) {
827                         str_array = &str;
828                         len = 1;
829                 }
830         }
831         if(str_array == NULL) return 0;
832
833         for (i = 0; i < len; i++) {
834                 if(str_array[i] == NULL) break;
835                 /* valgrind log file option */
836                 if (strncmp(str_array[i], OPT_VALGRIND_LOGFILE
837                         , strlen(OPT_VALGRIND_LOGFILE)) == 0)
838                 {
839                         if(strncmp(str_array[i], OPT_VALGRIND_LOGFILE_FIXED
840                                 , strlen(str_array[i])))
841                         {
842                                 _E("wrong valgrind option(%s). It should be %s"
843                                         , str_array[i]
844                                         , OPT_VALGRIND_LOGFILE_FIXED);
845                                 return 1;
846                         }else{
847                                 poll_outputfile |= POLL_VALGRIND_LOGFILE;
848                                 if(remove(PATH_VALGRIND_LOGFILE)){
849                                         _D("cannot remove %s"
850                                                 , PATH_VALGRIND_LOGFILE);
851                                 }
852                         }
853                 }
854                 /* valgrind xml file option */
855                 else if (strncmp(str_array[i], OPT_VALGRIND_XMLFILE
856                         , strlen(OPT_VALGRIND_XMLFILE)) == 0)
857                 {
858                         if(strncmp(str_array[i], OPT_VALGRIND_XMLFILE_FIXED
859                                 , strlen(str_array[i])))
860                         {
861                                 _E("wrong valgrind option(%s). It should be %s"
862                                         , str_array[i]
863                                         , OPT_VALGRIND_XMLFILE_FIXED);
864                                 return 1;
865                         }else{
866                                 poll_outputfile |= POLL_VALGRIND_XMLFILE;
867                                 if(remove(PATH_VALGRIND_XMLFILE)){
868                                         _D("cannot remove %s"
869                                                 , PATH_VALGRIND_XMLFILE);
870                                 }
871                         }
872                 }
873         }
874         return 0;
875 }
876
877 int __prepare_fork(bundle *kb, char *appid)
878 {
879         const char *str = NULL;
880         const char **str_array = NULL;
881         int len = 0;
882         int i;
883
884         poll_outputfile = 0;
885         if(bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
886                 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
887         } else {
888                 str = bundle_get_val(kb, AUL_K_SDK);
889                 if(str) {
890                         str_array = &str;
891                         len = 1;
892                 }
893         }
894         if(str_array == NULL) return 0;
895
896         for (i = 0; i < len; i++) {
897                 if(str_array[i] == NULL) break;
898                 /* gdbserver */
899                 if (strncmp(str_array[i], SDK_DEBUG, strlen(str_array[i])) == 0)
900                 {
901                         if(apply_smack_rules("sdbd",appid,"w")) {
902                                 _E("unable to set sdbd rules");
903                                 return 1;
904                         }
905
906                         // FIXME: set gdbfolder to 755 also
907                         if(dlp_chmod(PATH_GDBSERVER
908                                 , S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP
909                                 |S_IROTH|S_IXOTH
910                                 , 1))
911                         {
912                                 _D("unable to set 755 to %s", PATH_GDBSERVER);
913                         }
914                 }
915                 /* valgrind */
916                 else if (strncmp(str_array[i], SDK_VALGRIND
917                         , strlen(str_array[i])) == 0)
918                 {
919                         if (__prepare_valgrind_outputfile(kb)) return 1;
920                 }
921         }
922         return 0;
923 }
924
925 /* chmod and chsmack to read file without root privilege */
926 void __chmod_chsmack_toread(const char * path)
927 {
928         /* chmod */
929         if(dlp_chmod(path, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH, 0))
930         {
931                 _E("unable to set 644 to %s", path);
932         }else{
933                 _D("set 644 to %s", path);
934         }
935
936         /* chsmack */
937         if(smack_setlabel(path, "*", SMACK_LABEL_ACCESS))
938         {
939                 _E("failed chsmack -a \"*\" %s", path);
940         }else{
941                 _D("chsmack -a \"*\" %s", path);
942         }
943
944         return;
945 }
946
947 /* waiting for creating outputfile by child process */
948 void __waiting_outputfile()
949 {
950         int wait_count = 0;
951         while(poll_outputfile && wait_count<10) {
952                 /* valgrind log file */
953                 if( (poll_outputfile & POLL_VALGRIND_LOGFILE) 
954                         && (access(PATH_VALGRIND_LOGFILE,F_OK)==0) )
955                 {
956                         __chmod_chsmack_toread(PATH_VALGRIND_LOGFILE);
957                         poll_outputfile &= ~POLL_VALGRIND_LOGFILE;
958                 }
959
960                 /* valgrind xml file */
961                 if( (poll_outputfile & POLL_VALGRIND_XMLFILE)
962                         && (access(PATH_VALGRIND_XMLFILE,F_OK)==0) )
963                 {
964                         __chmod_chsmack_toread(PATH_VALGRIND_XMLFILE);
965                         poll_outputfile &= ~POLL_VALGRIND_XMLFILE;
966                 }
967                 
968                 if(poll_outputfile) {
969                         _D("-- now wait for creating the file --");
970                         usleep(50 * 1000);      /* 50ms sleep*/
971                         wait_count++;
972                 }
973         }
974
975         if(wait_count==10) _E("faild to waiting");
976         return;
977 }
978
979 void __launchpad_main_loop(int main_fd)
980 {
981         bundle *kb = NULL;
982         app_pkt_t *pkt = NULL;
983         app_info_from_db *menu_info = NULL;
984
985         const char *pkg_name = NULL;
986         const char *app_path = NULL;
987         int pid = -1;
988         int clifd = -1;
989         struct ucred cr;
990         int is_real_launch = 0;
991
992         char sock_path[UNIX_PATH_MAX] = {0,};
993         char * appid = NULL;
994
995         pkt = __app_recv_raw(main_fd, &clifd, &cr);
996         if (!pkt) {
997                 _D("packet is NULL");
998                 goto end;
999         }
1000
1001         kb = bundle_decode(pkt->data, pkt->len);
1002         if (!kb) {
1003                 _D("bundle decode error");
1004                 goto end;
1005         }
1006
1007         INIT_PERF(kb);
1008         PERF("packet processing start");
1009
1010         pkg_name = bundle_get_val(kb, AUL_K_PKG_NAME);
1011         _D("pkg name : %s\n", pkg_name);
1012
1013         menu_info = _get_app_info_from_bundle_by_pkgname(pkg_name, kb);
1014         if (menu_info == NULL) {
1015                 _D("such pkg no found");
1016                 goto end;
1017         }
1018
1019         app_path = _get_app_path(menu_info);
1020         if(app_path == NULL) {
1021                 _E("app_path is NULL");
1022                 goto end;
1023         }
1024         if (app_path[0] != '/') {
1025                 _D("app_path is not absolute path");
1026                 goto end;
1027         }
1028
1029         {
1030                 int rc = get_native_appid(app_path,&appid);
1031                 if(rc!=0 || appid==NULL) {
1032                         _E("unable to get native appid");
1033                         if(appid) free(appid);
1034                         goto end;
1035                 }
1036         }
1037
1038         __modify_bundle(kb, cr.pid, menu_info, pkt->cmd);
1039         pkg_name = _get_pkgname(menu_info);
1040
1041         PERF("get package information & modify bundle done");
1042
1043         if(__prepare_fork(kb,appid)) goto end;
1044
1045         pid = fork();
1046         if (pid == 0) {
1047                 PERF("fork done");
1048                 _D("lock up test log(no error) : fork done");
1049
1050                 close(clifd);
1051                 close(main_fd);
1052                 __signal_unset_sigchld();
1053                 __signal_fini();
1054
1055                 snprintf(sock_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX
1056                         , getpid());
1057                 unlink(sock_path);
1058
1059                 PERF("prepare exec - first done");
1060                 _D("lock up test log(no error) : prepare exec - first done");
1061
1062                 if (__prepare_exec(pkg_name, app_path,
1063                                    menu_info, kb) < 0) {
1064                         _E("preparing work fail to launch - "
1065                            "can not launch %s\n", pkg_name);
1066                         exit(-1);
1067                 }
1068
1069                 PERF("prepare exec - second done");
1070                 _D("lock up test log(no error) : prepare exec - second done");
1071
1072                 __real_launch(app_path, kb);
1073
1074                 exit(-1);
1075         }
1076
1077         _D("==> real launch pid : %d %s\n", pid, app_path);
1078         is_real_launch = 1;
1079
1080  end:
1081         __send_result_to_caller(clifd, pid);
1082
1083         if (pid > 0) {
1084                 if (is_real_launch) {
1085                         /*TODO: retry*/
1086                         __signal_block_sigchld();
1087                         __send_app_launch_signal(pid);
1088                         __signal_unblock_sigchld();
1089                 }
1090         }
1091
1092         if (menu_info != NULL)
1093                 _free_app_info_from_db(menu_info);
1094
1095         if (kb != NULL)
1096                 bundle_free(kb);
1097         if (pkt != NULL)
1098                 free(pkt);
1099         if (appid != NULL) 
1100                 free(appid);
1101
1102         /* Active Flusing for Daemon */
1103         if (initialized > AUL_POLL_CNT) {
1104                 sqlite3_release_memory(SQLITE_FLUSH_MAX);
1105                 malloc_trim(0);
1106                 initialized = 1;
1107         }
1108
1109         if(poll_outputfile) __waiting_outputfile();
1110 }
1111
1112 int __launchpad_pre_init(int argc, char **argv)
1113 {
1114         int fd;
1115
1116         /* signal init*/
1117         __signal_init();
1118
1119         /* get my(launchpad) command line*/
1120         launchpad_cmdline = __proc_get_cmdline_bypid(getpid());
1121         if (launchpad_cmdline == NULL) {
1122                 _E("launchpad cmdline fail to get");
1123                 return -1;
1124         }
1125         _D("launchpad cmdline = %s", launchpad_cmdline);
1126
1127         /* create launchpad sock        */
1128         fd = __create_server_sock(DEBUG_LAUNCHPAD_PID);
1129         if (fd < 0) {
1130                 _E("server sock error");
1131                 return -1;
1132         }
1133
1134         __preload_init(argc, argv);
1135
1136         __preexec_init(argc, argv);
1137
1138         return fd;
1139 }
1140
1141 int __launchpad_post_init()
1142 {
1143         /* Setting this as a global variable to keep track 
1144         of launchpad poll cnt */
1145         /* static int initialized = 0;*/
1146
1147         if (initialized) {
1148                 initialized++;
1149                 return 0;
1150         }
1151
1152         if (__signal_set_sigchld() < 0)
1153                 return -1;
1154
1155         initialized++;
1156
1157         return 0;
1158 }
1159
1160 int main(int argc, char **argv)
1161 {
1162         int main_fd;
1163         struct pollfd pfds[POLLFD_MAX];
1164         int i;
1165
1166         /* init without concerning X & EFL*/
1167         main_fd = __launchpad_pre_init(argc, argv);
1168         if (main_fd < 0) {
1169                 _E("launchpad pre init failed");
1170                 exit(-1);
1171         }
1172
1173         pfds[0].fd = main_fd;
1174         pfds[0].events = POLLIN;
1175         pfds[0].revents = 0;
1176
1177         while (1) {
1178                 if (poll(pfds, POLLFD_MAX, -1) < 0)
1179                         continue;
1180
1181                 /* init with concerning X & EFL (because of booting 
1182                 sequence problem)*/
1183                 if (__launchpad_post_init() < 0) {
1184                         _E("launcpad post init failed");
1185                         exit(-1);
1186                 }
1187
1188                 for (i = 0; i < POLLFD_MAX; i++) {
1189                         if ((pfds[i].revents & POLLIN) != 0) {
1190                                 __launchpad_main_loop(pfds[i].fd);
1191                         }
1192                 }
1193         }
1194 }
1195