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 if ((*clifd = accept(fd, (struct sockaddr *)&aul_addr,
160 (socklen_t *)&sun_size)) == -1) {
166 if (getsockopt(*clifd, SOL_SOCKET, SO_PEERCRED, cr,
167 (socklen_t *)&cl) < 0) {
168 _E("peer information error");
173 __set_sock_option(*clifd, 1);
176 /* receive header(cmd, datalen) */
177 len = recv(*clifd, buf, AUL_PKT_HEADER_SIZE, 0);
182 if (len < AUL_PKT_HEADER_SIZE) {
187 memcpy(&cmd, buf, sizeof(int));
188 memcpy(&datalen, buf + sizeof(int), sizeof(int));
189 memcpy(&opt, buf + sizeof(int) + sizeof(int), sizeof(int));
191 /* allocate for a null byte */
192 pkt = (app_pkt_t *)calloc(1, AUL_PKT_HEADER_SIZE + datalen + 1);
202 while (len != pkt->len) {
203 ret = recv(*clifd, pkt->data + len, pkt->len - len, 0);
205 _E("recv error %d %d", len, pkt->len);
211 _D("recv len %d %d", len, pkt->len);
217 static char *__appinfo_get_app_path(appinfo_t *appinfo)
223 if (appinfo == NULL || appinfo->app_path == NULL)
226 while (appinfo->app_path[i] != 0) {
227 if (appinfo->app_path[i] == ' '
228 || appinfo->app_path[i] == '\t') {
237 free(appinfo->app_path);
238 appinfo->app_path = NULL;
239 } else if (path_len > 0) {
240 tmp_app_path = (char *)malloc(sizeof(char) * (path_len + 1));
241 if (tmp_app_path == NULL)
244 snprintf(tmp_app_path, path_len + 1, "%s", appinfo->app_path);
245 free(appinfo->app_path);
246 appinfo->app_path = tmp_app_path;
249 return appinfo->app_path;
252 appinfo_t *_appinfo_create(bundle *kb)
257 appinfo = (appinfo_t *)calloc(1, sizeof(appinfo_t));
261 ptr = bundle_get_val(kb, AUL_K_APPID);
263 appinfo->appid = strdup(ptr);
264 ptr = bundle_get_val(kb, AUL_K_PACKAGETYPE);
266 appinfo->pkg_type = strdup(ptr);
267 ptr = bundle_get_val(kb, AUL_K_HWACC);
269 appinfo->hwacc = strdup(ptr);
270 ptr = bundle_get_val(kb, AUL_K_PKGID);
272 appinfo->debug_appid = strdup(ptr);
273 ptr = bundle_get_val(kb, AUL_K_TASKMANAGE);
275 appinfo->taskmanage = strdup(ptr);
276 ptr = bundle_get_val(kb, AUL_K_COMP_TYPE);
278 appinfo->comp_type = strdup(ptr);
279 ptr = bundle_get_val(kb, AUL_K_EXEC);
281 appinfo->app_path = strdup(ptr);
282 if (appinfo->app_path)
283 appinfo->original_app_path = strdup(appinfo->app_path);
285 if (__appinfo_get_app_path(appinfo) == NULL) {
286 _appinfo_free(appinfo);
293 void _appinfo_free(appinfo_t *appinfo)
299 free(appinfo->appid);
300 if (appinfo->app_path)
301 free(appinfo->app_path);
302 if (appinfo->original_app_path)
303 free(appinfo->original_app_path);
304 if (appinfo->pkg_type)
305 free(appinfo->pkg_type);
307 free(appinfo->hwacc);
308 if (appinfo->taskmanage)
309 free(appinfo->taskmanage);
310 if (appinfo->debug_appid)
311 free(appinfo->debug_appid);
312 if (appinfo->comp_type)
313 free(appinfo->comp_type);
318 static int __parse_app_path(const char *arg, char *out, int out_size)
322 char *start_out = out;
324 if (arg == NULL || out == NULL)
327 for (i = 0; out_size > 1; i++) {
351 case 2: /* escape start */
366 case 4: /* character escape */
377 if (out != start_out) {
386 return -1; /* error */
387 case 7: /* terminate */
404 void _modify_bundle(bundle *kb, int caller_pid, appinfo_t *appinfo, int cmd)
407 char exe[MAX_PATH_LEN];
412 bundle_del(kb, AUL_K_APPID);
413 bundle_del(kb, AUL_K_EXEC);
414 bundle_del(kb, AUL_K_PACKAGETYPE);
415 bundle_del(kb, AUL_K_HWACC);
416 bundle_del(kb, AUL_K_PKGID);
417 bundle_del(kb, AUL_K_TASKMANAGE);
418 bundle_del(kb, AUL_K_COMP_TYPE);
420 /* Parse app_path to retrieve default bundle */
421 if (cmd == PAD_CMD_LAUNCH) {
422 ptr = appinfo->original_app_path;
423 flag = __parse_app_path(ptr, exe, sizeof(exe));
426 SECURE_LOGD("parsing app_path: EXEC - %s", exe);
429 flag = __parse_app_path(ptr, key, sizeof(key));
434 flag = __parse_app_path(ptr, value,
440 /* bundle_del(kb, key); */
441 bundle_add(kb, key, value);
443 } else if (flag == 0) {
444 _D("parsing app_path: No arguments");
446 _D("parsing app_path: Invalid argument");
452 static char *__get_libdir(const char *path)
458 path_dup = strdup(path);
459 if (path_dup == NULL)
462 ptr = strrchr(path_dup, '/');
465 snprintf(buf, sizeof(buf), "%s/../lib/", path_dup);
468 if (access(buf, F_OK) == -1)
474 static void __set_sdk_env(const char *appid, const char *value)
476 char buf[MAX_LOCAL_BUFSZ];
479 _D("key: %s / value: %s", AUL_K_SDK, value);
480 /* http://gcc.gnu.org/onlinedocs/gcc/Cross_002dprofiling.html*/
481 /* GCOV_PREFIX contains the prefix to add to the absolute paths */
482 /* in the object file. Prefix can be absolute, or relative.*/
483 /* The default is no prefix. */
484 /* GCOV_PREFIX_STRIP indicates the how many initial directory names */
485 /* to stripoff the hardwired absolute paths. Default value is 0. */
486 if (strncmp(value, SDK_CODE_COVERAGE, strlen(value)) == 0) {
487 token = strrchr(appid, '.');
492 snprintf(buf, sizeof(buf), PATH_TMP"/%s"PATH_DATA, token);
493 setenv("GCOV_PREFIX", buf, 1);
494 setenv("GCOV_PREFIX_STRIP", "0", 1);
498 void _set_env(appinfo_t *appinfo, bundle *kb)
501 const char **str_array = NULL;
506 setenv("PKG_NAME", appinfo->appid, 1);
508 str = bundle_get_val(kb, AUL_K_STARTTIME);
510 setenv("APP_START_TIME", str, 1);
512 setenv("HWACC", appinfo->hwacc, 1);
513 if (appinfo->taskmanage)
514 setenv("TASKMANAGE", appinfo->taskmanage, 1);
516 str = bundle_get_val(kb, AUL_K_WAYLAND_DISPLAY);
518 setenv("WAYLAND_DISPLAY", str, 1);
520 str = bundle_get_val(kb, AUL_K_WAYLAND_WORKING_DIR);
522 setenv("XDG_RUNTIME_DIR", str, 1);
524 str = bundle_get_val(kb, AUL_K_API_VERSION);
526 setenv("TIZEN_API_VERSION", str, 1);
528 libdir = __get_libdir(appinfo->app_path);
530 setenv("LD_LIBRARY_PATH", libdir, 1);
534 if (bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
535 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
537 str = bundle_get_val(kb, AUL_K_SDK);
544 for (i = 0; i < len; i++)
545 __set_sdk_env(appinfo->appid, str_array[i]);
548 static char **__add_arg(bundle *kb, char **argv, int *margc, const char *key)
550 const char *str = NULL;
551 const char **str_array = NULL;
554 char **new_argv = NULL;
556 if (bundle_get_type(kb, key) & BUNDLE_TYPE_ARRAY) {
557 str_array = bundle_get_str_array(kb, key, &len);
559 str = bundle_get_val(kb, key);
567 if (strncmp(key, DLP_K_DEBUG_ARG, strlen(key)) == 0
568 || strncmp(key, DLP_K_VALGRIND_ARG, strlen(key)) == 0) {
569 new_argv = (char **)realloc(argv,
570 sizeof(char *) * (*margc + len + 2));
571 if (new_argv == NULL) {
572 _E("Failed to realloc (key: %s)", key);
576 for (i = *margc + len + 1; i - (len + 1) >= 0; i--)
577 new_argv[i] = new_argv[i - (len + 1)];
579 /* need to add new_argv[0] */
580 for (i = 0; i < len; i++)
581 new_argv[1 + i] = strdup(str_array[i]);
583 len++; /* gdbserver or valgrind */
584 } else if (strncmp(key, DLP_K_ATTACH_ARG, strlen(key)) == 0) {
585 new_argv = (char **)malloc((len + 2) * sizeof(char *));
586 if (new_argv == NULL) {
587 _E("Failed to malloc (key: %s)", key);
591 for (i = 0; i < len; i++)
592 new_argv[1 + i] = strdup(str_array[i]);
597 new_argv = (char **)realloc(argv,
598 sizeof(char *) * (*margc + len + 1));
599 if (new_argv == NULL) {
600 _E("Failed to realloc (key: %s)", key);
604 for (i = 0; i < len; i++)
605 new_argv[*margc + i] = strdup(str_array[i]);
608 new_argv[*margc + len] = NULL;
611 if (strncmp(key, DLP_K_DEBUG_ARG, strlen(key)) == 0
612 || strncmp(key, DLP_K_VALGRIND_ARG, strlen(key)) == 0) {
613 new_argv = (char **)realloc(argv,
614 sizeof(char *) * (*margc + 2));
615 if (new_argv == NULL) {
616 _E("Failed to realloc (key: %s)", key);
620 for (i = *margc + 1; i - 1 >= 0; i--)
621 new_argv[i] = new_argv[i - 1];
623 /* need to add new_argv[0] */
628 if (new_argv == NULL)
634 char **_create_argc_argv(bundle *kb, int *margc, const char *app_path)
637 char **new_argv = NULL;
640 char buf[MAX_LOCAL_BUFSZ];
642 const char **str_array = NULL;
646 argc = bundle_export_to_argv(kb, &argv);
648 argv[0] = strdup(app_path);
650 _E("bundle_export_to_argv() is failed.");
654 if (bundle_get_type(kb, AUL_K_SDK) & BUNDLE_TYPE_ARRAY) {
655 str_array = bundle_get_str_array(kb, AUL_K_SDK, &len);
657 str = bundle_get_val(kb, AUL_K_SDK);
664 for (i = 0; i < len; i++) {
665 if (str_array[i] == NULL)
668 if (strncmp(str_array[i], SDK_DEBUG,
669 strlen(str_array[i])) == 0) {
672 snprintf(buf, sizeof(buf), "%s.exe", app_path);
673 /* this code is added because core app don't have '.exe' excutable */
674 /* if '.exe' not exist then use app_path */
675 if (access(buf, F_OK) != 0)
676 argv[0] = strdup(app_path);
678 argv[0] = strdup(buf);
680 path = bundle_get_val(kb, DLP_K_GDBSERVER_PATH);
682 _E("Failed to get gdbserver path");
685 bundle_free_exported_argv(argc, &argv);
689 new_argv = __add_arg(kb, argv, &argc, DLP_K_DEBUG_ARG);
690 new_argv[0] = strdup(path);
692 } else if (strncmp(str_array[i], SDK_VALGRIND,
693 strlen(str_array[i])) == 0) {
694 path = bundle_get_val(kb, DLP_K_VALGRIND_PATH);
696 _E("Failed to get valgrind path");
699 bundle_free_exported_argv(argc, &argv);
703 new_argv = __add_arg(kb, argv, &argc,
705 new_argv[0] = strdup(path);
707 } else if (strncmp(str_array[i], SDK_UNIT_TEST,
708 strlen(str_array[i])) == 0) {
709 new_argv = __add_arg(kb, argv, &argc,
710 DLP_K_UNIT_TEST_ARG);
712 } else if (strncmp(str_array[i], SDK_ATTACH,
713 strlen(str_array[i])) == 0) {
716 bundle_free_exported_argv(argc, &argv);
718 path = bundle_get_val(kb, DLP_K_GDBSERVER_PATH);
720 _E("Failed to get gdbserver path");
723 new_argv = __add_arg(kb, argv, &argc, DLP_K_ATTACH_ARG);
724 new_argv[0] = strdup(path);
734 static int __read_proc(const char *path, char *buf, int size)
739 if (buf == NULL || path == NULL)
742 fd = open(path, O_RDONLY);
746 ret = read(fd, buf, size - 1);
759 int _proc_check_cmdline_bypid(int pid)
761 char buf[MAX_CMD_BUFSZ];
764 snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid);
765 ret = __read_proc(buf, buf, sizeof(buf));
769 _D("cmdline: %s", buf);