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.
23 #include <sys/types.h>
26 #include <sys/xattr.h>
27 #include <sys/socket.h>
32 #include <bundle_internal.h>
33 #ifdef _APPFW_FEATURE_SOCKET_ACTIVATION
34 #include <systemd/sd-daemon.h>
35 #endif /* _APPFW_FEATURE_SOCKET_ACTIVATION */
38 #include "debug_util.h"
41 #define MAX_PATH_LEN 1024
42 #define MAX_CMD_BUFSZ 1024
43 #define PATH_TMP "/tmp"
44 #define PATH_DATA "/data"
45 #define AUL_PKT_HEADER_SIZE (sizeof(int) + sizeof(int) + sizeof(int))
47 static void __set_sock_option(int fd, int cli)
50 struct timeval tv = { 5, 200 * 1000 }; /* 5.2 sec */
52 size = AUL_SOCK_MAXBUFF;
53 setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
54 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
56 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
59 #ifdef _APPFW_FEATURE_SOCKET_ACTIVATION
60 static int __create_sock_activation(void)
64 listen_fds = sd_listen_fds(0);
66 return SD_LISTEN_FDS_START;
67 else if (listen_fds > 1)
68 _E("Too many file descriptors received.");
70 _E("There is no socket stream");
74 #endif /* _APPFW_FEATURE_SOCKET_ACTIVATION */
76 static int __create_server_socket(bool is_app)
78 struct sockaddr_un saddr;
82 fd = socket(AF_UNIX, SOCK_STREAM, 0);
84 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
85 /* support above version 2.6.27 */
87 if (errno == EINVAL) {
88 fd = socket(AF_UNIX, SOCK_STREAM, 0);
90 _E("second chance - socket create error");
99 memset(&saddr, 0, sizeof(saddr));
100 saddr.sun_family = AF_UNIX;
103 snprintf(saddr.sun_path, sizeof(saddr.sun_path),
105 SOCKET_PATH, getuid(), getpid());
107 snprintf(saddr.sun_path, sizeof(saddr.sun_path),
108 "%s/daemons/%d/.debug-launchpad-sock",
109 SOCKET_PATH, getuid());
111 unlink(saddr.sun_path);
113 if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
119 if (chmod(saddr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
120 /* Flawfinder: ignore */
121 _E("Failed to change the socket permission");
126 __set_sock_option(fd, 0);
128 if (listen(fd, 128) == -1) {
137 int _create_server_sock(void)
141 #ifdef _APPFW_FEATURE_SOCKET_ACTIVATION
142 fd = __create_sock_activation();
143 #endif /* _APPFW_FEATURE_SOCKET_ACTIAVTION */
145 fd = __create_server_socket(false);
147 _E("server sock error %d", fd);
155 app_pkt_t *_recv_pkt_raw(int fd, int *clifd, struct ucred *cr)
159 struct sockaddr_un aul_addr = {0, };
161 app_pkt_t *pkt = NULL;
162 int cl = sizeof(struct ucred);
163 unsigned char buf[AUL_SOCK_MAXBUFF];
168 sun_size = sizeof(struct sockaddr_un);
170 *clifd = accept(fd, (struct sockaddr *)&aul_addr,
171 (socklen_t *)&sun_size);
178 if (getsockopt(*clifd, SOL_SOCKET, SO_PEERCRED, cr,
179 (socklen_t *)&cl) < 0) {
180 _E("peer information error");
185 __set_sock_option(*clifd, 1);
188 /* receive header(cmd, datalen) */
189 len = recv(*clifd, buf, AUL_PKT_HEADER_SIZE, 0);
194 if (len < AUL_PKT_HEADER_SIZE) {
199 memcpy(&cmd, buf, sizeof(int));
200 memcpy(&datalen, buf + sizeof(int), sizeof(int));
201 memcpy(&opt, buf + sizeof(int) + sizeof(int), sizeof(int));
203 /* allocate for a null byte */
204 pkt = (app_pkt_t *)calloc(1, AUL_PKT_HEADER_SIZE + datalen + 1);
214 while (len != pkt->len) {
215 ret = recv(*clifd, pkt->data + len, pkt->len - len, 0);
217 _E("recv error %d %d", len, pkt->len);
223 _D("recv len %d %d", len, pkt->len);
229 static char *__appinfo_get_app_path(appinfo_t *appinfo)
235 if (appinfo == NULL || appinfo->app_path == NULL)
238 while (appinfo->app_path[i] != 0) {
239 if (appinfo->app_path[i] == ' '
240 || appinfo->app_path[i] == '\t') {
249 free(appinfo->app_path);
250 appinfo->app_path = NULL;
251 } else if (path_len > 0) {
252 tmp_app_path = (char *)malloc(sizeof(char) * (path_len + 1));
253 if (tmp_app_path == NULL)
256 snprintf(tmp_app_path, path_len + 1, "%s", appinfo->app_path);
257 free(appinfo->app_path);
258 appinfo->app_path = tmp_app_path;
261 return appinfo->app_path;
264 appinfo_t *_appinfo_create(bundle *kb)
269 appinfo = (appinfo_t *)calloc(1, sizeof(appinfo_t));
273 ptr = bundle_get_val(kb, AUL_K_APPID);
275 appinfo->appid = strdup(ptr);
276 ptr = bundle_get_val(kb, AUL_K_PACKAGETYPE);
278 appinfo->pkg_type = strdup(ptr);
279 ptr = bundle_get_val(kb, AUL_K_HWACC);
281 appinfo->hwacc = strdup(ptr);
282 ptr = bundle_get_val(kb, AUL_K_PKGID);
284 appinfo->debug_appid = strdup(ptr);
285 ptr = bundle_get_val(kb, AUL_K_TASKMANAGE);
287 appinfo->taskmanage = strdup(ptr);
288 ptr = bundle_get_val(kb, AUL_K_COMP_TYPE);
290 appinfo->comp_type = strdup(ptr);
291 ptr = bundle_get_val(kb, AUL_K_EXEC);
293 appinfo->app_path = strdup(ptr);
294 if (appinfo->app_path)
295 appinfo->original_app_path = strdup(appinfo->app_path);
297 if (__appinfo_get_app_path(appinfo) == NULL) {
298 _appinfo_free(appinfo);
305 void _appinfo_free(appinfo_t *appinfo)
311 free(appinfo->appid);
312 if (appinfo->app_path)
313 free(appinfo->app_path);
314 if (appinfo->original_app_path)
315 free(appinfo->original_app_path);
316 if (appinfo->pkg_type)
317 free(appinfo->pkg_type);
319 free(appinfo->hwacc);
320 if (appinfo->taskmanage)
321 free(appinfo->taskmanage);
322 if (appinfo->debug_appid)
323 free(appinfo->debug_appid);
324 if (appinfo->comp_type)
325 free(appinfo->comp_type);
330 static int __parse_app_path(const char *arg, char *out, int out_size)
334 char *start_out = out;
336 if (arg == NULL || out == NULL)
339 for (i = 0; out_size > 1; i++) {
363 case 2: /* escape start */
378 case 4: /* character escape */
389 if (out != start_out) {
398 return -1; /* error */
399 case 7: /* terminate */
416 void _modify_bundle(bundle *kb, int caller_pid, appinfo_t *appinfo, int cmd)
419 char exe[MAX_PATH_LEN];
424 bundle_del(kb, AUL_K_APPID);
425 bundle_del(kb, AUL_K_EXEC);
426 bundle_del(kb, AUL_K_PACKAGETYPE);
427 bundle_del(kb, AUL_K_HWACC);
428 bundle_del(kb, AUL_K_PKGID);
429 bundle_del(kb, AUL_K_TASKMANAGE);
430 bundle_del(kb, AUL_K_COMP_TYPE);
432 /* Parse app_path to retrieve default bundle */
433 if (cmd == PAD_CMD_LAUNCH) {
434 ptr = appinfo->original_app_path;
435 flag = __parse_app_path(ptr, exe, sizeof(exe));
438 SECURE_LOGD("parsing app_path: EXEC - %s", exe);
441 flag = __parse_app_path(ptr, key, sizeof(key));
446 flag = __parse_app_path(ptr, value,
452 /* bundle_del(kb, key); */
453 bundle_add(kb, key, value);
455 } else if (flag == 0) {
456 _D("parsing app_path: No arguments");
458 _D("parsing app_path: Invalid argument");
464 static char *__get_libdir(const char *path)
470 path_dup = strdup(path);
471 if (path_dup == NULL)
474 ptr = strrchr(path_dup, '/');
477 snprintf(buf, sizeof(buf), "%s/../lib/", path_dup);
480 if (access(buf, F_OK) == -1)
486 static void __set_sdk_env(const char *appid, const char *value)
488 char buf[MAX_LOCAL_BUFSZ];
491 _D("key: %s / value: %s", AUL_K_SDK, value);
492 /* http://gcc.gnu.org/onlinedocs/gcc/Cross_002dprofiling.html*/
493 /* GCOV_PREFIX contains the prefix to add to the absolute paths */
494 /* in the object file. Prefix can be absolute, or relative.*/
495 /* The default is no prefix. */
496 /* GCOV_PREFIX_STRIP indicates the how many initial directory names */
497 /* to stripoff the hardwired absolute paths. Default value is 0. */
498 if (strncmp(value, SDK_CODE_COVERAGE, strlen(value)) == 0) {
499 token = strrchr(appid, '.');
504 snprintf(buf, sizeof(buf), PATH_TMP"/%s"PATH_DATA, token);
505 setenv("GCOV_PREFIX", buf, 1);
506 setenv("GCOV_PREFIX_STRIP", "0", 1);
510 void _set_env(appinfo_t *appinfo, bundle *kb)
513 const char **str_array = NULL;
518 setenv("PKG_NAME", appinfo->appid, 1);
520 str = bundle_get_val(kb, AUL_K_STARTTIME);
522 setenv("APP_START_TIME", str, 1);
524 setenv("HWACC", appinfo->hwacc, 1);
525 if (appinfo->taskmanage)
526 setenv("TASKMANAGE", appinfo->taskmanage, 1);
528 str = bundle_get_val(kb, AUL_K_WAYLAND_DISPLAY);
530 setenv("WAYLAND_DISPLAY", str, 1);
532 str = bundle_get_val(kb, AUL_K_WAYLAND_WORKING_DIR);
534 setenv("XDG_RUNTIME_DIR", str, 1);
536 str = bundle_get_val(kb, AUL_K_API_VERSION);
538 setenv("TIZEN_API_VERSION", str, 1);
540 str = bundle_get_val(kb, AUL_K_ROOT_PATH);
542 setenv("AUL_ROOT_PATH", str, 1);
544 libdir = __get_libdir(appinfo->app_path);
546 setenv("LD_LIBRARY_PATH", libdir, 1);
550 if (bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
551 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
553 str = bundle_get_val(kb, AUL_K_SDK);
560 for (i = 0; i < len; i++)
561 __set_sdk_env(appinfo->appid, str_array[i]);
564 static char **__add_arg(bundle *kb, char **argv, int *margc, const char *key)
566 const char *str = NULL;
567 const char **str_array = NULL;
570 char **new_argv = NULL;
572 if (bundle_get_type(kb, key) & BUNDLE_TYPE_ARRAY) {
573 str_array = bundle_get_str_array(kb, key, &len);
575 str = bundle_get_val(kb, key);
583 if (strncmp(key, DLP_K_DEBUG_ARG, strlen(key)) == 0
584 || strncmp(key, DLP_K_VALGRIND_ARG, strlen(key)) == 0) {
585 new_argv = (char **)realloc(argv,
586 sizeof(char *) * (*margc + len + 2));
587 if (new_argv == NULL) {
588 _E("Failed to realloc (key: %s)", key);
592 for (i = *margc + len + 1; i - (len + 1) >= 0; i--)
593 new_argv[i] = new_argv[i - (len + 1)];
595 /* need to add new_argv[0] */
596 for (i = 0; i < len; i++)
597 new_argv[1 + i] = strdup(str_array[i]);
599 len++; /* gdbserver or valgrind */
600 } else if (strncmp(key, DLP_K_ATTACH_ARG, strlen(key)) == 0) {
601 new_argv = (char **)malloc((len + 2) * sizeof(char *));
602 if (new_argv == NULL) {
603 _E("Failed to malloc (key: %s)", key);
607 for (i = 0; i < len; i++)
608 new_argv[1 + i] = strdup(str_array[i]);
613 new_argv = (char **)realloc(argv,
614 sizeof(char *) * (*margc + len + 1));
615 if (new_argv == NULL) {
616 _E("Failed to realloc (key: %s)", key);
620 for (i = 0; i < len; i++)
621 new_argv[*margc + i] = strdup(str_array[i]);
624 new_argv[*margc + len] = NULL;
627 if (strncmp(key, DLP_K_DEBUG_ARG, strlen(key)) == 0
628 || strncmp(key, DLP_K_VALGRIND_ARG, strlen(key)) == 0) {
629 new_argv = (char **)realloc(argv,
630 sizeof(char *) * (*margc + 2));
631 if (new_argv == NULL) {
632 _E("Failed to realloc (key: %s)", key);
636 for (i = *margc + 1; i - 1 >= 0; i--)
637 new_argv[i] = new_argv[i - 1];
639 /* need to add new_argv[0] */
644 if (new_argv == NULL)
650 char **_create_argc_argv(bundle *kb, int *margc, const char *app_path)
653 char **new_argv = NULL;
656 char buf[MAX_LOCAL_BUFSZ];
658 const char **str_array = NULL;
662 argc = bundle_export_to_argv(kb, &argv);
664 argv[0] = strdup(app_path);
666 _E("bundle_export_to_argv() is failed.");
670 if (bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
671 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
673 str = bundle_get_val(kb, AUL_K_SDK);
680 for (i = 0; i < len; i++) {
681 if (str_array[i] == NULL)
684 if (strncmp(str_array[i], SDK_DEBUG,
685 strlen(str_array[i])) == 0) {
688 snprintf(buf, sizeof(buf), "%s.exe", app_path);
689 /* this code is added because core app don't have '.exe' excutable */
690 /* if '.exe' not exist then use app_path */
691 if (access(buf, F_OK) != 0)
692 argv[0] = strdup(app_path);
694 argv[0] = strdup(buf);
696 path = bundle_get_val(kb, DLP_K_GDBSERVER_PATH);
698 _E("Failed to get gdbserver path");
701 bundle_free_exported_argv(argc, &argv);
705 new_argv = __add_arg(kb, argv, &argc, DLP_K_DEBUG_ARG);
706 new_argv[0] = strdup(path);
708 } else if (strncmp(str_array[i], SDK_VALGRIND,
709 strlen(str_array[i])) == 0) {
710 path = bundle_get_val(kb, DLP_K_VALGRIND_PATH);
712 _E("Failed to get valgrind path");
715 bundle_free_exported_argv(argc, &argv);
719 new_argv = __add_arg(kb, argv, &argc,
721 new_argv[0] = strdup(path);
723 } else if (strncmp(str_array[i], SDK_UNIT_TEST,
724 strlen(str_array[i])) == 0) {
725 new_argv = __add_arg(kb, argv, &argc,
726 DLP_K_UNIT_TEST_ARG);
728 } else if (strncmp(str_array[i], SDK_ATTACH,
729 strlen(str_array[i])) == 0) {
732 bundle_free_exported_argv(argc, &argv);
734 path = bundle_get_val(kb, DLP_K_GDBSERVER_PATH);
736 _E("Failed to get gdbserver path");
739 new_argv = __add_arg(kb, argv, &argc, DLP_K_ATTACH_ARG);
740 new_argv[0] = strdup(path);
750 static int __read_proc(const char *path, char *buf, int size)
755 if (buf == NULL || path == NULL)
758 fd = open(path, O_RDONLY);
762 ret = read(fd, buf, size - 1);
774 int _proc_check_cmdline_bypid(int pid)
776 char buf[MAX_CMD_BUFSZ];
779 snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
780 ret = __read_proc(buf, buf, sizeof(buf));
784 _D("cmdline: %s", buf);
789 void _prepare_listen_sock(void)
794 fd = __create_server_socket(true);
798 snprintf(buf, sizeof(buf), "%d", fd);
799 setenv("AUL_LISTEN_SOCK", buf, 1);