4 * Copyright (c) 2000 - 2012 Samsung Electronics Co., Ltd All Rights Reserved
6 * Contact: Kidong Kim <kd0228.kim@samsung.com>
8 * Licensed under the Apache License, Version 2.0 (the "License");
9 * you may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
12 * http://www.apache.org/licenses/LICENSE-2.0
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
26 #include <sys/types.h>
38 #include <sys/smack.h>
39 #include <linux/capability.h>
40 #include <sys/capability.h>
45 #include "privilege-control.h"
46 #include "access-db.h"
52 #define DEVELOPER_GID 5100
53 #define DEVELOPER_UID 5100
55 #define APP_USER_NAME "app"
56 #define DEV_USER_NAME "developer"
58 #define APP_HOME_DIR TOSTRING(HOMEDIR) "/app"
59 #define DEV_HOME_DIR TOSTRING(HOMEDIR) "/developer"
61 #define APP_GROUP_PATH TOSTRING(SHAREDIR) "/app_group_list"
62 #define DEV_GROUP_PATH TOSTRING(SHAREDIR) "/dev_group_list"
64 #define SMACK_SRC_FILE_SUFFIX "_src_file"
65 #define SMACK_SRC_DIR_SUFFIX "_src_dir"
66 #define SMACK_DATA_SUFFIX "_data"
67 #define WRT_BASE_DEVCAP "WRT"
68 #define WRT_CLIENT_PATH "/usr/bin/wrt-client"
70 #define TIZEN_PRIVILEGE_ANTIVIRUS "http://tizen.org/privilege/antivirus"
71 #define TIZEN_PRIVILEGE_APPSETTING "http://tizen.org/privilege/appsetting"
72 #define PATH_RULES_PUBLIC_RO "PATH_RULES_PUBLIC_RO.smack"
73 #define PATH_RULES_GROUP_RW "PATH_RULES_GROUP_RW.smack"
89 typedef int (*label_decision_fn)(const FTSENT*);
95 __attribute__ ((destructor))
96 static void libprivilege_destructor()
98 SECURE_C_LOGD("Entering function: %s.", __func__);
102 API int perm_begin(void)
104 SECURE_C_LOGD("Entering function: %s.", __func__);
105 return rdb_modification_start();
108 API int perm_end(void)
110 SECURE_C_LOGD("Entering function: %s.", __func__);
112 rdb_modification_finish();
114 return PC_OPERATION_SUCCESS;
117 API int control_privilege(void)//deprecated
119 SECURE_C_LOGD("Entering function: %s.", __func__);
121 if(getuid() == APP_UID) // current user is 'app'
122 return PC_OPERATION_SUCCESS;
124 if(perm_app_set_privilege("org.tizen.", NULL, NULL) == PC_OPERATION_SUCCESS)
125 return PC_OPERATION_SUCCESS;
127 C_LOGE("perm_app_set_privilege failed (not permitted).");
128 return PC_ERR_NOT_PERMITTED;
133 * TODO: this function should be moved to libsmack in open-source.
135 API int get_smack_label_from_process(pid_t pid, char *smack_label)
137 SECURE_C_LOGD("Entering function: %s. Params: pid=%i", __func__, pid);
141 int PATH_MAX_LEN = 64;
142 char path[PATH_MAX_LEN + 1];
145 C_LOGE("invalid param pid.");
146 ret = PC_ERR_INVALID_PARAM;
150 if(smack_label == NULL) {
151 C_LOGE("Invalid param smack_label (NULL).");
152 ret = PC_ERR_INVALID_PARAM;
156 bzero(smack_label, SMACK_LABEL_LEN + 1);
157 if (!have_smack()) { // If no smack just return success with empty label
158 C_LOGD("No SMACK. Returning empty label");
159 ret = PC_OPERATION_SUCCESS;
163 bzero(path, PATH_MAX_LEN + 1);
164 snprintf(path, PATH_MAX_LEN, "/proc/%d/attr/current", pid);
165 fd = open(path, O_RDONLY);
167 SECURE_C_LOGE("Cannot open file %s (errno: %s)", path, strerror(errno));
168 ret = PC_ERR_FILE_OPERATION;
172 ret = read(fd, smack_label, SMACK_LABEL_LEN);
174 SECURE_C_LOGE("Cannot read from file %s", path);
175 ret = PC_ERR_FILE_OPERATION;
179 SECURE_C_LOGD("smack_label=%s", smack_label);
181 ret = PC_OPERATION_SUCCESS;
187 API int smack_pid_have_access(pid_t pid,
189 const char *access_type)
191 SECURE_C_LOGD("Entering function: %s. Params: pid=%i, object=%s, access_type=%s",
192 __func__, pid, object, access_type);
195 char pid_subject_label[SMACK_LABEL_LEN + 1];
197 cap_flag_value_t cap_v;
200 C_LOGD("No SMACK. Return access granted");
205 C_LOGE("Invalid pid.");
210 C_LOGE("Invalid object param.");
214 if(access_type == NULL) {
215 C_LOGE("Invalid access_type param");
219 //get SMACK label of process
220 ret = get_smack_label_from_process(pid, pid_subject_label);
221 if (PC_OPERATION_SUCCESS != ret) {
222 SECURE_C_LOGE("get_smack_label_from_process %d failed: %d", pid, ret);
225 SECURE_C_LOGD("pid %d has label: %s", pid, pid_subject_label);
227 // do not call smack_have_access() if label is empty
228 if (pid_subject_label[0] != '\0') {
229 ret = smack_have_access(pid_subject_label, object, access_type);
231 C_LOGE("smack_have_access failed.");
234 if ( 1 == ret ) { // smack_have_access return 1 (access granted)
235 C_LOGD("smack_have_access returned 1 (access granted)");
240 // smack_have_access returned 0 (access denied). Now CAP_MAC_OVERRIDE should be checked
241 C_LOGD("smack_have_access returned 0 (access denied)");
242 cap = cap_get_pid(pid);
244 C_LOGE("cap_get_pid failed");
247 ret = cap_get_flag(cap, CAP_MAC_OVERRIDE, CAP_EFFECTIVE, &cap_v);
249 C_LOGE("cap_get_flag failed");
253 if (cap_v == CAP_SET) {
254 C_LOGD("pid %d has CAP_MAC_OVERRIDE", pid);
258 C_LOGD("pid %d doesn't have CAP_MAC_OVERRIDE", pid);
263 static int set_dac(const char *smack_label, const char *pkg_name)
265 SECURE_C_LOGD("Entering function: %s. Params: smack_label=%s, pkg_name=%s",
266 __func__, smack_label, pkg_name);
268 FILE* fp_group = NULL; // /etc/group
269 uid_t t_uid = -1; // uid of current process
270 gid_t *glist = NULL; // group list
271 gid_t temp_gid = -1; // for group list
272 char buf[10] = {0, }; // contents in group_list file
273 int glist_cnt = 0; // for group list
277 unsigned *additional_gids = NULL;
280 * initialize user structure
282 C_LOGD("Initialize user structure");
283 memset(usr.user_name, 0x00, 10);
284 memset(usr.home_dir, 0x00, 64);
285 memset(usr.group_list, 0x00, 64);
290 C_LOGD("Current uid is %d", t_uid);
292 if(t_uid == 0) // current user is 'root'
294 if(!strncmp(pkg_name, "developer", 9))
296 strncpy(usr.user_name, DEV_USER_NAME, sizeof(usr.user_name));
297 usr.uid = DEVELOPER_UID;
298 usr.gid = DEVELOPER_GID;
299 strncpy(usr.home_dir, DEV_HOME_DIR, sizeof(usr.home_dir));
300 strncpy(usr.group_list, DEV_GROUP_PATH, sizeof(usr.group_list));
304 strncpy(usr.user_name, APP_USER_NAME, sizeof(usr.user_name));
307 strncpy(usr.home_dir, APP_HOME_DIR, sizeof(usr.home_dir));
308 strncpy(usr.group_list, APP_GROUP_PATH, sizeof(usr.group_list));
312 * get group information
314 C_LOGD("Get group information");
315 SECURE_C_LOGD("Opening file %s.", usr.group_list);
316 if(!(fp_group = fopen(usr.group_list, "r")))
318 C_LOGE("fopen failed.");
319 result = PC_ERR_FILE_OPERATION; // return -1
323 while(fgets(buf, 10, fp_group) != NULL)
326 temp_gid = strtoul(buf, 0, 10);
327 if(errno != 0) // error occured during strtoul()
329 C_LOGE("Cannot change string to integer: %s", buf);
330 result = PC_ERR_INVALID_OPERATION;
334 glist = (gid_t*)realloc(glist, sizeof(gid_t) * (glist_cnt + 1));
337 result = PC_ERR_MEM_OPERATION; // return -2
338 C_LOGE("Cannot allocate memory");
341 glist[glist_cnt] = temp_gid;
347 if(NULL != smack_label)
352 result = get_app_gids(smack_label, &additional_gids, &cnt);
353 if (result != PC_OPERATION_SUCCESS)
357 glist_new = (gid_t*)realloc(glist, sizeof(gid_t) * (glist_cnt + cnt));
358 if (glist_new == NULL) {
359 result = PC_ERR_MEM_OPERATION; // return -2
360 C_LOGE("Memory allocation failed");
364 for (i = 0; i < cnt; ++i) {
365 C_LOGD("Additional GID based on enabled permissions: %u", additional_gids[i]);
366 glist[glist_cnt++] = additional_gids[i];
374 C_LOGD("Adding process to the following groups:");
375 for(i=0; i<glist_cnt; ++i) {
376 SECURE_C_LOGD("glist [ %d ] = %d", i, glist[i]);
378 C_LOGD("Calling setgroups()");
379 if(setgroups(glist_cnt, glist) != 0)
381 C_LOGE("setgroups failed");
382 result = PC_ERR_NOT_PERMITTED; // return -3
392 * setuid() & setgid()
394 C_LOGD("setgid( %d ) & setuid( %d )", usr.gid, usr.uid);
395 if(setgid(usr.gid) != 0) // fail
397 C_LOGE("Failed to execute setgid().");
398 result = PC_ERR_INVALID_OPERATION;
401 if(setuid(usr.uid) != 0) // fail
403 C_LOGE("Failed to execute setuid().");
404 result = PC_ERR_INVALID_OPERATION;
408 SECURE_C_LOGD("setenv(): USER = %s, HOME = %s", usr.user_name, usr.home_dir);
409 if(setenv("USER", usr.user_name, 1) != 0) //fail
411 C_LOGE("Failed to execute setenv() [USER].");
412 result = PC_ERR_INVALID_OPERATION;
415 if(setenv("HOME", usr.home_dir, 1) != 0) // fail
417 C_LOGE("Failed to execute setenv() [HOME].");
418 result = PC_ERR_INVALID_OPERATION;
422 else // current user is not only 'root' but 'app'
424 C_LOGE("Current user is NOT root");
425 result = PC_ERR_NOT_PERMITTED; // return -3
429 result = PC_OPERATION_SUCCESS;
436 free(additional_gids);
442 * Get SMACK label from EXEC label of a file.
443 * SMACK label should be freed by caller
445 * @param path file path to take label from
446 * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
448 static int get_smack_from_binary(char **smack_label, const char* path, app_type_t type)
450 SECURE_C_LOGD("Entering function: %s. Params: path=%s, type=%d",
451 __func__, path, type);
455 if (type == PERM_APP_TYPE_WGT
456 || type == PERM_APP_TYPE_WGT_PARTNER
457 || type == PERM_APP_TYPE_WGT_PLATFORM) {
458 ret = smack_lgetlabel(path, smack_label, SMACK_LABEL_EXEC);
460 ret = smack_getlabel(path, smack_label, SMACK_LABEL_EXEC);
463 C_LOGE("Getting exec label from file %s failed", path);
464 return PC_ERR_INVALID_OPERATION;
467 return PC_OPERATION_SUCCESS;
471 * Set process SMACK label.
472 * This function is emulating EXEC label behavior of SMACK for programs
473 * run by dlopen/dlsym instead of execv.
476 * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
478 static int set_smack_for_self (char *smack_label)
480 SECURE_C_LOGD("Entering function: %s. Params: smack_label=%s",
481 __func__, smack_label);
484 if (smack_label == NULL) {
485 /* No label to set, just return with success */
486 C_LOGD("No label to set, just return with success.");
487 ret = PC_OPERATION_SUCCESS;
490 SECURE_C_LOGD("smack_label=%s", smack_label);
492 ret = smack_set_label_for_self(smack_label);
493 C_LOGD("smack_set_label_for_self returned %d", ret);
495 ret = PC_OPERATION_SUCCESS;
501 static int is_widget(const char* path)
503 SECURE_C_LOGD("Entering function: %s. Params: path=%s",
505 char buf[sizeof(WRT_CLIENT_PATH)];
508 ret = readlink(path, buf, sizeof(WRT_CLIENT_PATH));
510 C_LOGD("readlink(%s) returned error: %s. Assuming that app is not a widget", path, strerror(errno));
511 else if (ret == sizeof(WRT_CLIENT_PATH))
512 C_LOGD("%s is not a widget", path);
513 if (ret == -1 || ret == sizeof(WRT_CLIENT_PATH))
516 C_LOGD("buf=%s", buf);
518 ret = !strcmp(WRT_CLIENT_PATH, buf);
519 C_LOGD("%s is %s widget", path, ret ? "a" : "not a");
524 * Partially verify, that the type given for app is correct.
525 * This function will use some heuristics to check whether the app type is right.
526 * It is intended for security hardening to catch privilege setting for the
527 * app type not corresponding to the actual binary.
528 * Beware - when it detects an anomaly, the whole process will be terminated.
530 * @param type claimed application type
531 * @param path file path to executable
532 * @return return void on success, terminate the process on error
534 static app_type_t verify_app_type(const char* type, const char* path)
536 SECURE_C_LOGD("Entering function: %s. Params: type=%s, path=%s",
537 __func__, type, path);
539 /* TODO: this should actually be treated as error, but until the old
540 * set_privilege API is removed, it must be ignored */
542 C_LOGD("PKG_TYPE_OTHER");
543 return APP_TYPE_OTHER; /* good */
546 if (is_widget(path)) {
547 if (!strcmp(type, "wgt")) {
548 C_LOGD("PKG_TYPE_WGT");
549 return PERM_APP_TYPE_WGT; /* good */
550 } else if (!strcmp(type, "wgt_partner")) {
551 C_LOGD("PKG_TYPE_WGT_PARTNER");
552 return PERM_APP_TYPE_WGT_PARTNER; /* good */
553 } else if (!strcmp(type, "wgt_platform")) {
554 C_LOGD("PKG_TYPE_WGT_PLATFORM");
555 return PERM_APP_TYPE_WGT_PLATFORM; /* good */
559 if (type == NULL || (strcmp(type, "wgt")
560 && strcmp(type, "wgt_partner")
561 && strcmp(type, "wgt_platform"))){
562 C_LOGD("PKG_TYPE_OTHER");
563 return PERM_APP_TYPE_OTHER; /* good */
568 C_LOGE("EXIT_FAILURE");
572 API int set_app_privilege(const char* name, const char* type, const char* path)//deprecated
574 SECURE_C_LOGD("Entering function: %s. Params: name=%s, type=%s, path=%s",
575 __func__, name, type, path);
577 return perm_app_set_privilege(name, type, path);
580 API int perm_app_set_privilege(const char* name, const char* type, const char* path)
582 SECURE_C_LOGD("Entering function: %s. Params: name=%s, type=%s, path=%s",
583 __func__, name, type, path);
585 //SECURE_C_LOGD("Function params: name = %s, type = %s, path = %s", name, type, path);
586 int ret = PC_OPERATION_SUCCESS;
587 char *smack_label AUTO_FREE;
590 C_LOGE("Error invalid parameter");
591 return PC_ERR_INVALID_PARAM;
594 if (path != NULL && have_smack()) {
595 ret = get_smack_from_binary(&smack_label, path, verify_app_type(type, path));
596 if (ret != PC_OPERATION_SUCCESS)
599 ret = set_smack_for_self(smack_label);
600 if (ret != PC_OPERATION_SUCCESS)
604 if (path != NULL && !have_smack()) {
605 ret = get_smack_from_binary(&smack_label, path, verify_app_type(type, path));
606 if (ret != PC_OPERATION_SUCCESS)
610 return set_dac(smack_label, name);
613 API int set_privilege(const char* pkg_name)//deprecated
615 SECURE_C_LOGD("Entering function: %s. Params: pkg_name=%s",
618 return perm_app_set_privilege(pkg_name, NULL, NULL);
621 static int perm_file_path(char** path, app_type_t app_type, const char* perm, const char *suffix, bool is_early)
623 SECURE_C_LOGD("Entering function: %s. Params: app_type=%d, perm=%s, suffix=%s, is_early=%d",
624 __func__, app_type, perm, suffix, is_early);
626 const char* app_type_prefix = NULL;
627 char* perm_basename = NULL;
630 if (perm == NULL || strlen(perm) == 0) {
631 C_LOGE("Empty permission name.");
632 return PC_ERR_INVALID_PARAM;
635 app_type_prefix = app_type_group_name(app_type);
637 ret = base_name_from_perm(perm, &perm_basename);
638 if (ret != PC_OPERATION_SUCCESS) {
639 C_LOGE("Couldn't get permission basename.");
644 ret = asprintf(path, TOSTRING(SHAREDIR) "/%s%s%s%s%s",
645 app_type_prefix ? app_type_prefix : "", app_type_prefix ? "_" : "",
646 perm_basename, "_early", suffix);
649 ret = asprintf(path, TOSTRING(SHAREDIR) "/%s%s%s%s",
650 app_type_prefix ? app_type_prefix : "", app_type_prefix ? "_" : "",
651 perm_basename, suffix);
654 C_LOGE("asprintf failed.");
655 return PC_ERR_MEM_OPERATION;
658 C_LOGD("Path=%s", *path);
660 return PC_OPERATION_SUCCESS;
663 static int perm_to_dac(const char* app_label, app_type_t app_type, const char* perm)
665 SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, app_type=%d, perm=%s",
666 __func__, app_label, app_type, perm);
669 char* path AUTO_FREE;
670 FILE* file AUTO_FCLOSE;
673 ret = perm_file_path(&path, app_type, perm, ".dac", 0);
674 if (ret != PC_OPERATION_SUCCESS) {
675 C_LOGD("No dac config file for permission %s", perm);
679 SECURE_C_LOGD("Opening file %s.", path);
680 file = fopen(path, "r");
682 C_LOGW("fopen failed.");
683 return PC_OPERATION_SUCCESS;
686 while (fscanf(file, "%d\n", &gid) == 1) {
687 SECURE_C_LOGD("Adding app_id %s to group %d", app_label, gid);
688 ret = add_app_gid(app_label, gid);
689 if (ret != PC_OPERATION_SUCCESS) {
690 C_LOGE("add_app_gid failed");
695 return PC_OPERATION_SUCCESS;
698 static int label_all(const FTSENT* ftsent UNUSED)
700 SECURE_C_LOGD("Entering function: %s.", __func__);
702 return DECISION_LABEL;
705 static int label_execs(const FTSENT* ftsent)
707 SECURE_C_LOGD("Entering function: %s.", __func__);
709 C_LOGD("Mode = %d", ftsent->fts_statp->st_mode);
710 // label only regular executable files
711 if (S_ISREG(ftsent->fts_statp->st_mode) && (ftsent->fts_statp->st_mode & S_IXUSR))
712 return DECISION_LABEL;
713 return DECISION_SKIP;
716 static int label_dirs(const FTSENT* ftsent)
718 SECURE_C_LOGD("Entering function: %s.", __func__);
720 // label only directories
721 if (S_ISDIR(ftsent->fts_statp->st_mode))
722 return DECISION_LABEL;
723 return DECISION_SKIP;
726 static int label_links_to_execs(const FTSENT* ftsent)
728 SECURE_C_LOGD("Entering function: %s.", __func__);
731 char* target AUTO_FREE;
733 // check if it's a link
734 if ( !S_ISLNK(ftsent->fts_statp->st_mode))
735 return DECISION_SKIP;
737 target = realpath(ftsent->fts_path, NULL);
739 SECURE_C_LOGE("Getting link target for %s failed (Error = %s)", ftsent->fts_path, strerror(errno));
740 return PC_ERR_FILE_OPERATION;
742 if (-1 == stat(target, &buf)) {
743 SECURE_C_LOGE("stat failed for %s (Error = %s", target, strerror(errno));
744 return PC_ERR_FILE_OPERATION;
746 // skip if link target is not a regular executable file
747 if (buf.st_mode != (buf.st_mode | S_IXUSR | S_IFREG)) {
748 SECURE_C_LOGD("%s is not a regular executable file. Skipping.", target);
749 return DECISION_SKIP;
752 return DECISION_LABEL;
755 static int dir_set_smack_r(const char *path, const char* label,
756 enum smack_label_type type, label_decision_fn fn)
758 SECURE_C_LOGD("Entering function: %s. Params: path=%s, label=%s, type=%d",
759 __func__, path, label, type);
761 const char* path_argv[] = {path, NULL};
762 FTS *fts AUTO_FTS_CLOSE;
766 fts = fts_open((char * const *) path_argv, FTS_PHYSICAL | FTS_NOCHDIR, NULL);
768 C_LOGE("fts_open failed.");
769 return PC_ERR_FILE_OPERATION;
772 while ((ftsent = fts_read(fts)) != NULL) {
773 /* Check for error (FTS_ERR) or failed stat(2) (FTS_NS) */
774 if (ftsent->fts_info == FTS_ERR || ftsent->fts_info == FTS_NS) {
775 C_LOGE("FTS_ERR error or failed stat(2) (FTS_NS)");
776 return PC_ERR_FILE_OPERATION;
781 C_LOGE("fn(ftsent) failed.");
785 if (ret == DECISION_LABEL) {
786 C_LOGD("smack_lsetlabel (label: %s (type: %d), path: %s)", label, type, ftsent->fts_path);
787 if (smack_lsetlabel(ftsent->fts_path, label, type) != 0) {
788 C_LOGE("smack_lsetlabel failed.");
789 return PC_ERR_FILE_OPERATION;
794 /* If last call to fts_read() set errno, we need to return error. */
796 C_LOGE("Last errno from fts_read: %s", strerror(errno));
797 return PC_ERR_FILE_OPERATION;
799 return PC_OPERATION_SUCCESS;
801 API char* app_id_from_socket(int sockfd)//deprecated
803 SECURE_C_LOGD("Entering function: %s. Params: sockfd=%d",
806 return perm_app_id_from_socket(sockfd);
809 API char* perm_app_id_from_socket(int sockfd)
811 SECURE_C_LOGD("Entering function: %s. Params: sockfd=%d",
815 C_LOGD("No SMACK. Returning NULL.");
822 ret = smack_new_label_from_socket(sockfd, &app_id);
824 C_LOGE("smack_new_label_from_socket failed");
828 SECURE_C_LOGD("app_id = %s", app_id);
834 static int app_add_permissions_internal(const char* app_id, app_type_t app_type, const char** perm_list, int permanent)
836 SECURE_C_LOGD("Entering function: %s. Params: app_id=%s, app_type=%d, permanent=%d",
837 __func__, app_id, app_type, permanent);
840 char* smack_path AUTO_FREE;
841 char* smack_path_early AUTO_FREE;
843 int fd_early AUTO_CLOSE;
844 struct smack_accesses *smack AUTO_SMACK_FREE;
845 struct smack_accesses *smack_early AUTO_SMACK_FREE;
847 if (!smack_label_is_valid(app_id)) {
848 C_LOGE("Invalid param app_id.");
849 return PC_ERR_INVALID_PARAM;
852 if(perm_list == NULL) {
853 C_LOGE("Invalid perm_list (NULL).");
854 return PC_ERR_INVALID_PARAM;
857 if (app_type_group_name(app_type) == NULL) {
858 C_LOGE("Unknown app type.");
859 return PC_ERR_INVALID_PARAM;
862 // Add permission to DAC
863 for (i = 0; perm_list[i] != NULL; ++i) {
864 ret = perm_to_dac(app_id, app_type, perm_list[i]);
865 if (ret != PC_OPERATION_SUCCESS){
866 C_LOGE("perm_to_dac failed");
871 // Enable the permissions:
872 ret = rdb_enable_app_permissions(app_id,
876 if (ret != PC_OPERATION_SUCCESS) {
877 C_LOGE("RDB rdb_enable_app_permissions failed with: %d", ret);
882 SECURE_C_LOGD("Leaving function: %s. Params: app_id=%s, app_type=%d, permanent=%d",
883 __func__, app_id, app_type, permanent);
885 return PC_OPERATION_SUCCESS;
888 API int app_add_permissions(const char* app_id, const char** perm_list)//deprecated
890 SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
893 return app_add_permissions_internal(app_id, APP_TYPE_OTHER, perm_list, 1);
896 API int app_add_volatile_permissions(const char* app_id, const char** perm_list)//deprecated
898 SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
901 return app_add_permissions_internal(app_id, APP_TYPE_OTHER, perm_list, 0);
904 API int app_enable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list, bool persistent)//deprecated
906 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d, persistent=%d",
907 __func__, pkg_id, app_type, persistent);
909 return app_add_permissions_internal(pkg_id, app_type, perm_list, persistent);
912 API int perm_app_enable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list, bool persistent)
914 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d, persistent=%d",
915 __func__, pkg_id, app_type, persistent);
917 return app_add_permissions_internal(pkg_id, app_type, perm_list, persistent);
920 API int app_disable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list)//deprecated
922 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d",
923 __func__, pkg_id, app_type);
925 return perm_app_disable_permissions(pkg_id, app_type, perm_list);
928 /* FIXME: this function is only a stub */
929 API int perm_app_disable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list)
931 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d",
932 __func__, pkg_id, app_type);
935 if (!smack_label_is_valid(pkg_id)) {
936 C_LOGE("Invalid param app_id.");
937 return PC_ERR_INVALID_PARAM;
940 if (perm_list == NULL) {
941 C_LOGE("Invalid perm_list (NULL).");
942 return PC_ERR_INVALID_PARAM;
945 if (app_type_group_name(app_type) == NULL) {
946 C_LOGE("Unknown app type.");
947 return PC_ERR_INVALID_PARAM;
950 ret = rdb_disable_app_permissions(pkg_id, app_type, perm_list);
951 if (ret != PC_OPERATION_SUCCESS) {
952 C_LOGE("RDB rdb_disable_app_permissions failed with: %d", ret);
956 return PC_OPERATION_SUCCESS;
959 API int app_revoke_permissions(const char* pkg_id)//deprecated
961 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
962 return perm_app_revoke_permissions(pkg_id);
965 API int perm_app_revoke_permissions(const char* pkg_id)
967 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
970 if (!smack_label_is_valid(pkg_id)) {
971 C_LOGE("Invalid param app_id.");
972 return PC_ERR_INVALID_PARAM;
975 ret = rdb_revoke_app_permissions(pkg_id);
976 if (ret != PC_OPERATION_SUCCESS) {
977 C_LOGE("RDB rdb_disable_app_permissions failed with: %d", ret);
981 return PC_OPERATION_SUCCESS;
984 API int app_reset_permissions(const char* pkg_id)//deprecated
986 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
989 return perm_app_reset_permissions(pkg_id);
992 API int perm_app_reset_permissions(const char* pkg_id)
994 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
998 if (!smack_label_is_valid(pkg_id)) {
999 C_LOGE("Invalid param pkg_id.");
1000 return PC_ERR_INVALID_PARAM;
1003 ret = rdb_reset_app_permissions(pkg_id);
1004 if (ret != PC_OPERATION_SUCCESS) {
1005 C_LOGE("RDB rdb_disable_app_permissions failed with: %d", ret);
1009 return PC_OPERATION_SUCCESS;
1012 API int app_label_dir(const char* label, const char* path)//deprecated
1014 SECURE_C_LOGD("Entering function: %s. Params: label=%s, path=%s",
1015 __func__, label, path);
1017 int ret = PC_OPERATION_SUCCESS;
1020 C_LOGE("Invalid argument path (NULL).");
1021 return PC_ERR_INVALID_PARAM;
1024 if (!smack_label_is_valid(label)) {
1025 C_LOGE("Invalid param label.");
1026 return PC_ERR_INVALID_PARAM;
1029 //setting access label on everything in given directory and below
1030 ret = dir_set_smack_r(path, label, SMACK_LABEL_ACCESS, &label_all);
1031 if (PC_OPERATION_SUCCESS != ret)
1033 C_LOGE("dir_set_smack_r failed.");
1037 //setting execute label for everything with permission to execute
1038 ret = dir_set_smack_r(path, label, SMACK_LABEL_EXEC, &label_execs);
1039 if (PC_OPERATION_SUCCESS != ret)
1041 C_LOGE("dir_set_smack_r failed.");
1045 //setting execute label for everything with permission to execute
1046 ret = dir_set_smack_r(path, label, SMACK_LABEL_EXEC, &label_links_to_execs);
1051 API int app_label_shared_dir(const char* app_label, const char* shared_label, const char* path)//deprecated
1053 SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, shared_label=%s, path=%s",
1054 __func__, app_label, shared_label, path);
1058 C_LOGE("Invalid param path.");
1059 return PC_ERR_INVALID_PARAM;
1062 if(!smack_label_is_valid(app_label)) {
1063 C_LOGE("Invalid param app_label");
1064 return PC_ERR_INVALID_PARAM;
1067 if(!smack_label_is_valid(shared_label)) {
1068 C_LOGE("Invalid param shared_label");
1069 return PC_ERR_INVALID_PARAM;
1072 if (strcmp(app_label, shared_label) == 0) {
1073 C_LOGE("app_label equals shared_label");
1074 return PC_ERR_INVALID_PARAM;
1077 //setting label on everything in given directory and below
1078 ret = dir_set_smack_r(path, shared_label, SMACK_LABEL_ACCESS, label_all);
1079 if(ret != PC_OPERATION_SUCCESS){
1080 C_LOGE("dir_set_smack_r failed.");
1084 //setting transmute on dir
1085 ret = dir_set_smack_r(path, "1", SMACK_LABEL_TRANSMUTE, label_dirs);
1086 if (ret != PC_OPERATION_SUCCESS) {
1087 C_LOGE("dir_set_smack_r failed");
1091 return PC_OPERATION_SUCCESS;
1094 API int add_shared_dir_readers(const char* shared_label UNUSED, const char** app_list UNUSED)//deprecated
1096 SECURE_C_LOGD("Entering function: %s. Params: shared_label=%s",
1097 __func__, shared_label);
1099 C_LOGE("add_shared_dir_readers is deprecated and unimplemented!");
1101 // TODO: This function is not implemented with RDB.
1102 return PC_ERR_INVALID_OPERATION;
1105 static char* smack_label_for_path(const char *app_id, const char *path)
1107 SECURE_C_LOGD("Entering function: %s. Params: app_id=%s, path=%s",
1108 __func__, app_id, path);
1110 char *salt AUTO_FREE;
1114 /* Prefix $1$ causes crypt() to use MD5 function */
1115 if (-1 == asprintf(&salt, "$1$%s", app_id)) {
1116 C_LOGE("asprintf failed");
1120 label = crypt(path, salt);
1121 if (label == NULL) {
1122 C_LOGE("crypt failed");
1126 /* crypt() output may contain slash character,
1127 * which is not legal in Smack labels */
1128 for (x = label; *x; ++x) {
1136 /* FIXME: remove this pragma once deprecated API is deleted */
1137 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1138 static int perm_app_setup_path_internal(const char* pkg_id, const char* path, app_path_type_t app_path_type, va_list ap)
1140 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, path=%s, app_path_type=%d",
1141 __func__, pkg_id, path, app_path_type);
1144 C_LOGE("Invalid argument path.");
1145 return PC_ERR_INVALID_PARAM;
1148 if (!smack_label_is_valid(pkg_id)) {
1149 C_LOGE("Invalid pkg_id.");
1150 SECURE_C_LOGE("Invalid pkg_id %s", pkg_id);
1151 return PC_ERR_INVALID_PARAM;
1154 switch (app_path_type) {
1155 case APP_PATH_PRIVATE:
1156 C_LOGD("app_path_type is APP_PATH_PRIVATE.");
1157 return app_label_dir(pkg_id, path);
1159 case APP_PATH_GROUP: {
1160 C_LOGD("app_path_type is APP_PATH_GROUP.");
1162 const char *shared_label;
1164 shared_label = va_arg(ap, const char *);
1166 if (!smack_label_is_valid(shared_label)) {
1167 C_LOGE("Invalid shared_label.");
1168 return PC_ERR_INVALID_PARAM;
1171 if (strcmp(pkg_id, shared_label) == 0) {
1172 C_LOGE("pkg_id equals shared_label.");
1173 return PC_ERR_INVALID_PARAM;
1176 ret = app_label_shared_dir(pkg_id, shared_label, path);
1177 if (ret != PC_OPERATION_SUCCESS) {
1178 C_LOGE("app_label_shared_dir failed: %d", ret);
1182 // Add the path to the database:
1183 ret = rdb_add_path(pkg_id, shared_label, path, "rwxatl", "GROUP_PATH");
1184 if (ret != PC_OPERATION_SUCCESS) {
1185 C_LOGE("RDB rdb_add_path failed with: %d", ret);
1189 return PC_OPERATION_SUCCESS;
1192 case APP_PATH_PUBLIC: {
1193 C_LOGD("app_path_type is APP_PATH_PUBLIC.");
1194 char **app_ids AUTO_FREE;
1198 C_LOGD("New public RO path %s", path);
1201 label = smack_label_for_path(pkg_id, path);
1202 if (label == NULL) {
1203 C_LOGE("smack_label_for_path failed.");
1204 return PC_ERR_INVALID_OPERATION;
1206 C_LOGD("Generated label '%s' for public RO path %s", label, path);
1208 ret = app_label_shared_dir(pkg_id, label, path);
1209 if (ret != PC_OPERATION_SUCCESS) {
1210 C_LOGE("app_label_shared_dir failed.");
1214 // Add the path to the database:
1215 ret = rdb_add_path(pkg_id, label, path, "rwxatl", "PUBLIC_PATH");
1216 if (ret != PC_OPERATION_SUCCESS) {
1217 C_LOGE("RDB rdb_add_path failed with: %d", ret);
1221 return PC_OPERATION_SUCCESS;
1224 case APP_PATH_SETTINGS: {
1225 C_LOGD("app_path_type is APP_PATH_SETTINGS.");
1226 char **app_ids AUTO_FREE;
1231 label = smack_label_for_path(pkg_id, path);
1232 if (label == NULL) {
1233 C_LOGE("smack_label_for_path failed.");
1234 return PC_ERR_INVALID_OPERATION;
1236 C_LOGD("Appsetting: generated label '%s' for setting path %s", label, path);
1238 /*set id for path and all subfolders*/
1239 ret = app_label_shared_dir(pkg_id, label, path);
1240 if (ret != PC_OPERATION_SUCCESS) {
1241 C_LOGE("Appsetting: app_label_shared_dir failed (%d)", ret);
1245 // Add the path to the database:
1246 ret = rdb_add_path(pkg_id, label, path, "rwxatl", "SETTINGS_PATH");
1247 if (ret != PC_OPERATION_SUCCESS) {
1248 C_LOGE("RDB rdb_add_path failed with: %d", ret);
1252 return PC_OPERATION_SUCCESS;
1255 case APP_PATH_ANY_LABEL: {
1256 C_LOGD("app_path_type is APP_PATH_ANY_LABEL.");
1257 const char *label = NULL;
1258 label = va_arg(ap, const char *);
1259 return app_label_dir(label, path);
1263 C_LOGE("app_path_type is invalid.");
1264 return PC_ERR_INVALID_PARAM;
1267 return PC_OPERATION_SUCCESS;
1269 /* FIXME: remove this pragma once deprecated API is deleted */
1270 #pragma GCC diagnostic warning "-Wdeprecated-declarations"
1272 API int app_setup_path(const char* pkg_id, const char* path, app_path_type_t app_path_type, ...)//deprecated
1274 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, path=%s, app_path_type=%d",
1275 __func__, pkg_id, path, app_path_type);
1279 va_start( ap, app_path_type );
1280 ret = perm_app_setup_path_internal( pkg_id, path, app_path_type, ap );
1286 API int perm_app_setup_path(const char* pkg_id, const char* path, app_path_type_t app_path_type, ...)
1288 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, path=%s, app_path_type=%d",
1289 __func__, pkg_id, path, app_path_type);
1293 va_start( ap, app_path_type );
1294 ret = perm_app_setup_path_internal( pkg_id, path, app_path_type, ap );
1299 API int app_add_friend(const char* pkg_id1, const char* pkg_id2)//deprecated
1301 SECURE_C_LOGD("Entering function: %s. Params: pkg_id1=%s, pkg_id2=%s",
1302 __func__, pkg_id1, pkg_id2);
1304 return perm_app_add_friend(pkg_id1, pkg_id2);
1307 API int perm_app_add_friend(const char* pkg_id1 UNUSED, const char* pkg_id2 UNUSED)
1309 SECURE_C_LOGD("Entering function: %s. Params: pkg_id1=%s, pkg_id2=%s",
1310 __func__, pkg_id1, pkg_id2);
1312 C_LOGE("app_register_av is deprecated and unimplemented!");
1314 // TODO: This function is not implemented with RDB.
1315 return PC_ERR_INVALID_OPERATION;
1318 API int app_install(const char* pkg_id)//deprecated
1320 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
1323 return perm_app_install(pkg_id);
1326 API int perm_app_install(const char* pkg_id)
1328 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
1332 char* smack_path AUTO_FREE;
1333 struct smack_accesses *smack AUTO_SMACK_FREE;
1336 if(ret != PC_OPERATION_SUCCESS) {
1337 C_LOGE("RDB perm_begin failed with: %d", ret);
1341 if (!smack_label_is_valid(pkg_id)) {
1342 C_LOGE("Invalid param pkg_id.");
1343 return PC_ERR_INVALID_PARAM;
1346 // Add application to the database:
1347 ret = rdb_add_application(pkg_id);
1348 if (ret != PC_OPERATION_SUCCESS) {
1349 C_LOGE("RDB rdb_add_application failed with: %d", ret);
1353 return PC_OPERATION_SUCCESS;
1356 API int app_uninstall(const char* pkg_id)//deprecated
1358 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
1361 return perm_app_uninstall(pkg_id);
1364 API int perm_app_uninstall(const char* pkg_id)
1366 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
1367 char* smack_path AUTO_FREE;
1370 if (!smack_label_is_valid(pkg_id)) {
1371 C_LOGE("Invalid param pkg_id.");
1372 return PC_ERR_INVALID_PARAM;
1375 // Remove application from the database
1376 ret = rdb_remove_application(pkg_id);
1377 if (ret != PC_OPERATION_SUCCESS) {
1378 C_LOGE("RDB rdb_remove_application failed with: %d", ret);
1382 return PC_OPERATION_SUCCESS;
1385 static int save_gids(FILE* file, const gid_t* list_of_db_gids, size_t list_size) {
1387 SECURE_C_LOGD("Entering function: %s.", __func__);
1388 int ret = PC_OPERATION_SUCCESS;
1393 C_LOGE("Unable to create file. Error: %s", strerror(errno));
1394 return PC_ERR_FILE_OPERATION; // TODO remove smack accesses?
1397 if(-1 == fchmod(fileno(file), 0644)) {
1398 C_LOGE("Unable to chmod file. Error: %s", strerror(errno));
1399 return PC_ERR_FILE_OPERATION;
1402 for (i = 0; i < list_size ; ++i) {
1403 written = fprintf(file, "%u\n", list_of_db_gids[i]);
1405 C_LOGE("fprintf failed for file. Error: %s", strerror(errno));
1406 ret = PC_ERR_FILE_OPERATION;
1413 API int add_api_feature(app_type_t app_type,
1414 const char* api_feature_name,
1415 const char** smack_rules,
1416 const gid_t* list_of_db_gids,
1417 size_t list_size)//deprecated
1419 SECURE_C_LOGD("Entering function: %s. Params: app_type=%d, api_feature_name=%s",
1420 __func__, app_type, api_feature_name);
1422 return perm_add_api_feature(app_type, api_feature_name, smack_rules, list_of_db_gids, list_size);
1425 API int perm_add_api_feature(app_type_t app_type,
1426 const char* api_feature_name,
1427 const char** smack_rules,
1428 const gid_t* list_of_db_gids,
1430 SECURE_C_LOGD("Entering function: %s. Params: app_type=%d, api_feature_name=%s",
1431 __func__, app_type, api_feature_name);
1433 int ret = PC_OPERATION_SUCCESS;
1434 char* smack_file AUTO_FREE;
1435 char* dac_file AUTO_FREE;
1436 char * base_api_feature_name AUTO_FREE;
1438 // struct smack_accesses* accesses = NULL;
1439 const char *s_type_name = app_type_name(app_type);
1441 // Check input values
1442 if (s_type_name == NULL || !strcmp(s_type_name, "")) {
1443 C_LOGE("Unknown api type");
1444 return PC_ERR_INVALID_PARAM;
1447 if (api_feature_name == NULL || strlen(api_feature_name) == 0) {
1448 C_LOGE("Api feature name is empty.");
1449 return PC_ERR_INVALID_PARAM;
1452 if (smack_rules && ((ret = validate_all_rules(smack_rules) ) != PC_OPERATION_SUCCESS) ) {
1453 C_LOGE("Error in rules list.");
1457 // check .dac existence only if gids are supported
1458 if (list_of_db_gids && list_size > 0) {
1459 // get feature DAC file name
1460 ret = perm_file_path(&dac_file, app_type, api_feature_name, ".dac", 0);
1461 if (ret != PC_OPERATION_SUCCESS || !dac_file ) {
1462 C_LOGE("perm_file_path failed.");
1469 // go through gid list
1470 if (ret == PC_OPERATION_SUCCESS && list_of_db_gids && list_size > 0) {
1472 SECURE_C_LOGD("Opening file %s.", dac_file);
1473 file = fopen(dac_file, "w+");
1474 ret = save_gids(file, list_of_db_gids, list_size);
1475 if(file) fclose(file);
1478 // remove file in case of failure
1479 if (ret != PC_OPERATION_SUCCESS && dac_file) {
1483 ret = base_name_from_perm(api_feature_name, &base_api_feature_name);
1484 if (ret != PC_OPERATION_SUCCESS){
1485 C_LOGE("Error during creating base name: ", ret);
1489 // Save api feature to the database.
1490 ret = rdb_add_permission_rules(base_api_feature_name, s_type_name, smack_rules);
1491 if (ret != PC_OPERATION_SUCCESS) {
1492 C_LOGE("RDB rdb_add_permission_rules failed with: %d", ret);
1500 * This function is marked as deprecated and will be removed
1502 API int app_register_av(const char* app_av_id UNUSED)//deprecated
1504 SECURE_C_LOGD("Entering function: %s. Params: app_av_id=%s",
1505 __func__, app_av_id);
1507 C_LOGE("app_register_av is deprecated and unimplemented!");
1509 // TODO: This function is not implemented with RDB.
1510 return PC_ERR_INVALID_OPERATION;
1513 API int perm_add_additional_rules(const char** smack_rules){
1514 SECURE_C_LOGD("Entering function: %s.", __func__);
1517 C_LOGE("smack_rules is NULL");
1518 return PC_ERR_INVALID_PARAM;
1521 ret = rdb_add_additional_rules(smack_rules);
1522 if (ret != PC_OPERATION_SUCCESS) {
1523 C_LOGE("RDB rdb_add_additional_rules failed with: %d", ret);
1527 return PC_OPERATION_SUCCESS;