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 #include <systemd/sd-daemon.h>
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 static int __create_sock_activation(void)
62 listen_fds = sd_listen_fds(0);
64 return SD_LISTEN_FDS_START;
65 else if (listen_fds > 1)
66 _E("Too many file descriptors received.");
68 _E("There is no socket stream");
73 static int __create_server_socket(bool is_app)
75 struct sockaddr_un saddr;
80 fd = socket(AF_UNIX, SOCK_STREAM, 0);
82 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
83 /* support above version 2.6.27 */
85 if (errno == EINVAL) {
86 fd = socket(AF_UNIX, SOCK_STREAM, 0);
88 _E("second chance - socket create error");
97 memset(&saddr, 0, sizeof(saddr));
98 saddr.sun_family = AF_UNIX;
101 snprintf(saddr.sun_path, sizeof(saddr.sun_path),
103 SOCKET_PATH, getuid(), getpid());
104 ret = mkdir(saddr.sun_path, 0700);
106 if (errno == EEXIST) {
107 if (access(saddr.sun_path, R_OK) != 0) {
108 _E("Failed to access %s directory - %d",
109 saddr.sun_path, errno);
114 _E("Failed to create %s directory - %d",
115 saddr.sun_path, errno);
120 snprintf(saddr.sun_path, sizeof(saddr.sun_path),
121 "%s/apps/%d/%d/.app-sock",
122 SOCKET_PATH, getuid(), getpid());
124 snprintf(saddr.sun_path, sizeof(saddr.sun_path),
125 "%s/daemons/%d/.debug-launchpad-sock",
126 SOCKET_PATH, getuid());
128 unlink(saddr.sun_path);
130 if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
136 if (chmod(saddr.sun_path, (S_IRWXU | S_IRWXG | S_IRWXO)) < 0) {
137 /* Flawfinder: ignore */
138 _E("Failed to change the socket permission");
143 __set_sock_option(fd, 0);
145 if (listen(fd, 128) == -1) {
154 int _create_server_sock(void)
158 fd = __create_sock_activation();
160 fd = __create_server_socket(false);
162 _E("server sock error %d", fd);
170 app_pkt_t *_recv_pkt_raw(int fd, int *clifd, struct ucred *cr)
174 struct sockaddr_un aul_addr = {0, };
176 app_pkt_t *pkt = NULL;
177 int cl = sizeof(struct ucred);
178 unsigned char buf[AUL_SOCK_MAXBUFF];
183 sun_size = sizeof(struct sockaddr_un);
185 *clifd = accept(fd, (struct sockaddr *)&aul_addr,
186 (socklen_t *)&sun_size);
193 if (getsockopt(*clifd, SOL_SOCKET, SO_PEERCRED, cr,
194 (socklen_t *)&cl) < 0) {
195 _E("peer information error");
200 __set_sock_option(*clifd, 1);
203 /* receive header(cmd, datalen) */
204 len = recv(*clifd, buf, AUL_PKT_HEADER_SIZE, 0);
209 if (len < AUL_PKT_HEADER_SIZE) {
214 memcpy(&cmd, buf, sizeof(int));
215 memcpy(&datalen, buf + sizeof(int), sizeof(int));
216 memcpy(&opt, buf + sizeof(int) + sizeof(int), sizeof(int));
218 /* allocate for a null byte */
219 pkt = (app_pkt_t *)calloc(1, AUL_PKT_HEADER_SIZE + datalen + 1);
229 while (len != pkt->len) {
230 ret = recv(*clifd, pkt->data + len, pkt->len - len, 0);
232 _E("recv error %d %d", len, pkt->len);
238 _D("recv len %d %d", len, pkt->len);
244 static char *__appinfo_get_app_path(appinfo_t *appinfo)
250 if (appinfo == NULL || appinfo->app_path == NULL)
253 while (appinfo->app_path[i] != 0) {
254 if (appinfo->app_path[i] == ' '
255 || appinfo->app_path[i] == '\t') {
264 free(appinfo->app_path);
265 appinfo->app_path = NULL;
266 } else if (path_len > 0) {
267 tmp_app_path = (char *)malloc(sizeof(char) * (path_len + 1));
268 if (tmp_app_path == NULL)
271 snprintf(tmp_app_path, path_len + 1, "%s", appinfo->app_path);
272 free(appinfo->app_path);
273 appinfo->app_path = tmp_app_path;
276 return appinfo->app_path;
279 appinfo_t *_appinfo_create(bundle *kb)
284 appinfo = (appinfo_t *)calloc(1, sizeof(appinfo_t));
288 ptr = bundle_get_val(kb, AUL_K_APPID);
290 appinfo->appid = strdup(ptr);
291 ptr = bundle_get_val(kb, AUL_K_PACKAGETYPE);
293 appinfo->pkg_type = strdup(ptr);
294 ptr = bundle_get_val(kb, AUL_K_HWACC);
296 appinfo->hwacc = strdup(ptr);
297 ptr = bundle_get_val(kb, AUL_K_PKGID);
299 appinfo->debug_appid = strdup(ptr);
300 ptr = bundle_get_val(kb, AUL_K_TASKMANAGE);
302 appinfo->taskmanage = strdup(ptr);
303 ptr = bundle_get_val(kb, AUL_K_COMP_TYPE);
305 appinfo->comp_type = strdup(ptr);
306 ptr = bundle_get_val(kb, AUL_K_PKGID);
308 appinfo->pkgid = strdup(ptr);
309 ptr = bundle_get_val(kb, AUL_K_EXEC);
311 appinfo->app_path = strdup(ptr);
312 if (appinfo->app_path)
313 appinfo->original_app_path = strdup(appinfo->app_path);
315 if (__appinfo_get_app_path(appinfo) == NULL) {
316 _appinfo_free(appinfo);
323 void _appinfo_free(appinfo_t *appinfo)
329 free(appinfo->appid);
330 if (appinfo->app_path)
331 free(appinfo->app_path);
332 if (appinfo->original_app_path)
333 free(appinfo->original_app_path);
334 if (appinfo->pkg_type)
335 free(appinfo->pkg_type);
337 free(appinfo->hwacc);
338 if (appinfo->taskmanage)
339 free(appinfo->taskmanage);
340 if (appinfo->debug_appid)
341 free(appinfo->debug_appid);
342 if (appinfo->comp_type)
343 free(appinfo->comp_type);
345 free(appinfo->pkgid);
350 static int __parse_app_path(const char *arg, char *out, int out_size)
354 char *start_out = out;
356 if (arg == NULL || out == NULL)
359 for (i = 0; out_size > 1; i++) {
383 case 2: /* escape start */
398 case 4: /* character escape */
409 if (out != start_out) {
418 return -1; /* error */
419 case 7: /* terminate */
436 void _modify_bundle(bundle *kb, int caller_pid, appinfo_t *appinfo, int cmd)
439 char exe[MAX_PATH_LEN];
444 bundle_del(kb, AUL_K_APPID);
445 bundle_del(kb, AUL_K_EXEC);
446 bundle_del(kb, AUL_K_PACKAGETYPE);
447 bundle_del(kb, AUL_K_HWACC);
448 bundle_del(kb, AUL_K_PKGID);
449 bundle_del(kb, AUL_K_TASKMANAGE);
450 bundle_del(kb, AUL_K_COMP_TYPE);
452 /* Parse app_path to retrieve default bundle */
453 if (cmd == PAD_CMD_LAUNCH) {
454 ptr = appinfo->original_app_path;
455 flag = __parse_app_path(ptr, exe, sizeof(exe));
458 SECURE_LOGD("parsing app_path: EXEC - %s", exe);
461 flag = __parse_app_path(ptr, key, sizeof(key));
466 flag = __parse_app_path(ptr, value,
472 /* bundle_del(kb, key); */
473 bundle_add(kb, key, value);
475 } else if (flag == 0) {
476 _D("parsing app_path: No arguments");
478 _D("parsing app_path: Invalid argument");
484 static char *__get_libdir(const char *path)
490 path_dup = strdup(path);
491 if (path_dup == NULL)
494 ptr = strrchr(path_dup, '/');
500 snprintf(buf, sizeof(buf), "%s/../lib/", path_dup);
503 if (access(buf, F_OK) == -1)
509 static void __set_sdk_env(const char *appid, const char *value)
511 char buf[MAX_LOCAL_BUFSZ];
514 _D("key: %s / value: %s", AUL_K_SDK, value);
515 /* http://gcc.gnu.org/onlinedocs/gcc/Cross_002dprofiling.html*/
516 /* GCOV_PREFIX contains the prefix to add to the absolute paths */
517 /* in the object file. Prefix can be absolute, or relative.*/
518 /* The default is no prefix. */
519 /* GCOV_PREFIX_STRIP indicates the how many initial directory names */
520 /* to stripoff the hardwired absolute paths. Default value is 0. */
521 if (strncmp(value, SDK_CODE_COVERAGE, strlen(value)) == 0) {
522 token = strrchr(appid, '.');
527 snprintf(buf, sizeof(buf), PATH_TMP"/%s"PATH_DATA, token);
528 setenv("GCOV_PREFIX", buf, 1);
529 setenv("GCOV_PREFIX_STRIP", "0", 1);
533 void _set_env(appinfo_t *appinfo, bundle *kb)
536 const char **str_array = NULL;
541 setenv("PKG_NAME", appinfo->appid, 1);
543 str = bundle_get_val(kb, AUL_K_STARTTIME);
545 setenv("APP_START_TIME", str, 1);
547 setenv("HWACC", appinfo->hwacc, 1);
548 if (appinfo->taskmanage)
549 setenv("TASKMANAGE", appinfo->taskmanage, 1);
551 setenv("AUL_APPID", appinfo->appid, 1);
553 setenv("AUL_PKGID", appinfo->pkgid, 1);
555 str = bundle_get_val(kb, AUL_K_WAYLAND_DISPLAY);
557 setenv("WAYLAND_DISPLAY", str, 1);
559 str = bundle_get_val(kb, AUL_K_WAYLAND_WORKING_DIR);
561 setenv("XDG_RUNTIME_DIR", str, 1);
563 str = bundle_get_val(kb, AUL_K_API_VERSION);
565 setenv("TIZEN_API_VERSION", str, 1);
567 str = bundle_get_val(kb, AUL_K_ROOT_PATH);
569 setenv("AUL_ROOT_PATH", str, 1);
571 libdir = __get_libdir(appinfo->app_path);
573 setenv("LD_LIBRARY_PATH", libdir, 1);
577 if (bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
578 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
580 str = bundle_get_val(kb, AUL_K_SDK);
587 for (i = 0; i < len; i++)
588 __set_sdk_env(appinfo->appid, str_array[i]);
591 static char **__add_arg(bundle *kb, char **argv, int *margc, const char *key)
593 const char *str = NULL;
594 const char **str_array = NULL;
597 char **new_argv = NULL;
599 if (bundle_get_type(kb, key) & BUNDLE_TYPE_ARRAY) {
600 str_array = bundle_get_str_array(kb, key, &len);
602 str = bundle_get_val(kb, key);
610 if (strncmp(key, DLP_K_DEBUG_ARG, strlen(key)) == 0
611 || strncmp(key, DLP_K_VALGRIND_ARG, strlen(key)) == 0) {
612 new_argv = (char **)realloc(argv,
613 sizeof(char *) * (*margc + len + 2));
614 if (new_argv == NULL) {
615 _E("Failed to realloc (key: %s)", key);
619 for (i = *margc + len + 1; i - (len + 1) >= 0; i--)
620 new_argv[i] = new_argv[i - (len + 1)];
622 /* need to add new_argv[0] */
623 for (i = 0; i < len; i++)
624 new_argv[1 + i] = strdup(str_array[i]);
626 len++; /* gdbserver or valgrind */
627 } else if (strncmp(key, DLP_K_ATTACH_ARG, strlen(key)) == 0) {
628 new_argv = (char **)malloc((len + 2) * sizeof(char *));
629 if (new_argv == NULL) {
630 _E("Failed to malloc (key: %s)", key);
634 for (i = 0; i < len; i++)
635 new_argv[1 + i] = strdup(str_array[i]);
640 new_argv = (char **)realloc(argv,
641 sizeof(char *) * (*margc + len + 1));
642 if (new_argv == NULL) {
643 _E("Failed to realloc (key: %s)", key);
647 for (i = 0; i < len; i++)
648 new_argv[*margc + i] = strdup(str_array[i]);
651 new_argv[*margc + len] = NULL;
654 if (strncmp(key, DLP_K_DEBUG_ARG, strlen(key)) == 0
655 || strncmp(key, DLP_K_VALGRIND_ARG, strlen(key)) == 0) {
656 new_argv = (char **)realloc(argv,
657 sizeof(char *) * (*margc + 2));
658 if (new_argv == NULL) {
659 _E("Failed to realloc (key: %s)", key);
663 for (i = *margc + 1; i - 1 >= 0; i--)
664 new_argv[i] = new_argv[i - 1];
666 /* need to add new_argv[0] */
671 if (new_argv == NULL)
677 char **_create_argc_argv(bundle *kb, int *margc, const char *app_path)
680 char **new_argv = NULL;
683 char buf[MAX_LOCAL_BUFSZ];
685 const char **str_array = NULL;
689 argc = bundle_export_to_argv(kb, &argv);
691 argv[0] = strdup(app_path);
693 _E("bundle_export_to_argv() is failed.");
697 if (bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
698 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
700 str = bundle_get_val(kb, AUL_K_SDK);
707 for (i = 0; i < len; i++) {
708 if (str_array[i] == NULL)
711 if (strncmp(str_array[i], SDK_DEBUG,
712 strlen(str_array[i])) == 0) {
715 snprintf(buf, sizeof(buf), "%s.exe", app_path);
716 /* this code is added */
717 /* because core app don't have '.exe' excutable */
718 /* if '.exe' not exist then use app_path */
719 if (access(buf, F_OK) != 0)
720 argv[0] = strdup(app_path);
722 argv[0] = strdup(buf);
724 path = bundle_get_val(kb, DLP_K_GDBSERVER_PATH);
726 _E("Failed to get gdbserver path");
729 bundle_free_exported_argv(argc, &argv);
733 new_argv = __add_arg(kb, argv, &argc, DLP_K_DEBUG_ARG);
734 new_argv[0] = strdup(path);
736 } else if (strncmp(str_array[i], SDK_VALGRIND,
737 strlen(str_array[i])) == 0) {
738 path = bundle_get_val(kb, DLP_K_VALGRIND_PATH);
740 _E("Failed to get valgrind path");
743 bundle_free_exported_argv(argc, &argv);
747 new_argv = __add_arg(kb, argv, &argc,
749 new_argv[0] = strdup(path);
751 } else if (strncmp(str_array[i], SDK_UNIT_TEST,
752 strlen(str_array[i])) == 0) {
753 new_argv = __add_arg(kb, argv, &argc,
754 DLP_K_UNIT_TEST_ARG);
756 } else if (strncmp(str_array[i], SDK_ATTACH,
757 strlen(str_array[i])) == 0) {
760 bundle_free_exported_argv(argc, &argv);
762 path = bundle_get_val(kb, DLP_K_GDBSERVER_PATH);
764 _E("Failed to get gdbserver path");
767 new_argv = __add_arg(kb, argv, &argc, DLP_K_ATTACH_ARG);
768 new_argv[0] = strdup(path);
778 static int __delete_dir(const char *path)
781 struct dirent dentry;
782 struct dirent *result = NULL;
794 while (readdir_r(dp, &dentry, &result) == 0 && result) {
795 if (!strcmp(dentry.d_name, ".") || !strcmp(dentry.d_name, ".."))
798 snprintf(buf, sizeof(buf), "%s/%s", path, dentry.d_name);
799 ret = stat(buf, &statbuf);
801 if (S_ISDIR(statbuf.st_mode))
814 int _delete_sock_path(int pid, uid_t uid)
818 snprintf(path, sizeof(path), "/run/aul/apps/%d/%d", uid, pid);
819 if (access(path, F_OK) == 0)
822 if (access(path, F_OK) == 0)
828 int _close_all_fds(void)
831 struct dirent dentry;
832 struct dirent *result = NULL;
836 dp = opendir("/proc/self/fd");
839 max_fd = sysconf(_SC_OPEN_MAX);
840 for (fd = 3; fd < max_fd; fd++)
846 while (readdir_r(dp, &dentry, &result) == 0 && result) {
847 if (!isdigit(dentry.d_name[0]))
850 fd = atoi(dentry.d_name);