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