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