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.
20 #include <sys/types.h>
22 #include <sys/mount.h>
27 #include <sys/xattr.h>
29 #include <sys/socket.h>
31 #include <linux/limits.h>
33 #include <tzplatform_config.h>
36 #include <systemd/sd-journal.h>
38 #include <sys/resource.h>
39 #include <sys/personality.h>
41 #include "launchpad_common.h"
44 #define MAX_PATH_LEN 1024
45 #define MAX_CMD_BUFSZ 1024
47 #define MAX_PENDING_CONNECTIONS 10
48 #define CONNECT_RETRY_TIME (100 * 1000)
49 #define CONNECT_RETRY_COUNT 3
50 #define AUL_PKT_HEADER_SIZE (sizeof(int) + sizeof(int) + sizeof(int))
51 #define PATH_AMD_SOCK "/run/aul/daemons/.amd-sock"
52 #define PATH_DEV_NULL "/dev/null"
54 static int __read_proc(const char *path, char *buf, int size)
59 if (buf == NULL || path == NULL)
62 fd = open(path, O_RDONLY);
66 ret = read(fd, buf, size - 1);
78 void _get_cpu_idle(unsigned long long *total, unsigned long long *idle)
82 unsigned long long sum = 0;
83 unsigned long long val;
84 unsigned long long iv = 0;
87 fp = fopen("/proc/stat", "rt");
92 if (fscanf(fp, "%3s", buf) == -1) {
97 for (i = 0; i < 10; i++) {
98 if (fscanf(fp, "%lld", &val) == -1) {
103 if (sum + val < sum) {
110 if (i == 3) /* idle */
120 void _set_sock_option(int fd, int cli)
124 struct timeval tv = { 5, 200 * 1000 }; /* 5.2 sec */
126 size = AUL_SOCK_MAXBUFF;
127 setsockopt(fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size));
128 setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
130 setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv));
131 flag = fcntl(fd, F_GETFD);
133 fcntl(fd, F_SETFD, flag);
137 static int __parse_app_path(const char *arg, char *out, int out_size)
141 char *start_out = out;
143 if (arg == NULL || out == NULL) {
144 /* Handles null buffer*/
148 for (i = 0; out_size > 1; i++) {
172 case 2: /* escape start*/
187 case 4: /* character escape*/
188 if (arg[i] == '\0') {
198 if (out != start_out) {
207 return -1; /* error*/
208 case 7: /* terminate*/
225 int _send_cmd_to_amd(int cmd)
227 struct sockaddr_un addr = {0,};
230 int retry = CONNECT_RETRY_COUNT;
231 app_pkt_t pkt = {0,};
233 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
234 /* support above version 2.6.27*/
236 if (errno == EINVAL) {
237 fd = socket(AF_UNIX, SOCK_STREAM, 0);
239 _E("second chance - socket create error");
248 addr.sun_family = AF_UNIX;
249 snprintf(addr.sun_path, sizeof(addr.sun_path), "%s", PATH_AMD_SOCK);
250 while (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
251 if (errno != ETIMEDOUT || retry <= 0) {
252 _E("Failed to connect error(%d)", errno);
257 usleep(CONNECT_RETRY_TIME);
259 _D("re-connect to %s (%d)", addr.sun_path, retry);
263 ret = send(fd, &pkt, sizeof(app_pkt_t), MSG_NOSIGNAL);
265 _E("Failed to send cmd(%d), errno(%d)", cmd, errno);
274 int _create_server_sock(const char *name)
276 struct sockaddr_un saddr;
279 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
280 /* support above version 2.6.27*/
282 if (errno == EINVAL) {
283 fd = socket(AF_UNIX, SOCK_STREAM, 0);
285 _E("second chance - socket create error");
294 memset(&saddr, 0, sizeof(saddr));
295 saddr.sun_family = AF_UNIX;
297 snprintf(saddr.sun_path, sizeof(saddr.sun_path),
299 SOCKET_PATH, getuid(), name);
300 unlink(saddr.sun_path);
302 if (bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) {
308 _set_sock_option(fd, 0);
310 if (listen(fd, 128) == -1) {
319 app_pkt_t *_recv_pkt_raw(int fd)
323 unsigned char buf[AUL_SOCK_MAXBUFF];
330 /* receive header(cmd, datalen) */
331 len = recv(fd, buf, AUL_PKT_HEADER_SIZE, 0);
336 if (len < AUL_PKT_HEADER_SIZE) {
340 memcpy(&cmd, buf, sizeof(int));
341 memcpy(&datalen, buf + sizeof(int), sizeof(int));
342 memcpy(&opt, buf + sizeof(int) + sizeof(int), sizeof(int));
344 /* allocate for a null byte */
345 pkt = (app_pkt_t *)calloc(1, AUL_PKT_HEADER_SIZE + datalen + 1);
347 _E("failed to alloc app_pkt_t");
355 while (len != pkt->len) {
356 ret = recv(fd, pkt->data + len, pkt->len - len, 0);
358 _E("recv error %d %d", len, pkt->len);
363 _D("recv len %d %d", len, pkt->len);
369 app_pkt_t *_accept_recv_pkt_raw(int fd, int *clifd, struct ucred *cr)
371 struct sockaddr_un aul_addr = { 0, };
375 int cl = sizeof(struct ucred);
377 sun_size = sizeof(struct sockaddr_un);
379 newfd = accept(fd, (struct sockaddr *)&aul_addr,
380 (socklen_t *) &sun_size);
387 if (getsockopt(newfd, SOL_SOCKET, SO_PEERCRED, cr,
388 (socklen_t *) &cl) < 0) {
389 _E("peer information error");
394 _set_sock_option(newfd, 1);
396 pkt = _recv_pkt_raw(newfd);
398 _E("failed to receive pkt from client");
407 int _send_pkt_raw(int client_fd, app_pkt_t *pkt)
413 if (client_fd == -1 || pkt == NULL) {
414 _E("arguments error!");
418 pkt_size = AUL_PKT_HEADER_SIZE + pkt->len;
420 while (sent != pkt_size) {
421 send_ret = send(client_fd, (char *)pkt + sent,
422 pkt_size - sent, MSG_NOSIGNAL);
423 if (send_ret == -1) {
424 _E("send error! (%d)", errno);
429 _D("send(%d: ret: %d) : %d / %d",
430 client_fd, send_ret, sent, pkt_size);
436 appinfo_t *_appinfo_create(bundle *kb)
438 appinfo_t *menu_info;
439 const char *ptr = NULL;
441 menu_info = calloc(1, sizeof(appinfo_t));
442 if (menu_info == NULL)
445 ptr = bundle_get_val(kb, AUL_K_APPID);
447 menu_info->appid = strdup(ptr);
448 ptr = bundle_get_val(kb, AUL_K_EXEC);
450 menu_info->app_path = strdup(ptr);
451 if (menu_info->app_path != NULL)
452 menu_info->original_app_path = strdup(menu_info->app_path);
453 ptr = bundle_get_val(kb, AUL_K_PACKAGETYPE);
455 menu_info->pkg_type = strdup(ptr);
456 ptr = bundle_get_val(kb, AUL_K_APP_TYPE);
458 menu_info->app_type = strdup(ptr);
459 ptr = bundle_get_val(kb, AUL_K_HWACC);
461 menu_info->hwacc = strdup(ptr);
462 ptr = bundle_get_val(kb, AUL_K_TASKMANAGE);
464 menu_info->taskmanage = strdup(ptr);
465 ptr = bundle_get_val(kb, AUL_K_PKGID);
467 menu_info->pkgid = strdup(ptr);
468 ptr = bundle_get_val(kb, AUL_K_COMP_TYPE);
470 menu_info->comp_type = strdup(ptr);
471 ptr = bundle_get_val(kb, AUL_K_INTERNAL_POOL);
473 menu_info->internal_pool = strdup(ptr);
474 ptr = bundle_get_val(kb, AUL_K_ROOT_PATH);
476 menu_info->root_path = strdup(ptr);
478 ptr = bundle_get_val(kb, AUL_K_LOADER_NAME);
480 menu_info->loader_name = strdup(ptr);
482 if (!_appinfo_get_app_path(menu_info)) {
483 _appinfo_free(menu_info);
490 char *_appinfo_get_app_path(appinfo_t *menu_info)
496 if (!menu_info || menu_info->app_path == NULL)
499 while (menu_info->app_path[i] != 0) {
500 if (menu_info->app_path[i] == ' '
501 || menu_info->app_path[i] == '\t') {
509 free(menu_info->app_path);
510 menu_info->app_path = NULL;
511 } else if (path_len > 0) {
512 tmp_app_path = malloc(sizeof(char) * (path_len + 1));
513 if (tmp_app_path == NULL)
515 snprintf(tmp_app_path, path_len + 1, "%s", menu_info->app_path);
516 free(menu_info->app_path);
517 menu_info->app_path = tmp_app_path;
520 return menu_info->app_path;
523 void _appinfo_free(appinfo_t *menu_info)
525 if (menu_info == NULL)
528 if (menu_info->appid != NULL)
529 free(menu_info->appid);
530 if (menu_info->app_path != NULL)
531 free(menu_info->app_path);
532 if (menu_info->original_app_path != NULL)
533 free(menu_info->original_app_path);
534 if (menu_info->pkg_type != NULL)
535 free(menu_info->pkg_type);
536 if (menu_info->app_type != NULL)
537 free(menu_info->app_type);
538 if (menu_info->hwacc != NULL)
539 free(menu_info->hwacc);
540 if (menu_info->taskmanage != NULL)
541 free(menu_info->taskmanage);
542 if (menu_info->pkgid != NULL)
543 free(menu_info->pkgid);
544 if (menu_info->comp_type != NULL)
545 free(menu_info->comp_type);
546 if (menu_info->internal_pool != NULL)
547 free(menu_info->internal_pool);
548 if (menu_info->root_path != NULL)
549 free(menu_info->root_path);
550 if (menu_info->loader_name != NULL)
551 free(menu_info->loader_name);
556 void _modify_bundle(bundle *kb, int caller_pid, appinfo_t *menu_info, int cmd)
559 char exe[MAX_PATH_LEN];
564 bundle_del(kb, AUL_K_APPID);
565 bundle_del(kb, AUL_K_EXEC);
566 bundle_del(kb, AUL_K_APP_TYPE);
567 bundle_del(kb, AUL_K_PACKAGETYPE);
568 bundle_del(kb, AUL_K_TASKMANAGE);
569 bundle_del(kb, AUL_K_PKGID);
570 bundle_del(kb, AUL_K_COMP_TYPE);
572 /* Parse app_path to retrieve default bundle*/
573 if (cmd == PAD_CMD_LAUNCH) {
574 ptr = menu_info->original_app_path;
575 flag = __parse_app_path(ptr, exe, sizeof(exe));
578 SECURE_LOGD("parsing app_path: EXEC - %s\n", exe);
581 flag = __parse_app_path(ptr, key, sizeof(key));
586 flag = __parse_app_path(ptr, value,
592 /*bundle_del(kb, key);*/
593 bundle_add(kb, key, value);
595 } else if (flag == 0)
596 _D("parsing app_path: No arguments\n");
598 _D("parsing app_path: Invalid argument\n");
602 int _connect_to_launchpad(int type, int id)
604 struct sockaddr_un addr;
606 int retry = CONNECT_RETRY_COUNT;
608 int client_pid = getpid();
610 _D("[launchpad] enter, type: %d", type);
612 fd = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0);
618 memset(&addr, 0x00, sizeof(struct sockaddr_un));
619 addr.sun_family = AF_UNIX;
620 snprintf(addr.sun_path, sizeof(addr.sun_path), "%s/daemons/%d/%s%d-%d",
621 SOCKET_PATH, getuid(), LAUNCHPAD_LOADER_SOCKET_NAME,
624 _D("connect to %s", addr.sun_path);
625 while (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
626 if (errno != ETIMEDOUT || retry <= 0) {
627 _E("connect error : %d", errno);
631 usleep(CONNECT_RETRY_TIME);
633 _D("re-connect to %s (%d)", addr.sun_path, retry);
636 send_ret = send(fd, &client_pid, sizeof(client_pid), MSG_NOSIGNAL);
637 _D("send(%d) : %d", client_pid, send_ret);
639 if (send_ret == -1) {
644 SECURE_LOGD("[launchpad] done, connect fd: %d", fd);
654 void _set_env(appinfo_t *menu_info, bundle *kb)
657 char buf[MAX_LOCAL_BUFSZ];
659 str = bundle_get_val(kb, AUL_K_STARTTIME);
661 setenv("APP_START_TIME", str, 1);
663 if (menu_info->hwacc != NULL)
664 setenv("HWACC", menu_info->hwacc, 1);
665 if (menu_info->taskmanage != NULL)
666 setenv("TASKMANAGE", menu_info->taskmanage, 1);
667 if (menu_info->root_path != NULL)
668 setenv("AUL_ROOT_PATH", menu_info->root_path, 1);
669 if (menu_info->appid != NULL)
670 setenv("AUL_APPID", menu_info->appid, 1);
671 if (menu_info->pkgid != NULL)
672 setenv("AUL_PKGID", menu_info->pkgid, 1);
673 if (menu_info->app_type != NULL)
674 setenv("RUNTIME_TYPE", menu_info->app_type, 1);
676 str = bundle_get_val(kb, AUL_K_WAYLAND_DISPLAY);
678 setenv("WAYLAND_DISPLAY", str, 1);
680 str = bundle_get_val(kb, AUL_K_WAYLAND_WORKING_DIR);
682 setenv("XDG_RUNTIME_DIR", str, 1);
684 str = bundle_get_val(kb, AUL_K_API_VERSION);
686 setenv("TIZEN_API_VERSION", str, 1);
688 snprintf(buf, sizeof(buf), "%d", getpid());
689 setenv("AUL_PID", buf, 1);
691 #ifdef TIZEN_FEATURE_SET_PERSONALITY_32
692 int res = personality(PER_LINUX32);
695 _E("personality() failed, error: %d (%s)",
696 errno, strerror(errno));
701 char **_create_argc_argv(bundle *kb, int *margc)
706 argc = bundle_export_to_argv(kb, &argv);
712 char *_get_libdir(const char *path)
720 path_dup = strdup(path);
721 if (path_dup == NULL)
723 ptr = strrchr(path_dup, '/');
729 snprintf(buf, sizeof(buf), "%s/../lib/", path_dup);
732 if (access(buf, F_OK) == -1)
738 int _proc_get_attr_by_pid(int pid, char *buf, int size)
740 char path[PATH_MAX] = { 0, };
743 snprintf(path, sizeof(path), "/proc/%d/attr/current", pid);
744 ret = __read_proc(path, buf, size);
751 static int __delete_dir(const char *path)
754 struct dirent *dentry = NULL;
766 while ((dentry = readdir(dp)) != NULL) {
767 if (!strcmp(dentry->d_name, ".") || !strcmp(dentry->d_name, ".."))
770 snprintf(buf, sizeof(buf), "%s/%s", path, dentry->d_name);
771 ret = stat(buf, &statbuf);
773 if (S_ISDIR(statbuf.st_mode))
786 int _delete_sock_path(int pid, uid_t uid)
790 snprintf(path, sizeof(path), "/run/aul/apps/%d/%d", uid, pid);
791 if (access(path, F_OK) == 0)
794 if (access(path, F_OK) == 0)
800 int _close_all_fds(void)
803 struct dirent *dentry = NULL;
807 dp = opendir("/proc/self/fd");
810 max_fd = sysconf(_SC_OPEN_MAX);
811 for (fd = 3; fd < max_fd; fd++)
817 while ((dentry = readdir(dp)) != NULL) {
818 if (!isdigit(dentry->d_name[0]))
821 fd = atoi(dentry->d_name);
835 int _setup_stdio(const char *ident)
840 fd = open(PATH_DEV_NULL, O_RDONLY | O_NOCTTY);
842 _W("Failed to open /dev/null - err(%d)", errno);
845 if (dup2(fd, STDIN_FILENO) < 0) {
846 _W("Failed to duplicate fd - oldfd(%d), newfd(%d)",
852 fd = sd_journal_stream_fd(ident, LOG_INFO, false);
854 _W("Failed to connect journal socket - err(%d)", errno);
855 fd = open(PATH_DEV_NULL, O_WRONLY | O_NOCTTY);
857 _W("Failed to open /dev/null - err(%d)", errno);
861 if (dup2(fd, STDOUT_FILENO) < 0) {
862 _W("Failed to duplicate fd - oldfd(%d), newfd(%d)",
868 fd = sd_journal_stream_fd(ident, LOG_INFO, false);
870 _W("Failed to connect journal socket - err(%d)", errno);
871 fd = open(PATH_DEV_NULL, O_WRONLY | O_NOCTTY);
873 _W("Failed to open /dev/null - err(%d)", errno);
877 if (dup2(fd, STDERR_FILENO) < 0) {
878 _W("Failed to duplicate fd - oldfd(%d), newfd(%d)",
886 int _set_priority(int prio)
890 r = setpriority(PRIO_PGRP, 0, prio);
892 SECURE_LOGE("Failed to set process(%d) priority(%d) - err(%d)",
893 getpid(), prio, errno);