2 * Copyright (c) 2015 - 2016 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.
22 #include <sys/types.h>
25 #include <sys/xattr.h>
26 #include <sys/socket.h>
31 #include <bundle_internal.h>
32 #ifdef _APPFW_FEATURE_SOCKET_ACTIVATION
33 #include <systemd/sd-daemon.h>
34 #endif /* _APPFW_FEATURE_SOCKET_ACTIVATION */
37 #include "debug_util.h"
40 #define MAX_PATH_LEN 1024
41 #define MAX_CMD_BUFSZ 1024
42 #define PATH_TMP "/tmp"
43 #define PATH_DATA "/data"
44 #define AUL_PKT_HEADER_SIZE (sizeof(int) + sizeof(int) + sizeof(int))
46 static void __set_sock_option(int fd, int cli)
49 struct timeval tv = { 5, 200 * 1000 }; /* 5.2 sec */
51 size = AUL_SOCK_MAXBUFF;
52 setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
53 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
55 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
58 #ifdef _APPFW_FEATURE_SOCKET_ACTIVATION
59 static int __create_sock_activation(void)
63 listen_fds = sd_listen_fds(0);
65 return SD_LISTEN_FDS_START;
66 else if (listen_fds > 1)
67 _E("Too many file descriptors received.");
69 _E("There is no socket stream");
73 #endif /* _APPFW_FEATURE_SOCKET_ACTIVATION */
75 static int __create_server_socket(void)
77 struct sockaddr_un saddr;
80 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
81 /* support above version 2.6.27 */
83 if (errno == EINVAL) {
84 fd = socket(AF_UNIX, SOCK_STREAM, 0);
86 _E("second chance - socket create error");
95 memset(&saddr, 0, sizeof(saddr));
96 saddr.sun_family = AF_UNIX;
97 snprintf(saddr.sun_path, sizeof(saddr.sun_path),
98 "%s/%d/.debug-launchpad-sock",
99 SOCKET_PATH, getuid());
100 unlink(saddr.sun_path);
102 if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
108 if (chmod(saddr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
109 /* Flawfinder: ignore */
110 _E("Failed to change the socket permission");
115 __set_sock_option(fd, 0);
117 if (listen(fd, 128) == -1) {
126 int _create_server_sock(void)
130 #ifdef _APPFW_FEATURE_SOCKET_ACTIVATION
131 fd = __create_sock_activation();
132 #endif /* _APPFW_FEATURE_SOCKET_ACTIAVTION */
134 fd = __create_server_socket();
136 _E("server sock error %d", fd);
144 app_pkt_t *_recv_pkt_raw(int fd, int *clifd, struct ucred *cr)
148 struct sockaddr_un aul_addr = {0, };
150 app_pkt_t *pkt = NULL;
151 int cl = sizeof(struct ucred);
152 unsigned char buf[AUL_SOCK_MAXBUFF];
157 sun_size = sizeof(struct sockaddr_un);
159 *clifd = accept(fd, (struct sockaddr *)&aul_addr,
160 (socklen_t *)&sun_size);
167 if (getsockopt(*clifd, SOL_SOCKET, SO_PEERCRED, cr,
168 (socklen_t *)&cl) < 0) {
169 _E("peer information error");
174 __set_sock_option(*clifd, 1);
177 /* receive header(cmd, datalen) */
178 len = recv(*clifd, buf, AUL_PKT_HEADER_SIZE, 0);
183 if (len < AUL_PKT_HEADER_SIZE) {
188 memcpy(&cmd, buf, sizeof(int));
189 memcpy(&datalen, buf + sizeof(int), sizeof(int));
190 memcpy(&opt, buf + sizeof(int) + sizeof(int), sizeof(int));
192 /* allocate for a null byte */
193 pkt = (app_pkt_t *)calloc(1, AUL_PKT_HEADER_SIZE + datalen + 1);
203 while (len != pkt->len) {
204 ret = recv(*clifd, pkt->data + len, pkt->len - len, 0);
206 _E("recv error %d %d", len, pkt->len);
212 _D("recv len %d %d", len, pkt->len);
218 static char *__appinfo_get_app_path(appinfo_t *appinfo)
224 if (appinfo == NULL || appinfo->app_path == NULL)
227 while (appinfo->app_path[i] != 0) {
228 if (appinfo->app_path[i] == ' '
229 || appinfo->app_path[i] == '\t') {
238 free(appinfo->app_path);
239 appinfo->app_path = NULL;
240 } else if (path_len > 0) {
241 tmp_app_path = (char *)malloc(sizeof(char) * (path_len + 1));
242 if (tmp_app_path == NULL)
245 snprintf(tmp_app_path, path_len + 1, "%s", appinfo->app_path);
246 free(appinfo->app_path);
247 appinfo->app_path = tmp_app_path;
250 return appinfo->app_path;
253 appinfo_t *_appinfo_create(bundle *kb)
258 appinfo = (appinfo_t *)calloc(1, sizeof(appinfo_t));
262 ptr = bundle_get_val(kb, AUL_K_APPID);
264 appinfo->appid = strdup(ptr);
265 ptr = bundle_get_val(kb, AUL_K_PACKAGETYPE);
267 appinfo->pkg_type = strdup(ptr);
268 ptr = bundle_get_val(kb, AUL_K_HWACC);
270 appinfo->hwacc = strdup(ptr);
271 ptr = bundle_get_val(kb, AUL_K_PKGID);
273 appinfo->debug_appid = strdup(ptr);
274 ptr = bundle_get_val(kb, AUL_K_TASKMANAGE);
276 appinfo->taskmanage = strdup(ptr);
277 ptr = bundle_get_val(kb, AUL_K_COMP_TYPE);
279 appinfo->comp_type = strdup(ptr);
280 ptr = bundle_get_val(kb, AUL_K_EXEC);
282 appinfo->app_path = strdup(ptr);
283 if (appinfo->app_path)
284 appinfo->original_app_path = strdup(appinfo->app_path);
286 if (__appinfo_get_app_path(appinfo) == NULL) {
287 _appinfo_free(appinfo);
294 void _appinfo_free(appinfo_t *appinfo)
300 free(appinfo->appid);
301 if (appinfo->app_path)
302 free(appinfo->app_path);
303 if (appinfo->original_app_path)
304 free(appinfo->original_app_path);
305 if (appinfo->pkg_type)
306 free(appinfo->pkg_type);
308 free(appinfo->hwacc);
309 if (appinfo->taskmanage)
310 free(appinfo->taskmanage);
311 if (appinfo->debug_appid)
312 free(appinfo->debug_appid);
313 if (appinfo->comp_type)
314 free(appinfo->comp_type);
319 static int __parse_app_path(const char *arg, char *out, int out_size)
323 char *start_out = out;
325 if (arg == NULL || out == NULL)
328 for (i = 0; out_size > 1; i++) {
352 case 2: /* escape start */
367 case 4: /* character escape */
378 if (out != start_out) {
387 return -1; /* error */
388 case 7: /* terminate */
405 void _modify_bundle(bundle *kb, int caller_pid, appinfo_t *appinfo, int cmd)
408 char exe[MAX_PATH_LEN];
413 bundle_del(kb, AUL_K_APPID);
414 bundle_del(kb, AUL_K_EXEC);
415 bundle_del(kb, AUL_K_PACKAGETYPE);
416 bundle_del(kb, AUL_K_HWACC);
417 bundle_del(kb, AUL_K_PKGID);
418 bundle_del(kb, AUL_K_TASKMANAGE);
419 bundle_del(kb, AUL_K_COMP_TYPE);
421 /* Parse app_path to retrieve default bundle */
422 if (cmd == PAD_CMD_LAUNCH) {
423 ptr = appinfo->original_app_path;
424 flag = __parse_app_path(ptr, exe, sizeof(exe));
427 SECURE_LOGD("parsing app_path: EXEC - %s", exe);
430 flag = __parse_app_path(ptr, key, sizeof(key));
435 flag = __parse_app_path(ptr, value,
441 /* bundle_del(kb, key); */
442 bundle_add(kb, key, value);
444 } else if (flag == 0) {
445 _D("parsing app_path: No arguments");
447 _D("parsing app_path: Invalid argument");
453 static char *__get_libdir(const char *path)
459 path_dup = strdup(path);
460 if (path_dup == NULL)
463 ptr = strrchr(path_dup, '/');
466 snprintf(buf, sizeof(buf), "%s/../lib/", path_dup);
469 if (access(buf, F_OK) == -1)
475 static void __set_sdk_env(const char *appid, const char *value)
477 char buf[MAX_LOCAL_BUFSZ];
480 _D("key: %s / value: %s", AUL_K_SDK, value);
481 /* http://gcc.gnu.org/onlinedocs/gcc/Cross_002dprofiling.html*/
482 /* GCOV_PREFIX contains the prefix to add to the absolute paths */
483 /* in the object file. Prefix can be absolute, or relative.*/
484 /* The default is no prefix. */
485 /* GCOV_PREFIX_STRIP indicates the how many initial directory names */
486 /* to stripoff the hardwired absolute paths. Default value is 0. */
487 if (strncmp(value, SDK_CODE_COVERAGE, strlen(value)) == 0) {
488 token = strrchr(appid, '.');
493 snprintf(buf, sizeof(buf), PATH_TMP"/%s"PATH_DATA, token);
494 setenv("GCOV_PREFIX", buf, 1);
495 setenv("GCOV_PREFIX_STRIP", "0", 1);
499 void _set_env(appinfo_t *appinfo, bundle *kb)
502 const char **str_array = NULL;
507 setenv("PKG_NAME", appinfo->appid, 1);
509 str = bundle_get_val(kb, AUL_K_STARTTIME);
511 setenv("APP_START_TIME", str, 1);
513 setenv("HWACC", appinfo->hwacc, 1);
514 if (appinfo->taskmanage)
515 setenv("TASKMANAGE", appinfo->taskmanage, 1);
517 str = bundle_get_val(kb, AUL_K_WAYLAND_DISPLAY);
519 setenv("WAYLAND_DISPLAY", str, 1);
521 str = bundle_get_val(kb, AUL_K_WAYLAND_WORKING_DIR);
523 setenv("XDG_RUNTIME_DIR", str, 1);
525 str = bundle_get_val(kb, AUL_K_API_VERSION);
527 setenv("TIZEN_API_VERSION", str, 1);
529 str = bundle_get_val(kb, AUL_K_ROOT_PATH);
531 setenv("AUL_ROOT_PATH", str, 1);
533 libdir = __get_libdir(appinfo->app_path);
535 setenv("LD_LIBRARY_PATH", libdir, 1);
539 if (bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
540 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
542 str = bundle_get_val(kb, AUL_K_SDK);
549 for (i = 0; i < len; i++)
550 __set_sdk_env(appinfo->appid, str_array[i]);
553 static char **__add_arg(bundle *kb, char **argv, int *margc, const char *key)
555 const char *str = NULL;
556 const char **str_array = NULL;
559 char **new_argv = NULL;
561 if (bundle_get_type(kb, key) & BUNDLE_TYPE_ARRAY) {
562 str_array = bundle_get_str_array(kb, key, &len);
564 str = bundle_get_val(kb, key);
572 if (strncmp(key, DLP_K_DEBUG_ARG, strlen(key)) == 0
573 || strncmp(key, DLP_K_VALGRIND_ARG, strlen(key)) == 0) {
574 new_argv = (char **)realloc(argv,
575 sizeof(char *) * (*margc + len + 2));
576 if (new_argv == NULL) {
577 _E("Failed to realloc (key: %s)", key);
581 for (i = *margc + len + 1; i - (len + 1) >= 0; i--)
582 new_argv[i] = new_argv[i - (len + 1)];
584 /* need to add new_argv[0] */
585 for (i = 0; i < len; i++)
586 new_argv[1 + i] = strdup(str_array[i]);
588 len++; /* gdbserver or valgrind */
589 } else if (strncmp(key, DLP_K_ATTACH_ARG, strlen(key)) == 0) {
590 new_argv = (char **)malloc((len + 2) * sizeof(char *));
591 if (new_argv == NULL) {
592 _E("Failed to malloc (key: %s)", key);
596 for (i = 0; i < len; i++)
597 new_argv[1 + i] = strdup(str_array[i]);
602 new_argv = (char **)realloc(argv,
603 sizeof(char *) * (*margc + len + 1));
604 if (new_argv == NULL) {
605 _E("Failed to realloc (key: %s)", key);
609 for (i = 0; i < len; i++)
610 new_argv[*margc + i] = strdup(str_array[i]);
613 new_argv[*margc + len] = NULL;
616 if (strncmp(key, DLP_K_DEBUG_ARG, strlen(key)) == 0
617 || strncmp(key, DLP_K_VALGRIND_ARG, strlen(key)) == 0) {
618 new_argv = (char **)realloc(argv,
619 sizeof(char *) * (*margc + 2));
620 if (new_argv == NULL) {
621 _E("Failed to realloc (key: %s)", key);
625 for (i = *margc + 1; i - 1 >= 0; i--)
626 new_argv[i] = new_argv[i - 1];
628 /* need to add new_argv[0] */
633 if (new_argv == NULL)
639 char **_create_argc_argv(bundle *kb, int *margc, const char *app_path)
642 char **new_argv = NULL;
645 char buf[MAX_LOCAL_BUFSZ];
647 const char **str_array = NULL;
651 argc = bundle_export_to_argv(kb, &argv);
653 argv[0] = strdup(app_path);
655 _E("bundle_export_to_argv() is failed.");
659 if (bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
660 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
662 str = bundle_get_val(kb, AUL_K_SDK);
669 for (i = 0; i < len; i++) {
670 if (str_array[i] == NULL)
673 if (strncmp(str_array[i], SDK_DEBUG,
674 strlen(str_array[i])) == 0) {
677 snprintf(buf, sizeof(buf), "%s.exe", app_path);
678 /* this code is added because core app don't have '.exe' excutable */
679 /* if '.exe' not exist then use app_path */
680 if (access(buf, F_OK) != 0)
681 argv[0] = strdup(app_path);
683 argv[0] = strdup(buf);
685 path = bundle_get_val(kb, DLP_K_GDBSERVER_PATH);
687 _E("Failed to get gdbserver path");
690 bundle_free_exported_argv(argc, &argv);
694 new_argv = __add_arg(kb, argv, &argc, DLP_K_DEBUG_ARG);
695 new_argv[0] = strdup(path);
697 } else if (strncmp(str_array[i], SDK_VALGRIND,
698 strlen(str_array[i])) == 0) {
699 path = bundle_get_val(kb, DLP_K_VALGRIND_PATH);
701 _E("Failed to get valgrind path");
704 bundle_free_exported_argv(argc, &argv);
708 new_argv = __add_arg(kb, argv, &argc,
710 new_argv[0] = strdup(path);
712 } else if (strncmp(str_array[i], SDK_UNIT_TEST,
713 strlen(str_array[i])) == 0) {
714 new_argv = __add_arg(kb, argv, &argc,
715 DLP_K_UNIT_TEST_ARG);
717 } else if (strncmp(str_array[i], SDK_ATTACH,
718 strlen(str_array[i])) == 0) {
721 bundle_free_exported_argv(argc, &argv);
723 path = bundle_get_val(kb, DLP_K_GDBSERVER_PATH);
725 _E("Failed to get gdbserver path");
728 new_argv = __add_arg(kb, argv, &argc, DLP_K_ATTACH_ARG);
729 new_argv[0] = strdup(path);
739 static int __read_proc(const char *path, char *buf, int size)
744 if (buf == NULL || path == NULL)
747 fd = open(path, O_RDONLY);
751 ret = read(fd, buf, size - 1);
763 int _proc_check_cmdline_bypid(int pid)
765 char buf[MAX_CMD_BUFSZ];
768 snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
769 ret = __read_proc(buf, buf, sizeof(buf));
773 _D("cmdline: %s", buf);