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