4 * Copyright (c) 2000 - 2013 Samsung Electronics Co., Ltd. All rights reserved.
8 * Jaewon Lim <jaewon81.lim@samsung.com>
9 * Woojin Jung <woojin2.jung@samsung.com>
10 * Juyoung Kim <j0.kim@samsung.com>
11 * Cherepanov Vitaliy <v.cherepanov@samsung.com>
12 * Nikita Kalyazin <n.kalyazin@samsung.com>
14 * Licensed under the Apache License, Version 2.0 (the "License");
15 * you may not use this file except in compliance with the License.
16 * You may obtain a copy of the License at
18 * http://www.apache.org/licenses/LICENSE-2.0
20 * Unless required by applicable law or agreed to in writing, software
21 * distributed under the License is distributed on an "AS IS" BASIS,
22 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
23 * See the License for the specific language governing permissions and
24 * limitations under the License.
28 * - Samsung RnD Institute Russia
37 #include <signal.h> // for signal
39 #include <unistd.h> // for unlink
40 #include <dirent.h> // for opendir, readdir
41 #include <sys/types.h> // for open
42 #include <sys/stat.h> // for open
43 #include <fcntl.h> // for open
44 #include <grp.h> // for setgroups
45 #include <sys/smack.h>
46 #include <attr/xattr.h>
48 #include <sys/wait.h> /* waitpid */
54 #define BUFFER_MAX 1024
55 #define APP_GROUPS_MAX 100
56 #define APP_GROUP_LIST "/usr/share/privilege-control/app_group_list"
57 #define SELF_LABEL_FILE "/proc/self/attr/current"
59 #define SMACK_LABEL_LEN 255
62 #define MANIFEST_PATH "/info/manifest.xml"
64 #define APPDIR1 "/opt/apps/"
65 #define APPDIR2 "/opt/usr/apps/"
67 uint64_t str_to_uint64(char* str)
73 while(*str >= '0' && *str <= '9')
75 res = res * 10 + (*str - '0');
83 int64_t str_to_int64(char* str)
101 while(*str >= '0' && *str <= '9')
103 res = res * 10 + (*str - '0');
108 return (res * factor);
111 int read_line(const int fd, char* ptr, const unsigned int maxlen)
119 if((rc = read(fd, c, 1)) != 1)
120 return -1; // eof or read err
129 return -1; // no space
132 int smack_set_label_for_self(const char *label)
138 len = strnlen(label, SMACK_LABEL_LEN + 1);
139 if (len > SMACK_LABEL_LEN)
142 fd = open(SELF_LABEL_FILE, O_WRONLY);
146 ret = write(fd, label, len);
149 return (ret < 0) ? -1 : 0;
152 void set_appuser_groups(void)
157 gid_t groups[APP_GROUPS_MAX] = {0, };
160 // groups[cnt++] = SID_DEVELOPER;
161 fd = open(APP_GROUP_LIST, O_RDONLY);
164 LOGE("cannot get app's group lists from %s", APP_GROUP_LIST);
170 if(read_line(fd, buffer, sizeof buffer) < 0)
175 t_gid = strtoul(buffer, 0, 10);
179 LOGE("cannot change string to integer: [%s]\n", buffer);
185 if(cnt < APP_GROUPS_MAX)
187 groups[cnt++] = t_gid;
191 LOGE("cannot add groups more than %d", APP_GROUPS_MAX);
199 if(setgroups(sizeof(groups) / sizeof(groups[0]), groups) != 0)
201 fprintf(stderr, "set groups failed errno: %d\n", errno);
209 int get_smack_label(const char* execpath, char* buffer, int buflen)
214 rc = smack_lgetlabel(execpath, &appid, SMACK_LABEL_ACCESS);
215 if(rc == 0 && appid != NULL)
217 strncpy(buffer, appid, (buflen < strlen(appid))? buflen:strlen(appid));
225 // return 0 if succeed
226 // return -1 if error occured
227 int remove_indir(const char *dirname)
230 struct dirent *entry;
233 dir = opendir(dirname);
239 while((entry = readdir(dir)) != NULL)
241 if (strcmp(entry->d_name, ".") && strcmp(entry->d_name, ".."))
243 snprintf(path, (size_t) PATH_MAX, "%s/%s", dirname, entry->d_name);
244 if (entry->d_type != DT_DIR) // file
248 else { } // directory
256 // return 0 to normal case
257 // return non-zero to error case
258 int get_manifest_path(const char* exec_path, char* buf, int buflen)
262 strcpy(buf, exec_path);
264 chr = strrchr(buf, '/');
270 chr = strrchr(buf, '/');
276 strcat(buf, MANIFEST_PATH);
280 /* execute applcation with executable binary path */
281 int exec_app_tizen(const char *app_id, const char *exec_path)
285 LOGI("exec %s\n", exec_path);
287 if (exec_path == NULL || !strlen(exec_path)) {
288 LOGE("Executable path is not correct\n");
291 LOGI("launch app path is %s, executable path is %s\n"
292 "launch app name (%s), app_id (%s)\n",
293 LAUNCH_APP_PATH, exec_path, LAUNCH_APP_NAME, app_id);
298 if (pid > 0) { /* parent */
301 ret = waitpid(pid, &status, 0);
302 while (ret == -1 && errno == EINTR);
305 execl(LAUNCH_APP_PATH, LAUNCH_APP_NAME, app_id, LAUNCH_APP_SDK,
306 DA_PRELOAD_EXEC, NULL);
307 /* FIXME: If code flows here, it deserves greater attention */
312 int exec_app_common(const char* exec_path)
316 char manifest[PATH_MAX];
317 char command[PATH_MAX];
319 LOGI("exec %s\n", exec_path);
320 if (exec_path == NULL || !strlen(exec_path)) {
321 LOGE("Executable path is not correct\n");
325 sprintf(command, "%s %s", DA_PRELOAD_OSP, exec_path);
326 LOGI("cmd: %s\n", command);
332 if (pid > 0) { /* parent */
335 execl(SHELL_CMD, SHELL_CMD, "-c", command, NULL);
336 /* FIXME: Again, such case deserve much more attention */
341 // find process id from executable binary path
342 pid_t find_pid_from_path(const char* path)
346 char buffer[BUFFER_MAX] = {0};
347 char command[BUFFER_MAX] = {0};
349 sprintf(command, "/bin/pidof %s", path);
350 LOGI("look for <%s>\n", path);
352 FILE *fp = popen(command, "r");
356 while (fgets(buffer, BUFFER_MAX, fp) != NULL)
357 LOGI("result of 'pidof' is %s\n", buffer);
361 if (strlen(buffer) > 0) {
362 if (sscanf(buffer, "%d\n", &status) != 1) {
363 LOGW("Failed to read result buffer of 'pidof',"
364 " status(%d) with cmd '%s'\n", status, command);
372 static pid_t get_pid_by_path(const char *binary_path)
377 static const char exe_line[] = ".exe";
380 pkg_pid = find_pid_from_path(binary_path);
382 len = strlen(binary_path);
383 real_path = malloc(len + sizeof(exe_line));
384 if (real_path == NULL) {
385 LOGE("cannot alloc memory\n");
388 memcpy(real_path, binary_path, len + 1);
390 // try remove or add ".exe" and get pid
391 if (strcmp(real_path + len - (sizeof(exe_line) - 1), exe_line) == 0)
392 // remove .exe from tPath
393 real_path[len - (sizeof(exe_line) - 1)] = '\0';
396 memcpy(&real_path[len], exe_line, sizeof(exe_line));
398 pkg_pid = find_pid_from_path(real_path);
405 static int find_alternative_bin_path(const char *binary_path, char *alter_bin_path) {
406 // alternative path may be /opt/apps/... or /opt/usr/apps/...)
407 if (strncmp(binary_path, APPDIR1, strlen(APPDIR1)) == 0) {
408 strcpy(alter_bin_path, APPDIR2);
409 strcat(alter_bin_path, binary_path + strlen(APPDIR1));
410 } else if (strncmp(binary_path, APPDIR2, strlen(APPDIR2)) == 0) {
411 strcpy(alter_bin_path, APPDIR1);
412 strcat(alter_bin_path, binary_path + strlen(APPDIR2));
419 int kill_app(const char *binary_path)
422 char alter_bin_path[PATH_MAX];
424 LOGI("kill %s (%d)\n", binary_path, SIGKILL);
426 pkg_pid = get_pid_by_path(binary_path);
429 if (find_alternative_bin_path(binary_path, alter_bin_path) == 0)
430 pkg_pid = get_pid_by_path(alter_bin_path);
434 if (kill(pkg_pid, SIGTERM) == -1) {
435 LOGE("cannot kill %d -%d err<%s>\n", pkg_pid, SIGKILL,
439 // we need sleep up there because kill() function
440 // returns control immediately after send signal
441 // without it app_launch returns err on start app
443 LOGI("killed %d -%d\n", pkg_pid, SIGKILL);
446 LOGI("cannot kill <%s>; process not found\n", binary_path);
451 int get_executable(char* appPath, char* buf, int buflen)
455 sprintf(buf, "%s.exe", appPath);
456 fd = open(buf, O_RDONLY);
463 strcpy(buf, appPath);
468 int get_app_install_path(char *strAppInstall, int length)
471 char buf[BUFFER_MAX];
475 if ((fp = fopen(DA_INSTALL_PATH, "r")) == NULL)
477 LOGE("Failed to open %s\n", DA_INSTALL_PATH);
481 /*ex : <15> DW_AT_comp_dir : (indirect string, offset: 0x25f): /home/yt/workspace/templatetest/Debug-Tizen-Emulator */
482 while (fgets(buf, BUFFER_MAX, fp) != NULL)
486 for (i = 0; i < BUFFER_MAX; i++)
499 for (; i < BUFFER_MAX; i++)
516 for (; i < BUFFER_MAX - 1; i++)
518 if (*p == ':' || *p == ' ' || *p == '\t')
525 if (strlen(p) <= length)
527 sprintf(strAppInstall, "%s", p);
528 for (i = 0; i < strlen(p); i++)
530 if (strAppInstall[i] == '\n' || strAppInstall[i] == '\t')
532 strAppInstall[i] = '\0';
544 int is_app_built_pie(void)
548 char buf[BUFFER_MAX];
550 if((fp = fopen(DA_BUILD_OPTION, "r")) == NULL)
552 LOGE("Failed to open %s\n", DA_BUILD_OPTION);
556 if(fgets(buf, BUFFER_MAX, fp) != NULL)
558 if(strcmp(buf, "DYN\n") == 0)
560 else if(strcmp(buf, "EXEC\n") == 0)
574 int get_app_base_address(int *baseAddress)
578 char buf[BUFFER_MAX];
580 if((fp = fopen(DA_BASE_ADDRESS, "r")) == NULL)
582 LOGE("Failed to open %s\n", DA_BASE_ADDRESS);
586 if(fgets(buf, BUFFER_MAX, fp) != NULL)
588 res = sscanf(buf, "%x", baseAddress);
599 int is_same_app_process(char* appPath, int pid)
604 char buf[BUFFER_MAX];
605 char cmdPath[PATH_MAX];
606 char tPath[PATH_MAX];
607 char buf_res[PATH_MAX];
608 char tPath_res[PATH_MAX];
610 strcpy(tPath, appPath);
611 tlen = strlen(tPath);
612 if(strcmp(tPath + tlen - 4, ".exe") == 0)
614 // remove .exe from tPath
615 tPath[tlen - 4] = '\0';
618 sprintf(cmdPath, "/proc/%d/cmdline", pid);
620 if((fp = fopen(cmdPath, "r")) == NULL)
625 if(fgets(buf, BUFFER_MAX, fp) != NULL)
628 if(strcmp(buf + tlen - 4, ".exe") == 0)
630 // remove .exe from tPath
631 buf[tlen - 4] = '\0';
634 dereference_tizen_exe_path(buf, buf_res);
635 dereference_tizen_exe_path(tPath, tPath_res);
637 if(strcmp(buf_res, tPath_res) == 0)
647 char *dereference_tizen_exe_path(const char *path, char *resolved)
650 char tmp_path[PATH_MAX];
653 //try resolve <path>.exe
654 sprintf(tmp_path, "%s.exe", path);
655 if ((res = realpath(tmp_path, resolved)) == NULL) {
656 //try to resolve path <path>
657 res = realpath(path, resolved);
663 void fd_setup_smack_attributes(int fd)
665 fsetxattr(fd, "security.SMACK64IPIN", "*", 1, 0);
666 fsetxattr(fd, "security.SMACK64IPOUT", "*", 1, 0);
669 float get_uptime(void)
671 const char *LINUX_UPTIME_FILE = "/proc/uptime";
672 FILE *fp = fopen(LINUX_UPTIME_FILE, "r");
677 if (fscanf(fp, "%f", &uptime) != 1)