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>
33 #include <bundle_internal.h>
34 #ifdef _APPFW_FEATURE_SOCKET_ACTIVATION
35 #include <systemd/sd-daemon.h>
36 #endif /* _APPFW_FEATURE_SOCKET_ACTIVATION */
39 #include "debug_util.h"
42 #define MAX_PATH_LEN 1024
43 #define MAX_CMD_BUFSZ 1024
44 #define PATH_TMP "/tmp"
45 #define PATH_DATA "/data"
46 #define AUL_PKT_HEADER_SIZE (sizeof(int) + sizeof(int) + sizeof(int))
48 static void __set_sock_option(int fd, int cli)
51 struct timeval tv = { 5, 200 * 1000 }; /* 5.2 sec */
53 size = AUL_SOCK_MAXBUFF;
54 setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
55 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
57 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
60 #ifdef _APPFW_FEATURE_SOCKET_ACTIVATION
61 static int __create_sock_activation(void)
65 listen_fds = sd_listen_fds(0);
67 return SD_LISTEN_FDS_START;
68 else if (listen_fds > 1)
69 _E("Too many file descriptors received.");
71 _E("There is no socket stream");
75 #endif /* _APPFW_FEATURE_SOCKET_ACTIVATION */
77 static int __create_server_socket(bool is_app)
79 struct sockaddr_un saddr;
84 fd = socket(AF_UNIX, SOCK_STREAM, 0);
86 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
87 /* support above version 2.6.27 */
89 if (errno == EINVAL) {
90 fd = socket(AF_UNIX, SOCK_STREAM, 0);
92 _E("second chance - socket create error");
101 memset(&saddr, 0, sizeof(saddr));
102 saddr.sun_family = AF_UNIX;
105 snprintf(saddr.sun_path, sizeof(saddr.sun_path),
107 SOCKET_PATH, getuid(), getpid());
108 ret = mkdir(saddr.sun_path, 0700);
110 if (errno == EEXIST) {
111 if (access(saddr.sun_path, R_OK) != 0) {
112 _E("Failed to access %s directory - %d",
113 saddr.sun_path, errno);
118 _E("Failed to create %s directory - %d",
119 saddr.sun_path, errno);
124 snprintf(saddr.sun_path, sizeof(saddr.sun_path),
125 "%s/apps/%d/%d/.app-sock",
126 SOCKET_PATH, getuid(), getpid());
128 snprintf(saddr.sun_path, sizeof(saddr.sun_path),
129 "%s/daemons/%d/.debug-launchpad-sock",
130 SOCKET_PATH, getuid());
132 unlink(saddr.sun_path);
134 if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
140 if (chmod(saddr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
141 /* Flawfinder: ignore */
142 _E("Failed to change the socket permission");
147 __set_sock_option(fd, 0);
149 if (listen(fd, 128) == -1) {
158 int _create_server_sock(void)
162 #ifdef _APPFW_FEATURE_SOCKET_ACTIVATION
163 fd = __create_sock_activation();
164 #endif /* _APPFW_FEATURE_SOCKET_ACTIAVTION */
166 fd = __create_server_socket(false);
168 _E("server sock error %d", fd);
176 app_pkt_t *_recv_pkt_raw(int fd, int *clifd, struct ucred *cr)
180 struct sockaddr_un aul_addr = {0, };
182 app_pkt_t *pkt = NULL;
183 int cl = sizeof(struct ucred);
184 unsigned char buf[AUL_SOCK_MAXBUFF];
189 sun_size = sizeof(struct sockaddr_un);
191 *clifd = accept(fd, (struct sockaddr *)&aul_addr,
192 (socklen_t *)&sun_size);
199 if (getsockopt(*clifd, SOL_SOCKET, SO_PEERCRED, cr,
200 (socklen_t *)&cl) < 0) {
201 _E("peer information error");
206 __set_sock_option(*clifd, 1);
209 /* receive header(cmd, datalen) */
210 len = recv(*clifd, buf, AUL_PKT_HEADER_SIZE, 0);
215 if (len < AUL_PKT_HEADER_SIZE) {
220 memcpy(&cmd, buf, sizeof(int));
221 memcpy(&datalen, buf + sizeof(int), sizeof(int));
222 memcpy(&opt, buf + sizeof(int) + sizeof(int), sizeof(int));
224 /* allocate for a null byte */
225 pkt = (app_pkt_t *)calloc(1, AUL_PKT_HEADER_SIZE + datalen + 1);
235 while (len != pkt->len) {
236 ret = recv(*clifd, pkt->data + len, pkt->len - len, 0);
238 _E("recv error %d %d", len, pkt->len);
244 _D("recv len %d %d", len, pkt->len);
250 static char *__appinfo_get_app_path(appinfo_t *appinfo)
256 if (appinfo == NULL || appinfo->app_path == NULL)
259 while (appinfo->app_path[i] != 0) {
260 if (appinfo->app_path[i] == ' '
261 || appinfo->app_path[i] == '\t') {
270 free(appinfo->app_path);
271 appinfo->app_path = NULL;
272 } else if (path_len > 0) {
273 tmp_app_path = (char *)malloc(sizeof(char) * (path_len + 1));
274 if (tmp_app_path == NULL)
277 snprintf(tmp_app_path, path_len + 1, "%s", appinfo->app_path);
278 free(appinfo->app_path);
279 appinfo->app_path = tmp_app_path;
282 return appinfo->app_path;
285 appinfo_t *_appinfo_create(bundle *kb)
290 appinfo = (appinfo_t *)calloc(1, sizeof(appinfo_t));
294 ptr = bundle_get_val(kb, AUL_K_APPID);
296 appinfo->appid = strdup(ptr);
297 ptr = bundle_get_val(kb, AUL_K_PACKAGETYPE);
299 appinfo->pkg_type = strdup(ptr);
300 ptr = bundle_get_val(kb, AUL_K_HWACC);
302 appinfo->hwacc = strdup(ptr);
303 ptr = bundle_get_val(kb, AUL_K_PKGID);
305 appinfo->debug_appid = strdup(ptr);
306 ptr = bundle_get_val(kb, AUL_K_TASKMANAGE);
308 appinfo->taskmanage = strdup(ptr);
309 ptr = bundle_get_val(kb, AUL_K_COMP_TYPE);
311 appinfo->comp_type = strdup(ptr);
312 ptr = bundle_get_val(kb, AUL_K_PKGID);
314 appinfo->pkgid = strdup(ptr);
315 ptr = bundle_get_val(kb, AUL_K_EXEC);
317 appinfo->app_path = strdup(ptr);
318 if (appinfo->app_path)
319 appinfo->original_app_path = strdup(appinfo->app_path);
321 if (__appinfo_get_app_path(appinfo) == NULL) {
322 _appinfo_free(appinfo);
329 void _appinfo_free(appinfo_t *appinfo)
335 free(appinfo->appid);
336 if (appinfo->app_path)
337 free(appinfo->app_path);
338 if (appinfo->original_app_path)
339 free(appinfo->original_app_path);
340 if (appinfo->pkg_type)
341 free(appinfo->pkg_type);
343 free(appinfo->hwacc);
344 if (appinfo->taskmanage)
345 free(appinfo->taskmanage);
346 if (appinfo->debug_appid)
347 free(appinfo->debug_appid);
348 if (appinfo->comp_type)
349 free(appinfo->comp_type);
351 free(appinfo->pkgid);
356 static int __parse_app_path(const char *arg, char *out, int out_size)
360 char *start_out = out;
362 if (arg == NULL || out == NULL)
365 for (i = 0; out_size > 1; i++) {
389 case 2: /* escape start */
404 case 4: /* character escape */
415 if (out != start_out) {
424 return -1; /* error */
425 case 7: /* terminate */
442 void _modify_bundle(bundle *kb, int caller_pid, appinfo_t *appinfo, int cmd)
445 char exe[MAX_PATH_LEN];
450 bundle_del(kb, AUL_K_APPID);
451 bundle_del(kb, AUL_K_EXEC);
452 bundle_del(kb, AUL_K_PACKAGETYPE);
453 bundle_del(kb, AUL_K_HWACC);
454 bundle_del(kb, AUL_K_PKGID);
455 bundle_del(kb, AUL_K_TASKMANAGE);
456 bundle_del(kb, AUL_K_COMP_TYPE);
458 /* Parse app_path to retrieve default bundle */
459 if (cmd == PAD_CMD_LAUNCH) {
460 ptr = appinfo->original_app_path;
461 flag = __parse_app_path(ptr, exe, sizeof(exe));
464 SECURE_LOGD("parsing app_path: EXEC - %s", exe);
467 flag = __parse_app_path(ptr, key, sizeof(key));
472 flag = __parse_app_path(ptr, value,
478 /* bundle_del(kb, key); */
479 bundle_add(kb, key, value);
481 } else if (flag == 0) {
482 _D("parsing app_path: No arguments");
484 _D("parsing app_path: Invalid argument");
490 static char *__get_libdir(const char *path)
496 path_dup = strdup(path);
497 if (path_dup == NULL)
500 ptr = strrchr(path_dup, '/');
506 snprintf(buf, sizeof(buf), "%s/../lib/", path_dup);
509 if (access(buf, F_OK) == -1)
515 static void __set_sdk_env(const char *appid, const char *value)
517 char buf[MAX_LOCAL_BUFSZ];
520 _D("key: %s / value: %s", AUL_K_SDK, value);
521 /* http://gcc.gnu.org/onlinedocs/gcc/Cross_002dprofiling.html*/
522 /* GCOV_PREFIX contains the prefix to add to the absolute paths */
523 /* in the object file. Prefix can be absolute, or relative.*/
524 /* The default is no prefix. */
525 /* GCOV_PREFIX_STRIP indicates the how many initial directory names */
526 /* to stripoff the hardwired absolute paths. Default value is 0. */
527 if (strncmp(value, SDK_CODE_COVERAGE, strlen(value)) == 0) {
528 token = strrchr(appid, '.');
533 snprintf(buf, sizeof(buf), PATH_TMP"/%s"PATH_DATA, token);
534 setenv("GCOV_PREFIX", buf, 1);
535 setenv("GCOV_PREFIX_STRIP", "0", 1);
539 void _set_env(appinfo_t *appinfo, bundle *kb)
542 const char **str_array = NULL;
547 setenv("PKG_NAME", appinfo->appid, 1);
549 str = bundle_get_val(kb, AUL_K_STARTTIME);
551 setenv("APP_START_TIME", str, 1);
553 setenv("HWACC", appinfo->hwacc, 1);
554 if (appinfo->taskmanage)
555 setenv("TASKMANAGE", appinfo->taskmanage, 1);
557 setenv("AUL_APPID", appinfo->appid, 1);
559 setenv("AUL_PKGID", appinfo->pkgid, 1);
561 str = bundle_get_val(kb, AUL_K_WAYLAND_DISPLAY);
563 setenv("WAYLAND_DISPLAY", str, 1);
565 str = bundle_get_val(kb, AUL_K_WAYLAND_WORKING_DIR);
567 setenv("XDG_RUNTIME_DIR", str, 1);
569 str = bundle_get_val(kb, AUL_K_API_VERSION);
571 setenv("TIZEN_API_VERSION", str, 1);
573 str = bundle_get_val(kb, AUL_K_ROOT_PATH);
575 setenv("AUL_ROOT_PATH", str, 1);
577 libdir = __get_libdir(appinfo->app_path);
579 setenv("LD_LIBRARY_PATH", libdir, 1);
583 if (bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
584 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
586 str = bundle_get_val(kb, AUL_K_SDK);
593 for (i = 0; i < len; i++)
594 __set_sdk_env(appinfo->appid, str_array[i]);
597 static char **__add_arg(bundle *kb, char **argv, int *margc, const char *key)
599 const char *str = NULL;
600 const char **str_array = NULL;
603 char **new_argv = NULL;
605 if (bundle_get_type(kb, key) & BUNDLE_TYPE_ARRAY) {
606 str_array = bundle_get_str_array(kb, key, &len);
608 str = bundle_get_val(kb, key);
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 + len + 2));
620 if (new_argv == NULL) {
621 _E("Failed to realloc (key: %s)", key);
625 for (i = *margc + len + 1; i - (len + 1) >= 0; i--)
626 new_argv[i] = new_argv[i - (len + 1)];
628 /* need to add new_argv[0] */
629 for (i = 0; i < len; i++)
630 new_argv[1 + i] = strdup(str_array[i]);
632 len++; /* gdbserver or valgrind */
633 } else if (strncmp(key, DLP_K_ATTACH_ARG, strlen(key)) == 0) {
634 new_argv = (char **)malloc((len + 2) * sizeof(char *));
635 if (new_argv == NULL) {
636 _E("Failed to malloc (key: %s)", key);
640 for (i = 0; i < len; i++)
641 new_argv[1 + i] = strdup(str_array[i]);
646 new_argv = (char **)realloc(argv,
647 sizeof(char *) * (*margc + len + 1));
648 if (new_argv == NULL) {
649 _E("Failed to realloc (key: %s)", key);
653 for (i = 0; i < len; i++)
654 new_argv[*margc + i] = strdup(str_array[i]);
657 new_argv[*margc + len] = NULL;
660 if (strncmp(key, DLP_K_DEBUG_ARG, strlen(key)) == 0
661 || strncmp(key, DLP_K_VALGRIND_ARG, strlen(key)) == 0) {
662 new_argv = (char **)realloc(argv,
663 sizeof(char *) * (*margc + 2));
664 if (new_argv == NULL) {
665 _E("Failed to realloc (key: %s)", key);
669 for (i = *margc + 1; i - 1 >= 0; i--)
670 new_argv[i] = new_argv[i - 1];
672 /* need to add new_argv[0] */
677 if (new_argv == NULL)
683 char **_create_argc_argv(bundle *kb, int *margc, const char *app_path)
686 char **new_argv = NULL;
689 char buf[MAX_LOCAL_BUFSZ];
691 const char **str_array = NULL;
695 argc = bundle_export_to_argv(kb, &argv);
697 argv[0] = strdup(app_path);
699 _E("bundle_export_to_argv() is failed.");
703 if (bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
704 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
706 str = bundle_get_val(kb, AUL_K_SDK);
713 for (i = 0; i < len; i++) {
714 if (str_array[i] == NULL)
717 if (strncmp(str_array[i], SDK_DEBUG,
718 strlen(str_array[i])) == 0) {
721 snprintf(buf, sizeof(buf), "%s.exe", app_path);
722 /* this code is added */
723 /* because core app don't have '.exe' excutable */
724 /* if '.exe' not exist then use app_path */
725 if (access(buf, F_OK) != 0)
726 argv[0] = strdup(app_path);
728 argv[0] = strdup(buf);
730 path = bundle_get_val(kb, DLP_K_GDBSERVER_PATH);
732 _E("Failed to get gdbserver path");
735 bundle_free_exported_argv(argc, &argv);
739 new_argv = __add_arg(kb, argv, &argc, DLP_K_DEBUG_ARG);
740 new_argv[0] = strdup(path);
742 } else if (strncmp(str_array[i], SDK_VALGRIND,
743 strlen(str_array[i])) == 0) {
744 path = bundle_get_val(kb, DLP_K_VALGRIND_PATH);
746 _E("Failed to get valgrind path");
749 bundle_free_exported_argv(argc, &argv);
753 new_argv = __add_arg(kb, argv, &argc,
755 new_argv[0] = strdup(path);
757 } else if (strncmp(str_array[i], SDK_UNIT_TEST,
758 strlen(str_array[i])) == 0) {
759 new_argv = __add_arg(kb, argv, &argc,
760 DLP_K_UNIT_TEST_ARG);
762 } else if (strncmp(str_array[i], SDK_ATTACH,
763 strlen(str_array[i])) == 0) {
766 bundle_free_exported_argv(argc, &argv);
768 path = bundle_get_val(kb, DLP_K_GDBSERVER_PATH);
770 _E("Failed to get gdbserver path");
773 new_argv = __add_arg(kb, argv, &argc, DLP_K_ATTACH_ARG);
774 new_argv[0] = strdup(path);
784 static int __delete_dir(const char *path)
787 struct dirent dentry;
788 struct dirent *result = NULL;
800 while (readdir_r(dp, &dentry, &result) == 0 && result) {
801 if (!strcmp(dentry.d_name, ".") || !strcmp(dentry.d_name, ".."))
804 snprintf(buf, sizeof(buf), "%s/%s", path, dentry.d_name);
805 ret = stat(buf, &statbuf);
807 if (S_ISDIR(statbuf.st_mode))
820 int _delete_sock_path(int pid, uid_t uid)
824 snprintf(path, sizeof(path), "/run/aul/apps/%d/%d", uid, pid);
825 if (access(path, F_OK) == 0)
828 if (access(path, F_OK) == 0)
834 int _close_all_fds(void)
837 struct dirent dentry;
838 struct dirent *result = NULL;
842 dp = opendir("/proc/self/fd");
845 max_fd = sysconf(_SC_OPEN_MAX);
846 for (fd = 3; fd < max_fd; fd++)
852 while (readdir_r(dp, &dentry, &result) == 0 && result) {
853 if (!isdigit(dentry.d_name[0]))
856 fd = atoi(dentry.d_name);