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