2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 * simple AUL daemon - launchpad
26 #include <sys/types.h>
33 #include <sys/prctl.h>
41 #include "menu_db_util.h"
42 #include "simple_util.h"
43 #include "access_control.h"
54 #include <app-checker.h>
57 #define _static_ static inline
59 #define SQLITE_FLUSH_MAX (1048576) /* (1024*1024) */
60 #define AUL_POLL_CNT 15
61 #define AUL_PR_NAME 16
62 #define PATH_APP_ROOT "/opt/usr/apps"
63 #define PATH_DATA "/data"
64 #define SDK_CODE_COVERAGE "CODE_COVERAGE"
65 #define SDK_DYNAMIC_ANALYSIS "DYNAMIC_ANALYSIS"
66 #define PATH_DA_SO "/home/developer/sdk_tools/da/da_probe.so"
69 static char *launchpad_cmdline;
70 static int initialized = 0;
73 _static_ void __set_oom();
74 _static_ void __set_env(app_info_from_db * menu_info, bundle * kb);
75 _static_ int __prepare_exec(const char *pkg_name,
76 const char *app_path, app_info_from_db * menu_info,
78 _static_ int __fake_launch_app(int cmd, int pid, bundle * kb);
79 _static_ char **__create_argc_argv(bundle * kb, int *margc);
80 _static_ int __normal_fork_exec(int argc, char **argv);
81 _static_ void __real_launch(const char *app_path, bundle * kb);
82 static inline int __parser(const char *arg, char *out, int out_size);
83 _static_ void __modify_bundle(bundle * kb, int caller_pid,
84 app_info_from_db * menu_info, int cmd);
85 _static_ int __child_raise_win_by_x(int pid, void *priv);
86 _static_ int __raise_win_by_x(int pid);
87 _static_ int __send_to_sigkill(int pid);
88 _static_ int __term_app(int pid);
89 _static_ int __resume_app(int pid);
90 _static_ void __real_send(int clifd, int ret);
91 _static_ void __send_result_to_caller(int clifd, int ret);
92 _static_ void __launchpad_main_loop(int main_fd);
93 _static_ int __launchpad_pre_init(int argc, char **argv);
94 _static_ int __launchpad_post_init();
96 extern ail_error_e ail_db_close(void);
100 _static_ void __set_oom()
102 char buf[MAX_LOCAL_BUFSZ];
105 /* we should reset oomadj value as default because child
106 inherits from parent oom_adj*/
107 snprintf(buf, MAX_LOCAL_BUFSZ, "/proc/%d/oom_adj", getpid());
108 fp = fopen(buf, "w");
111 fprintf(fp, "%d", -16);
115 _static_ void __set_sdk_env(app_info_from_db* menu_info, char* str) {
116 char buf[MAX_LOCAL_BUFSZ];
119 _D("key : %s / value : %s", AUL_K_SDK, str);
120 /* http://gcc.gnu.org/onlinedocs/gcc/Cross_002dprofiling.html*/
121 /* GCOV_PREFIX contains the prefix to add to the absolute paths in the object file. */
122 /* Prefix can be absolute, or relative. The default is no prefix. */
123 /* GCOV_PREFIX_STRIP indicates the how many initial directory names */
124 /* to stripoff the hardwired absolute paths. Default value is 0. */
125 if (strncmp(str, SDK_CODE_COVERAGE, strlen(str)) == 0) {
126 snprintf(buf, MAX_LOCAL_BUFSZ, PATH_APP_ROOT"/%s"PATH_DATA, _get_pkgname(menu_info));
127 ret = setenv("GCOV_PREFIX", buf, 1);
128 _D("GCOV_PREFIX : %d", ret);
129 ret = setenv("GCOV_PREFIX_STRIP", "4096", 1);
130 _D("GCOV_PREFIX_STRIP : %d", ret);
131 } else if (strncmp(str, SDK_DYNAMIC_ANALYSIS, strlen(str)) == 0) {
132 ret = setenv("LD_PRELOAD", PATH_DA_SO, 1);
133 _D("LD_PRELOAD : %d", ret);
138 _static_ void __set_env(app_info_from_db * menu_info, bundle * kb)
141 const char **str_array;
145 setenv("PKG_NAME", _get_pkgname(menu_info), 1);
149 str = bundle_get_val(kb, AUL_K_STARTTIME);
151 setenv("APP_START_TIME", str, 1);
153 if(bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
154 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
155 if(str_array != NULL) {
156 for (i = 0; i < len; i++) {
157 _D("index : [%d]", i);
158 __set_sdk_env(menu_info, (char *)str_array[i]);
162 str = bundle_get_val(kb, AUL_K_SDK);
164 __set_sdk_env(menu_info, (char *)str);
167 if (menu_info->hwacc != NULL)
168 setenv("HWACC", menu_info->hwacc, 1);
171 _static_ int __prepare_exec(const char *pkg_name,
172 const char *app_path, app_info_from_db * menu_info,
176 char process_name[AUL_PR_NAME];
178 /* Set new session ID & new process group ID*/
179 /* In linux, child can set new session ID without check permission */
180 /* TODO : should be add to check permission in the kernel*/
183 __preexec_run(menu_info->pkg_type, pkg_name, app_path);
189 if (__set_access(pkg_name, menu_info->pkg_type, app_path) < 0) {
190 _D("fail to set privileges - check your package's credential\n");
193 /* SET DUMPABLE - for coredump*/
194 prctl(PR_SET_DUMPABLE, 1);
196 /* SET PROCESS NAME*/
197 if (app_path == NULL) {
198 _D("app_path should not be NULL - check menu db");
201 file_name = strrchr(app_path, '/') + 1;
202 if (file_name == NULL) {
203 _D("can't locate file name to execute");
206 memset(process_name, '\0', AUL_PR_NAME);
207 snprintf(process_name, AUL_PR_NAME, "%s", file_name);
208 prctl(PR_SET_NAME, process_name);
211 __set_env(menu_info, kb);
216 _static_ int __fake_launch_app(int cmd, int pid, bundle * kb)
222 bundle_encode(kb, &kb_data, &datalen);
223 if ((ret = __app_send_raw(pid, cmd, kb_data, datalen)) < 0)
224 _E("error request fake launch - error code = %d", ret);
229 _static_ char **__create_argc_argv(bundle * kb, int *margc)
234 argc = bundle_export_to_argv(kb, &argv);
240 _static_ int __normal_fork_exec(int argc, char **argv)
242 _D("start real fork and exec\n");
244 // warning: unused parameter
247 if (execv(argv[0], argv) < 0) { /* Flawfinder: ignore */
249 _E("such a file is no executable - %s", argv[0]);
251 _E("unknown executable error - %s", argv[0]);
258 _static_ void __real_launch(const char *app_path, bundle * kb)
264 app_argv = __create_argc_argv(kb, &app_argc);
266 #ifndef NATIVE_LAUNCHPAD
267 if (__change_cmdline(app_path) < 0) {
268 _E("change cmdline fail");
272 app_argv[0] = g_argv[0];
274 app_argv[0] = strdup(app_path);
277 for (i = 0; i < app_argc; i++)
278 _D("input argument %d : %s##", i, app_argv[i]);
280 PERF("setup argument done");
281 _E("lock up test log(no error) : setup argument done");
283 /* Temporary log: launch time checking */
284 LOG(LOG_DEBUG, "LAUNCH", "[%s:Platform:launchpad:done]", app_path);
286 __preload_exec(app_argc, app_argv);
288 __normal_fork_exec(app_argc, app_argv);
292 * Parsing original app path to retrieve default bundle
294 * -1 : Invalid sequence
295 * -2 : Buffer overflow
298 static inline int __parser(const char *arg, char *out, int out_size)
302 char *start_out = out;
304 if (arg == NULL || out == NULL) {
305 /* Handles null buffer*/
309 for (i = 0; out_size > 1; i++) {
333 case 2: /* escape start*/
348 case 4: /* character escape*/
349 if (arg[i] == '\0') {
359 if (out != start_out) {
368 return -1; /* error*/
369 case 7: /* terminate*/
386 _static_ void __modify_bundle(bundle * kb, int caller_pid,
387 app_info_from_db * menu_info, int cmd)
389 // warning: unused parameter
390 caller_pid = caller_pid;
392 bundle_del(kb, AUL_K_PKG_NAME);
393 bundle_del(kb, AUL_K_EXEC);
394 bundle_del(kb, AUL_K_PACKAGETYPE);
395 bundle_del(kb, AUL_K_HWACC);
397 /* Parse app_path to retrieve default bundle*/
398 if (cmd == APP_START || cmd == APP_START_RES || cmd == APP_OPEN || cmd == APP_RESUME) {
400 char exe[MAX_PATH_LEN];
403 ptr = _get_original_app_path(menu_info);
405 flag = __parser(ptr, exe, sizeof(exe));
411 _D("parsing app_path: EXEC - %s\n", exe);
414 flag = __parser(ptr, key, sizeof(key));
419 flag = __parser(ptr, value, sizeof(value));
424 /*bundle_del(kb, key);*/
425 bundle_add(kb, key, value);
427 } else if (flag == 0) {
428 _D("parsing app_path: No arguments\n");
430 _D("parsing app_path: Invalid argument\n");
435 _static_ int __child_raise_win_by_x(int pid, void *priv)
437 // warning: unused parameter
440 return x_util_raise_win(pid);
443 _static_ int __raise_win_by_x(int pid)
446 if (x_util_raise_win(pid) == 0)
449 /* support app launched by shell script*/
451 _D("X raise failed. try to find first child & raise it - c:%d p:%d\n",
456 if (__proc_iter_pgid(pgid, __child_raise_win_by_x, NULL) < 0)
462 _static_ int __send_to_sigkill(int pid)
470 if (killpg(pgid, SIGKILL) < 0)
476 _static_ int __term_app(int pid)
480 (pid, APP_TERM_BY_PID, (unsigned char *)&dummy, sizeof(int)) < 0) {
481 _D("terminate packet send error - use SIGKILL");
482 if (__send_to_sigkill(pid) < 0) {
483 _E("fail to killing - %d\n", pid);
491 _static_ int __resume_app(int pid)
496 __app_send_raw(pid, APP_RESUME_BY_PID, (unsigned char *)&dummy,
499 _E("resume packet timeout error");
501 _D("resume packet send error - use raise win");
502 if (__raise_win_by_x(pid) < 0) {
503 _E("raise failed - %d resume fail\n", pid);
504 _E("we will term the app - %d\n", pid);
505 __send_to_sigkill(pid);
515 static int __get_caller_pid(bundle *kb)
520 pid_str = bundle_get_val(kb, AUL_K_ORG_CALLER_PID);
524 pid_str = bundle_get_val(kb, AUL_K_CALLER_PID);
536 _static_ int __foward_cmd(int cmd, bundle *kb, int cr_pid)
539 char tmp_pid[MAX_PID_STR_BUFSZ];
544 if ((pid = __get_caller_pid(kb)) < 0)
547 snprintf(tmp_pid, MAX_PID_STR_BUFSZ, "%d", cr_pid);
549 bundle_add(kb, AUL_K_CALLEE_PID, tmp_pid);
551 bundle_encode(kb, &kb_data, &datalen);
552 if ((res = __app_send_raw(pid, cmd, kb_data, datalen)) < 0)
560 _static_ void __real_send(int clifd, int ret)
562 if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) {
563 if (errno == EPIPE) {
564 _E("send failed due to EPIPE.\n");
566 _E("send fail to client");
572 _static_ void __send_result_to_caller(int clifd, int ret)
576 int cmdline_changed = 0;
577 int cmdline_exist = 0;
583 __real_send(clifd, ret);
586 /* check normally was launched?*/
589 cmdline = __proc_get_cmdline_bypid(ret);
590 if (cmdline == NULL) {
591 _E("error founded when being launched with %d", ret);
593 } else if (strcmp(cmdline, launchpad_cmdline)) {
602 _D("-- now wait to change cmdline --");
603 usleep(50 * 1000); /* 50ms sleep*/
605 } while (wait_count <= 20); /* max 50*20ms will be sleep*/
607 if ((!cmdline_exist) && (!cmdline_changed)) {
608 __real_send(clifd, -1); /* abnormally launched*/
612 if (!cmdline_changed)
613 _E("process launched, but cmdline not changed");
615 __real_send(clifd, ret);
619 static app_info_from_db *_get_app_info_from_bundle_by_pkgname(
620 const char *pkgname, bundle *kb)
622 app_info_from_db *menu_info;
624 menu_info = calloc(1, sizeof(app_info_from_db));
625 if (menu_info == NULL) {
629 menu_info->pkg_name = strdup(pkgname);
630 menu_info->app_path = strdup(bundle_get_val(kb, AUL_K_EXEC));
631 if (menu_info->app_path != NULL)
632 menu_info->original_app_path = strdup(menu_info->app_path);
633 menu_info->pkg_type = strdup(bundle_get_val(kb, AUL_K_PACKAGETYPE));
634 menu_info->hwacc = strdup(bundle_get_val(kb, AUL_K_HWACC));
636 if (!_get_app_path(menu_info)) {
637 _free_app_info_from_db(menu_info);
644 _static_ void __launchpad_main_loop(int main_fd)
647 app_pkt_t *pkt = NULL;
648 app_info_from_db *menu_info = NULL;
650 const char *pkg_name = NULL;
651 const char *app_path = NULL;
655 int is_real_launch = 0;
657 char sock_path[UNIX_PATH_MAX] = {0,};
659 pkt = __app_recv_raw(main_fd, &clifd, &cr);
661 _D("packet is NULL");
665 kb = bundle_decode(pkt->data, pkt->len);
667 _D("bundle decode error");
672 PERF("packet processing start");
674 pkg_name = bundle_get_val(kb, AUL_K_PKG_NAME);
675 _D("pkg name : %s\n", pkg_name);
677 menu_info = _get_app_info_from_bundle_by_pkgname(pkg_name, kb);
678 if (menu_info == NULL) {
679 _D("such pkg no found");
683 app_path = _get_app_path(menu_info);
684 if(app_path == NULL) {
685 _E("app_path is NULL");
688 if (app_path[0] != '/') {
689 _D("app_path is not absolute path");
693 __modify_bundle(kb, cr.pid, menu_info, pkt->cmd);
694 pkg_name = _get_pkgname(menu_info);
696 PERF("get package information & modify bundle done");
702 _E("lock up test log(no error) : fork done");
706 __signal_unset_sigchld();
709 snprintf(sock_path, UNIX_PATH_MAX, "%s/%d", AUL_SOCK_PREFIX, getpid());
712 PERF("prepare exec - first done");
713 _E("lock up test log(no error) : prepare exec - first done");
715 if (__prepare_exec(pkg_name, app_path,
716 menu_info, kb) < 0) {
717 _E("preparing work fail to launch - "
718 "can not launch %s\n", pkg_name);
722 PERF("prepare exec - second done");
723 _E("lock up test log(no error) : prepare exec - second done");
725 __real_launch(app_path, kb);
729 _D("==> real launch pid : %d %s\n", pid, app_path);
734 __send_result_to_caller(clifd, pid);
737 if (is_real_launch) {
739 __signal_block_sigchld();
740 __send_app_launch_signal(pid);
741 __signal_unblock_sigchld();
745 if (menu_info != NULL)
746 _free_app_info_from_db(menu_info);
753 /* Active Flusing for Daemon */
754 if (initialized > AUL_POLL_CNT) {
755 sqlite3_release_memory(SQLITE_FLUSH_MAX);
762 _static_ int __launchpad_pre_init(int argc, char **argv)
769 /* get my(launchpad) command line*/
770 launchpad_cmdline = __proc_get_cmdline_bypid(getpid());
771 if (launchpad_cmdline == NULL) {
772 _E("launchpad cmdline fail to get");
775 _D("launchpad cmdline = %s", launchpad_cmdline);
777 /* create launchpad sock */
778 fd = __create_server_sock(WRT_LAUNCHPAD_PID);
780 _E("server sock error");
784 __preload_init(argc, argv);
786 __preload_init_for_wrt();
788 __preexec_init(argc, argv);
793 _static_ int __launchpad_post_init()
795 /* Setting this as a global variable to keep track
796 of launchpad poll cnt */
797 /* static int initialized = 0;*/
804 if (__signal_set_sigchld() < 0)
812 int main(int argc, char **argv)
815 struct pollfd pfds[POLLFD_MAX];
818 /* init without concerning X & EFL*/
819 main_fd = __launchpad_pre_init(argc, argv);
821 _E("launchpad pre init failed");
825 pfds[0].fd = main_fd;
826 pfds[0].events = POLLIN;
830 if (poll(pfds, POLLFD_MAX, -1) < 0)
833 /* init with concerning X & EFL (because of booting
835 if (__launchpad_post_init() < 0) {
836 _E("launcpad post init failed");
840 for (i = 0; i < POLLFD_MAX; i++) {
841 if ((pfds[i].revents & POLLIN) != 0) {
842 __launchpad_main_loop(pfds[i].fd);