2 * Copyright (c) 2015 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.
24 #include <sys/prctl.h>
25 #include <sys/socket.h>
28 #include <sys/types.h>
30 #include <sys/signalfd.h>
31 #include <linux/limits.h>
35 #include <bundle_internal.h>
38 #include "signal_util.h"
39 #include "security_util.h"
40 #include "file_util.h"
41 #include "debug_util.h"
45 #define AUL_PR_NAME 16
47 static int __real_send(int clifd, int ret)
49 if (send(clifd, &ret, sizeof(int), MSG_NOSIGNAL) < 0) {
51 _E("send failed due to EPIPE.\n");
56 _E("send fail to client");
64 static void __send_result_to_caller(int clifd, int ret)
68 _W("Check app launching");
74 _E("launching failed");
75 __real_send(clifd, ret);
79 res = _proc_check_cmdline_bypid(ret);
81 _E("The app process might be terminated while we are wating %d", ret);
82 __real_send(clifd, -1); /* abnormally launched */
86 if (__real_send(clifd, ret) < 0) {
87 if (kill(ret, SIGKILL) == -1)
88 _E("Failed to send SIGKILL: %d", errno);
94 static int __prepare_exec(const char *appid, const char *app_path,
95 appinfo_t *appinfo, bundle *kb)
98 char process_name[AUL_PR_NAME];
101 /* Set new session ID & new process group ID */
102 /* In linux, child can set new session ID without check permission */
106 _D("appid: %s / pkg_type: %s / app_path: %s",
107 appid, appinfo->pkg_type, app_path);
108 if ((ret = _set_access(appid)) != 0) {
109 _E("Failed to set privileges - check your package's credential: %d", ret);
113 /* SET DUMPABLE - for coredump */
114 prctl(PR_SET_DUMPABLE, 1);
116 /* SET PROCESS NAME */
117 if (app_path == NULL) {
118 _D("app_path should not be NULL - check menu db");
122 file_name = strrchr(app_path, '/') + 1;
123 if (file_name == NULL) {
124 _D("can't locate file name to execute");
128 memset(process_name, '\0', AUL_PR_NAME);
129 snprintf(process_name, AUL_PR_NAME, "%s", file_name);
130 prctl(PR_SET_NAME, process_name);
133 _set_env(appinfo, kb);
138 static int __prepare_fork(bundle *kb, const char *appid)
141 const char **str_array = NULL;
144 if (bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
145 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
146 if (str_array == NULL)
149 str = bundle_get_val(kb, AUL_K_SDK);
156 _prepare_debug_tool(kb, appid, str_array, len);
161 static int __get_caller_pid(bundle *kb)
166 str = bundle_get_val(kb, AUL_K_ORG_CALLER_PID);
170 str = bundle_get_val(kb, AUL_K_CALLER_PID);
182 static int __redirect_stdfds(int caller_pid)
189 snprintf(buf, sizeof(buf), "/proc/%d/fd/1", caller_pid);
190 fd = open(buf, O_WRONLY);
192 _E("Failed to open caller(%d) stdout", caller_pid);
200 snprintf(buf, sizeof(buf), "/proc/%d/fd/2", caller_pid);
201 fd = open(buf, O_WRONLY);
203 _E("Failed to open caller(%d) stderr", caller_pid);
213 static int __normal_fork_exec(int argc, char **argv)
215 _D("start real fork and exec\n");
217 if (execv(argv[0], argv) < 0) { /* Flawfinder: ignore */
219 _E("such a file is no executable - %s", argv[0]);
221 _E("unknown executable error - %s", argv[0]);
230 static void __real_launch(const char *app_path, bundle *kb)
236 app_argv = _create_argc_argv(kb, &app_argc, app_path);
237 if (app_argv == NULL)
240 for (i = 0; i < app_argc; i++)
241 _D("input argument %d : %s##", i, app_argv[i]);
243 PERF("setup argument done");
245 __normal_fork_exec(app_argc, app_argv);
248 static int __start_process(const char *appid, const char *app_path,
249 bundle *kb, appinfo_t *appinfo)
251 char sock_path[PATH_MAX];
256 if (__prepare_fork(kb, appinfo->debug_appid) < 0)
262 _D("lock up test log(no error): fork done");
264 _signal_unblock_sigchld();
267 max_fd = sysconf(_SC_OPEN_MAX);
268 for (iter_fd = 3; iter_fd <= max_fd; iter_fd++)
271 snprintf(sock_path, sizeof(sock_path), "%s/%d/%d",
272 SOCKET_PATH, getuid(), getpid());
275 if (__redirect_stdfds(__get_caller_pid(kb)))
276 _E("Failed to redirect caller fds");
278 PERF("prepare exec - fisrt done");
279 _D("lock up test log(no error): prepare exec - first done");
281 if (__prepare_exec(appid, app_path, appinfo, kb) < 0) {
282 _E("preparing work fail to launch - can not launch %s", appid);
286 PERF("prepare exec - second done");
287 _D("lock up test log(no error): prepare exec - second done");
288 __real_launch(app_path, kb);
293 _D("==> real launch pid: %d %s", pid, app_path);
298 static gboolean __handle_sigchld(gpointer data)
300 GPollFD *gpollfd = (GPollFD *)data;
301 int fd = gpollfd->fd;
302 struct signalfd_siginfo siginfo;
306 s = read(fd, &siginfo, sizeof(struct signalfd_siginfo));
310 if (s != sizeof(struct signalfd_siginfo)) {
311 _E("error reading sigchld info");
315 _debug_launchpad_sigchld(&siginfo);
321 static gboolean __handle_launch_event(gpointer data)
323 GPollFD *gpollfd = (GPollFD *)data;
324 int fd = gpollfd->fd;
326 app_pkt_t *pkt = NULL;
327 appinfo_t *appinfo = NULL;
328 const char *app_path = NULL;
333 pkt = _recv_pkt_raw(fd, &clifd, &cr);
335 _E("packet is NULL");
339 kb = bundle_decode(pkt->data, pkt->len);
341 _E("bundle decode error");
346 PERF("packet processing start");
348 appinfo = _appinfo_create(kb);
349 if (appinfo == NULL) {
350 _E("_appinfo_create() is failed.");
354 app_path = appinfo->app_path;
355 if (app_path == NULL) {
356 _E("app_path is NULL");
360 if (app_path[0] != '/') {
361 _E("app_path is not absolute path: %s", app_path);
365 _D("appid: %s", appinfo->appid);
366 _D("exec: %s", appinfo->app_path);
367 _D("debug appid: %s", appinfo->debug_appid);
368 _D("hwacc: %s", appinfo->hwacc);
370 _modify_bundle(kb, cr.pid, appinfo, pkt->cmd);
371 if (appinfo->appid == NULL) {
372 _E("unable to get appid from appinfo");
376 PERF("get package infomation & modify bundle done");
378 pid = __start_process(appinfo->appid, app_path, kb, appinfo);
381 __send_result_to_caller(clifd, pid);
384 _send_app_launch_signal(pid, appinfo->appid);
386 _appinfo_free(appinfo);
391 if (_get_valgrind_option())
392 _wait_for_valgrind_output();
397 static gboolean __glib_check(GSource *src)
402 fd_list = src->poll_fds;
404 tmp = (GPollFD *)fd_list->data;
405 if ((tmp->revents & (G_IO_IN | G_IO_PRI | G_IO_HUP | G_IO_NVAL)))
407 fd_list = fd_list->next;
413 static gboolean __glib_dispatch(GSource *src, GSourceFunc callback, gpointer data)
415 return callback(data);
418 static gboolean __glib_prepare(GSource *src, gint *timeout)
423 static GSourceFuncs funcs = {
424 .prepare = __glib_prepare,
425 .check = __glib_check,
426 .dispatch = __glib_dispatch,
430 static int __poll_fd(int fd, GSourceFunc callback)
436 src = g_source_new(&funcs, sizeof(GSource));
442 gpollfd = (GPollFD *)g_malloc(sizeof(GPollFD));
443 if (gpollfd == NULL) {
445 g_source_destroy(src);
450 gpollfd->events = G_IO_IN;
452 g_source_add_poll(src, gpollfd);
453 g_source_set_callback(src, callback, (gpointer)gpollfd, NULL);
454 g_source_set_priority(src, G_PRIORITY_DEFAULT);
456 r = g_source_attach(src, NULL);
459 g_source_destroy(src);
466 static int __init_sigchld_fd(void)
470 fd = _signal_get_sigchld_fd();
472 _E("Failed to get sigchld fd");
476 if (__poll_fd(fd, (GSourceFunc)__handle_sigchld) < 0) {
484 static int __init_debug_launchpad_fd(int argc, char **argv)
491 /* create debug-launchpad socket */
492 fd = _create_server_sock();
494 _E("Failed to create server socket");
498 if (__poll_fd(fd, (GSourceFunc)__handle_launch_event) < 0) {
506 static int __before_loop(int argc, char **argv)
508 if (__init_sigchld_fd() < 0) {
509 _E("Failed to initialize sigchld fd.");
513 if (__init_debug_launchpad_fd(argc, argv) < 0) {
514 _E("Failed to initialize launchpad fd.");
521 int main(int argc, char **argv)
525 loop = g_main_loop_new(NULL, FALSE);
527 _E("Failed to create glib main loop.");
531 if (__before_loop(argc, argv) < 0) {
532 _E("Failed to initiailze debug-launchapd.");
536 g_main_loop_run(loop);