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 return rdb_modification_finish();
115 API int perm_rollback(void)
117 SECURE_C_LOGD("Entering function: %s.", __func__);
119 int ret = rdb_modification_rollback();
121 if (ret != PC_OPERATION_SUCCESS) {
122 C_LOGE("RDB %s failed with: %d", __func__, ret);
126 return PC_OPERATION_SUCCESS;
129 API int control_privilege(void)//deprecated
131 SECURE_C_LOGD("Entering function: %s.", __func__);
133 if(getuid() == APP_UID) // current user is 'app'
134 return PC_OPERATION_SUCCESS;
136 if(perm_app_set_privilege("org.tizen.", NULL, NULL) == PC_OPERATION_SUCCESS)
137 return PC_OPERATION_SUCCESS;
139 C_LOGE("perm_app_set_privilege failed (not permitted).");
140 return PC_ERR_NOT_PERMITTED;
145 * TODO: this function should be moved to libsmack in open-source.
147 API int get_smack_label_from_process(pid_t pid, char *smack_label)
149 SECURE_C_LOGD("Entering function: %s. Params: pid=%i", __func__, pid);
153 int PATH_MAX_LEN = 64;
154 char path[PATH_MAX_LEN + 1];
157 C_LOGE("invalid param pid.");
158 ret = PC_ERR_INVALID_PARAM;
162 if(smack_label == NULL) {
163 C_LOGE("Invalid param smack_label (NULL).");
164 ret = PC_ERR_INVALID_PARAM;
168 bzero(smack_label, SMACK_LABEL_LEN + 1);
169 if (!have_smack()) { // If no smack just return success with empty label
170 C_LOGD("No SMACK. Returning empty label");
171 ret = PC_OPERATION_SUCCESS;
175 bzero(path, PATH_MAX_LEN + 1);
176 snprintf(path, PATH_MAX_LEN, "/proc/%d/attr/current", pid);
177 fd = open(path, O_RDONLY);
179 SECURE_C_LOGE("Cannot open file %s (errno: %s)", path, strerror(errno));
180 ret = PC_ERR_FILE_OPERATION;
184 ret = read(fd, smack_label, SMACK_LABEL_LEN);
186 SECURE_C_LOGE("Cannot read from file %s", path);
187 ret = PC_ERR_FILE_OPERATION;
191 SECURE_C_LOGD("smack_label=%s", smack_label);
193 ret = PC_OPERATION_SUCCESS;
199 API int smack_pid_have_access(pid_t pid,
201 const char *access_type)
203 SECURE_C_LOGD("Entering function: %s. Params: pid=%i, object=%s, access_type=%s",
204 __func__, pid, object, access_type);
207 char pid_subject_label[SMACK_LABEL_LEN + 1];
209 cap_flag_value_t cap_v;
212 C_LOGD("No SMACK. Return access granted");
217 C_LOGE("Invalid pid.");
222 C_LOGE("Invalid object param.");
226 if(access_type == NULL) {
227 C_LOGE("Invalid access_type param");
231 //get SMACK label of process
232 ret = get_smack_label_from_process(pid, pid_subject_label);
233 if (PC_OPERATION_SUCCESS != ret) {
234 SECURE_C_LOGE("get_smack_label_from_process %d failed: %d", pid, ret);
237 SECURE_C_LOGD("pid %d has label: %s", pid, pid_subject_label);
239 // do not call smack_have_access() if label is empty
240 if (pid_subject_label[0] != '\0') {
241 ret = smack_have_access(pid_subject_label, object, access_type);
243 C_LOGE("smack_have_access failed.");
246 if ( 1 == ret ) { // smack_have_access return 1 (access granted)
247 C_LOGD("smack_have_access returned 1 (access granted)");
252 // smack_have_access returned 0 (access denied). Now CAP_MAC_OVERRIDE should be checked
253 C_LOGD("smack_have_access returned 0 (access denied)");
254 cap = cap_get_pid(pid);
256 C_LOGE("cap_get_pid failed");
259 ret = cap_get_flag(cap, CAP_MAC_OVERRIDE, CAP_EFFECTIVE, &cap_v);
261 C_LOGE("cap_get_flag failed");
265 if (cap_v == CAP_SET) {
266 C_LOGD("pid %d has CAP_MAC_OVERRIDE", pid);
270 C_LOGD("pid %d doesn't have CAP_MAC_OVERRIDE", pid);
277 static int get_user_groups(uid_t user_id, int *nbgroup, gid_t **groups_list)
279 gid_t *groups = NULL;
281 C_LOGD("Enter function: %s", __func__);
283 if ((!groups_list) || (!nbgroup))
284 return PC_ERR_INVALID_OPERATION;
285 pw = getpwuid(user_id);
287 C_LOGE("getgrouplist fails : Invalid User ID %d",user_id);
288 return PC_ERR_INVALID_OPERATION;
291 //First call is done with *ngroup = 0 to get the number of groups found for the user (Usefull for next malloc operation). It should return -1 in this case.
292 if (getgrouplist(pw->pw_name, pw->pw_gid, groups, nbgroup) != -1)
293 return PC_ERR_INVALID_OPERATION;
295 C_LOGD("getgrouplist %s user is member of %d groups ",pw->pw_name,*nbgroup);
296 groups = malloc(*nbgroup * sizeof (gid_t));
298 return PC_ERR_INVALID_OPERATION;
299 //Second call is done with the suitable ngroup value and structure groups allocated.
300 if (getgrouplist(pw->pw_name, pw->pw_gid, groups, nbgroup) == -1) {
302 C_LOGE("getgrouplist fails %d",nbgroup);
303 return PC_ERR_INVALID_OPERATION;
305 *groups_list = groups;
306 return PC_OPERATION_SUCCESS;
309 static int set_dac(const char *smack_label, const char *pkg_name)
311 SECURE_C_LOGD("Entering function: %s. Params: smack_label=%s, pkg_name=%s",
312 __func__, smack_label, pkg_name);
314 uid_t t_uid = -1; // uid of current process
315 gid_t *glist = NULL; // group list
316 int glist_cnt = 0; // for group list
320 unsigned *additional_gids = NULL;
323 * initialize user structure
325 C_LOGD("Initialize user structure");
326 memset(usr.user_name, 0x00, 10);
327 memset(usr.home_dir, 0x00, 64);
328 memset(usr.group_list, 0x00, 64);
333 C_LOGD("Current uid is %d", t_uid);
335 if(t_uid == 0) // current user is 'root'
337 if(!strncmp(pkg_name, "developer", 9))
339 strncpy(usr.user_name, DEV_USER_NAME, sizeof(usr.user_name));
340 usr.uid = DEVELOPER_UID;
341 usr.gid = DEVELOPER_GID;
342 strncpy(usr.home_dir, DEV_HOME_DIR, sizeof(usr.home_dir));
343 strncpy(usr.group_list, DEV_GROUP_PATH, sizeof(usr.group_list));
347 strncpy(usr.user_name, APP_USER_NAME, sizeof(usr.user_name));
350 strncpy(usr.home_dir, APP_HOME_DIR, sizeof(usr.home_dir));
354 * get group information
356 C_LOGD("get group information");
357 if (get_user_groups(usr.uid, &glist_cnt, &glist)) {
358 result = PC_ERR_FILE_OPERATION; // return -1
365 result = get_app_gids(smack_label, &additional_gids, &cnt);
366 if (result != PC_OPERATION_SUCCESS)
370 glist_new = (gid_t*)realloc(glist, sizeof(gid_t) * (glist_cnt + cnt));
371 if (glist_new == NULL) {
372 result = PC_ERR_MEM_OPERATION; // return -2
373 C_LOGE("Memory allocation failed");
377 for (i = 0; i < cnt; ++i) {
378 C_LOGD("Additional GID based on enabled permissions: %u", additional_gids[i]);
379 glist[glist_cnt++] = additional_gids[i];
387 C_LOGD("Adding process to the following groups:");
388 for(i=0; i<glist_cnt; ++i) {
389 SECURE_C_LOGD("glist [ %d ] = %d", i, glist[i]);
391 C_LOGD("Calling setgroups()");
392 if(setgroups(glist_cnt, glist) != 0)
394 C_LOGE("setgroups failed");
395 result = PC_ERR_NOT_PERMITTED; // return -3
405 * setuid() & setgid()
407 C_LOGD("setgid( %d ) & setuid( %d )", usr.gid, usr.uid);
408 if(setgid(usr.gid) != 0) // fail
410 C_LOGE("Failed to execute setgid().");
411 result = PC_ERR_INVALID_OPERATION;
414 if(setuid(usr.uid) != 0) // fail
416 C_LOGE("Failed to execute setuid().");
417 result = PC_ERR_INVALID_OPERATION;
421 SECURE_C_LOGD("setenv(): USER = %s, HOME = %s", usr.user_name, usr.home_dir);
422 if(setenv("USER", usr.user_name, 1) != 0) //fail
424 C_LOGE("Failed to execute setenv() [USER].");
425 result = PC_ERR_INVALID_OPERATION;
428 if(setenv("HOME", usr.home_dir, 1) != 0) // fail
430 C_LOGE("Failed to execute setenv() [HOME].");
431 result = PC_ERR_INVALID_OPERATION;
435 else // current user is not only 'root' but 'app'
437 C_LOGE("Current user is NOT root");
438 result = PC_ERR_NOT_PERMITTED; // return -3
442 result = PC_OPERATION_SUCCESS;
447 free(additional_gids);
453 * Get SMACK label from EXEC label of a file.
454 * SMACK label should be freed by caller
456 * @param path file path to take label from
457 * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
459 static int get_smack_from_binary(char **smack_label, const char* path, app_type_t type)
461 SECURE_C_LOGD("Entering function: %s. Params: path=%s, type=%d",
462 __func__, path, type);
466 if (type == PERM_APP_TYPE_WRT
467 || type == PERM_APP_TYPE_WRT_PARTNER
468 || type == PERM_APP_TYPE_WRT_PLATFORM) {
469 ret = smack_lgetlabel(path, smack_label, SMACK_LABEL_EXEC);
471 ret = smack_getlabel(path, smack_label, SMACK_LABEL_EXEC);
474 C_LOGE("Getting exec label from file %s failed", path);
475 return PC_ERR_INVALID_OPERATION;
478 return PC_OPERATION_SUCCESS;
482 * Set process SMACK label.
483 * This function is emulating EXEC label behavior of SMACK for programs
484 * run by dlopen/dlsym instead of execv.
487 * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
489 static int set_smack_for_self (char *smack_label)
491 SECURE_C_LOGD("Entering function: %s. Params: smack_label=%s",
492 __func__, smack_label);
495 if (smack_label == NULL) {
496 /* No label to set, just return with success */
497 C_LOGD("No label to set, just return with success.");
498 ret = PC_OPERATION_SUCCESS;
501 SECURE_C_LOGD("smack_label=%s", smack_label);
503 ret = smack_set_label_for_self(smack_label);
504 C_LOGD("smack_set_label_for_self returned %d", ret);
506 ret = PC_OPERATION_SUCCESS;
512 static int is_widget(const char* path)
514 SECURE_C_LOGD("Entering function: %s. Params: path=%s",
516 char buf[sizeof(WRT_CLIENT_PATH)];
519 ret = readlink(path, buf, sizeof(WRT_CLIENT_PATH));
521 C_LOGD("readlink(%s) returned error: %s. Assuming that app is not a widget", path, strerror(errno));
522 else if (ret == sizeof(WRT_CLIENT_PATH))
523 C_LOGD("%s is not a widget", path);
524 if (ret == -1 || ret == sizeof(WRT_CLIENT_PATH))
527 C_LOGD("buf=%s", buf);
529 ret = !strcmp(WRT_CLIENT_PATH, buf);
530 C_LOGD("%s is %s widget", path, ret ? "a" : "not a");
535 * Partially verify, that the type given for app is correct.
536 * This function will use some heuristics to check whether the app type is right.
537 * It is intended for security hardening to catch privilege setting for the
538 * app type not corresponding to the actual binary.
539 * Beware - when it detects an anomaly, the whole process will be terminated.
541 * @param type claimed application type
542 * @param path file path to executable
543 * @return return recognized type enum on success, terminate the process on error
545 static app_type_t verify_app_type(const char* type, const char* path)
547 SECURE_C_LOGD("Entering function: %s. Params: type=%s, path=%s",
548 __func__, type, path);
550 /* TODO: this should actually be treated as error, but until the old
551 * set_privilege API is removed, it must be ignored */
552 /* And it will be removed very soon */
553 if (path == NULL || type == NULL) {
554 C_LOGD("PKG_TYPE_OTHER");
555 return APP_TYPE_OTHER; /* good */
558 if (is_widget(path)) {
559 if (!strcmp(type, "wgt")) {
560 C_LOGD("PKG_TYPE_WRT");
561 return PERM_APP_TYPE_WRT; /* good */
562 } else if (!strcmp(type, "wgt_partner")) {
563 C_LOGD("PKG_TYPE_WRT_PARTNER");
564 return PERM_APP_TYPE_WRT_PARTNER; /* good */
565 } else if (!strcmp(type, "wgt_platform")) {
566 C_LOGD("PKG_TYPE_WRT_PLATFORM");
567 return PERM_APP_TYPE_WRT_PLATFORM; /* good */
571 if (!strcmp(type, "osp")) {
572 C_LOGD("PKG_TYPE_OSP");
573 return PERM_APP_TYPE_OSP; /* good */
574 } else if (!strcmp(type, "osp_partner")) {
575 C_LOGD("PKG_TYPE_OSP_PARTNER");
576 return PERM_APP_TYPE_OSP_PARTNER; /* good */
577 } else if (!strcmp(type, "osp_platform")) {
578 C_LOGD("PKG_TYPE_OSP_PLATFORM");
579 return PERM_APP_TYPE_OSP_PLATFORM; /* good */
580 } else if (!strcmp(type, "efl")) {
581 C_LOGD("PKG_TYPE_EFL");
582 return PERM_APP_TYPE_EFL; /* good */
587 C_LOGE("EXIT_FAILURE, app_type = \"%s\" unrecognized", type);
591 API int set_app_privilege(const char* name, const char* type, const char* path)//deprecated
593 SECURE_C_LOGD("Entering function: %s. Params: name=%s, type=%s, path=%s",
594 __func__, name, type, path);
596 return perm_app_set_privilege(name, type, path);
599 API int perm_app_set_privilege(const char* name, const char* type, const char* path)
601 SECURE_C_LOGD("Entering function: %s. Params: name=%s, type=%s, path=%s",
602 __func__, name, type, path);
604 //SECURE_C_LOGD("Function params: name = %s, type = %s, path = %s", name, type, path);
605 int ret = PC_OPERATION_SUCCESS;
606 char *smack_label AUTO_FREE;
609 C_LOGE("Error invalid parameter");
610 return PC_ERR_INVALID_PARAM;
613 if (path != NULL && have_smack()) {
614 ret = get_smack_from_binary(&smack_label, path, verify_app_type(type, path));
615 if (ret != PC_OPERATION_SUCCESS)
618 ret = set_smack_for_self(smack_label);
619 if (ret != PC_OPERATION_SUCCESS)
623 if (path != NULL && !have_smack()) {
624 ret = get_smack_from_binary(&smack_label, path, verify_app_type(type, path));
625 if (ret != PC_OPERATION_SUCCESS)
629 return set_dac(smack_label, name);
632 API int set_privilege(const char* pkg_name)//deprecated
634 SECURE_C_LOGD("Entering function: %s. Params: pkg_name=%s",
637 return perm_app_set_privilege(pkg_name, NULL, NULL);
640 static int perm_file_path(char** path, app_type_t app_type, const char* perm, const char *suffix, bool is_early)
642 SECURE_C_LOGD("Entering function: %s. Params: app_type=%d, perm=%s, suffix=%s, is_early=%d",
643 __func__, app_type, perm, suffix, is_early);
645 const char* app_type_prefix = NULL;
646 char* perm_basename = NULL;
649 if (perm == NULL || strlen(perm) == 0) {
650 C_LOGE("Empty permission name.");
651 return PC_ERR_INVALID_PARAM;
654 app_type_prefix = app_type_group_name(app_type);
656 ret = base_name_from_perm(perm, &perm_basename);
657 if (ret != PC_OPERATION_SUCCESS) {
658 C_LOGE("Couldn't get permission basename.");
663 ret = asprintf(path, TOSTRING(SHAREDIR) "/%s%s%s%s%s",
664 app_type_prefix ? app_type_prefix : "", app_type_prefix ? "_" : "",
665 perm_basename, "_early", suffix);
668 ret = asprintf(path, TOSTRING(SHAREDIR) "/%s%s%s%s",
669 app_type_prefix ? app_type_prefix : "", app_type_prefix ? "_" : "",
670 perm_basename, suffix);
673 C_LOGE("asprintf failed.");
674 return PC_ERR_MEM_OPERATION;
677 C_LOGD("Path=%s", *path);
679 return PC_OPERATION_SUCCESS;
682 static int perm_to_dac(const char* app_label, app_type_t app_type, const char* perm)
684 SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, app_type=%d, perm=%s",
685 __func__, app_label, app_type, perm);
688 char* path AUTO_FREE;
689 FILE* file AUTO_FCLOSE;
692 ret = perm_file_path(&path, app_type, perm, ".dac", 0);
693 if (ret != PC_OPERATION_SUCCESS) {
694 C_LOGD("No dac config file for permission %s", perm);
698 SECURE_C_LOGD("Opening file %s.", path);
699 file = fopen(path, "r");
701 C_LOGW("fopen failed.");
702 return PC_OPERATION_SUCCESS;
705 while (fscanf(file, "%d\n", &gid) == 1) {
706 SECURE_C_LOGD("Adding app_id %s to group %d", app_label, gid);
707 ret = add_app_gid(app_label, gid);
708 if (ret != PC_OPERATION_SUCCESS) {
709 C_LOGE("add_app_gid failed");
714 return PC_OPERATION_SUCCESS;
717 static int label_all(const FTSENT* ftsent UNUSED)
719 SECURE_C_LOGD("Entering function: %s.", __func__);
721 return DECISION_LABEL;
724 static int label_execs(const FTSENT* ftsent)
726 SECURE_C_LOGD("Entering function: %s.", __func__);
728 C_LOGD("Mode = %d", ftsent->fts_statp->st_mode);
729 // label only regular executable files
730 if (S_ISREG(ftsent->fts_statp->st_mode) && (ftsent->fts_statp->st_mode & S_IXUSR))
731 return DECISION_LABEL;
732 return DECISION_SKIP;
735 static int label_dirs(const FTSENT* ftsent)
737 SECURE_C_LOGD("Entering function: %s.", __func__);
739 // label only directories
740 if (S_ISDIR(ftsent->fts_statp->st_mode))
741 return DECISION_LABEL;
742 return DECISION_SKIP;
745 static int label_links_to_execs(const FTSENT* ftsent)
747 SECURE_C_LOGD("Entering function: %s.", __func__);
750 char* target AUTO_FREE;
752 // check if it's a link
753 if ( !S_ISLNK(ftsent->fts_statp->st_mode))
754 return DECISION_SKIP;
756 target = realpath(ftsent->fts_path, NULL);
758 SECURE_C_LOGE("Getting link target for %s failed (Error = %s)", ftsent->fts_path, strerror(errno));
759 return PC_ERR_FILE_OPERATION;
761 if (-1 == stat(target, &buf)) {
762 SECURE_C_LOGE("stat failed for %s (Error = %s", target, strerror(errno));
763 return PC_ERR_FILE_OPERATION;
765 // skip if link target is not a regular executable file
766 if (buf.st_mode != (buf.st_mode | S_IXUSR | S_IFREG)) {
767 SECURE_C_LOGD("%s is not a regular executable file. Skipping.", target);
768 return DECISION_SKIP;
771 return DECISION_LABEL;
774 static int dir_set_smack_r(const char *path, const char* label,
775 enum smack_label_type type, label_decision_fn fn)
777 SECURE_C_LOGD("Entering function: %s. Params: path=%s, label=%s, type=%d",
778 __func__, path, label, type);
780 const char* path_argv[] = {path, NULL};
781 FTS *fts AUTO_FTS_CLOSE;
785 fts = fts_open((char * const *) path_argv, FTS_PHYSICAL | FTS_NOCHDIR, NULL);
787 C_LOGE("fts_open failed.");
788 return PC_ERR_FILE_OPERATION;
791 while ((ftsent = fts_read(fts)) != NULL) {
792 /* Check for error (FTS_ERR) or failed stat(2) (FTS_NS) */
793 if (ftsent->fts_info == FTS_ERR || ftsent->fts_info == FTS_NS) {
794 C_LOGE("FTS_ERR error or failed stat(2) (FTS_NS)");
795 return PC_ERR_FILE_OPERATION;
800 C_LOGE("fn(ftsent) failed.");
804 if (ret == DECISION_LABEL) {
805 C_LOGD("smack_lsetlabel (label: %s (type: %d), path: %s)", label, type, ftsent->fts_path);
806 if (smack_lsetlabel(ftsent->fts_path, label, type) != 0) {
807 C_LOGE("smack_lsetlabel failed.");
808 return PC_ERR_FILE_OPERATION;
813 /* If last call to fts_read() set errno, we need to return error. */
815 C_LOGE("Last errno from fts_read: %s", strerror(errno));
816 return PC_ERR_FILE_OPERATION;
818 return PC_OPERATION_SUCCESS;
820 API char* app_id_from_socket(int sockfd)//deprecated
822 SECURE_C_LOGD("Entering function: %s. Params: sockfd=%d",
825 return perm_app_id_from_socket(sockfd);
828 API char* perm_app_id_from_socket(int sockfd)
830 SECURE_C_LOGD("Entering function: %s. Params: sockfd=%d",
834 C_LOGD("No SMACK. Returning NULL.");
841 ret = smack_new_label_from_socket(sockfd, &app_id);
843 C_LOGE("smack_new_label_from_socket failed");
847 SECURE_C_LOGD("app_id = %s", app_id);
853 API int app_add_permissions(const char* app_id, const char** perm_list)//deprecated
855 SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
858 return perm_app_enable_permissions(app_id, APP_TYPE_OTHER, perm_list, true);
861 API int app_add_volatile_permissions(const char* app_id, const char** perm_list)//deprecated
863 SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
866 return perm_app_enable_permissions(app_id, APP_TYPE_OTHER, perm_list, false);
869 API int perm_app_setup_permissions(const char* pkg_id, app_type_t app_type,
870 const char** perm_list)
872 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d",
873 __func__, pkg_id, app_type);
874 return perm_app_enable_permissions(pkg_id, app_type, perm_list, true);
877 API int app_enable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list, bool persistent)//deprecated
879 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d, persistent=%d",
880 __func__, pkg_id, app_type, persistent);
882 return perm_app_enable_permissions(pkg_id, app_type, perm_list, persistent);
885 API int perm_app_enable_permissions(const char* pkg_id, app_type_t app_type,
886 const char** perm_list, bool persistent)
888 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d, persistent=%d",
889 __func__, pkg_id, app_type, persistent);
893 if (!smack_label_is_valid(pkg_id)) {
894 C_LOGE("Invalid param app_id.");
895 return PC_ERR_INVALID_PARAM;
898 if (perm_list == NULL) {
899 C_LOGE("Invalid perm_list (NULL).");
900 return PC_ERR_INVALID_PARAM;
903 if (app_type_group_name(app_type) == NULL) {
904 C_LOGE("Unknown app type.");
905 return PC_ERR_INVALID_PARAM;
908 /* Add permission to DAC */
909 for (i = 0; perm_list[i] != NULL; ++i) {
910 ret = perm_to_dac(pkg_id, app_type, perm_list[i]);
911 if (ret != PC_OPERATION_SUCCESS) {
912 C_LOGE("perm_to_dac failed");
917 /* Enable the permissions: */
918 ret = rdb_enable_app_permissions(pkg_id, app_type, perm_list,
919 !((bool)persistent));
920 if (ret != PC_OPERATION_SUCCESS) {
921 C_LOGE("RDB rdb_enable_app_permissions failed with: %d", ret);
925 return PC_OPERATION_SUCCESS;
928 API int app_disable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list)//deprecated
930 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d",
931 __func__, pkg_id, app_type);
933 return perm_app_disable_permissions(pkg_id, app_type, perm_list);
936 API int perm_app_disable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list)
938 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d",
939 __func__, pkg_id, app_type);
942 if (!smack_label_is_valid(pkg_id)) {
943 C_LOGE("Invalid param app_id.");
944 return PC_ERR_INVALID_PARAM;
947 if (perm_list == NULL) {
948 C_LOGE("Invalid perm_list (NULL).");
949 return PC_ERR_INVALID_PARAM;
952 if (app_type_group_name(app_type) == NULL) {
953 C_LOGE("Unknown app type.");
954 return PC_ERR_INVALID_PARAM;
957 ret = rdb_disable_app_permissions(pkg_id, app_type, perm_list);
958 if (ret != PC_OPERATION_SUCCESS) {
959 C_LOGE("RDB rdb_disable_app_permissions failed with: %d", ret);
963 return PC_OPERATION_SUCCESS;
966 API int app_revoke_permissions(const char* pkg_id)//deprecated
968 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
969 return perm_app_revoke_permissions(pkg_id);
972 API int perm_app_revoke_permissions(const char* pkg_id)
974 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
977 if (!smack_label_is_valid(pkg_id)) {
978 C_LOGE("Invalid param app_id.");
979 return PC_ERR_INVALID_PARAM;
982 ret = rdb_revoke_app_permissions(pkg_id);
983 if (ret != PC_OPERATION_SUCCESS) {
984 C_LOGE("RDB rdb_disable_app_permissions failed with: %d", ret);
988 return PC_OPERATION_SUCCESS;
991 API int app_reset_permissions(const char* pkg_id)//deprecated
993 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
996 return perm_app_reset_permissions(pkg_id);
999 API int perm_app_reset_permissions(const char* pkg_id)
1001 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
1005 if (!smack_label_is_valid(pkg_id)) {
1006 C_LOGE("Invalid param pkg_id.");
1007 return PC_ERR_INVALID_PARAM;
1010 ret = rdb_reset_app_permissions(pkg_id);
1011 if (ret != PC_OPERATION_SUCCESS) {
1012 C_LOGE("RDB rdb_disable_app_permissions failed with: %d", ret);
1016 return PC_OPERATION_SUCCESS;
1019 API int perm_app_has_permission(const char *pkg_id,
1020 app_type_t app_type,
1021 const char *permission_name,
1024 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d, permission_name=%s",
1025 __func__, pkg_id, app_type, permission_name);
1027 const char *app_group = app_type_group_name(app_type);
1029 if (app_group == NULL) {
1030 C_LOGE("Unknown param app type.");
1031 return PC_ERR_INVALID_PARAM;
1034 if (!smack_label_is_valid(pkg_id)) {
1035 C_LOGE("Invalid param app_id.");
1036 return PC_ERR_INVALID_PARAM;
1039 if (permission_name == NULL) {
1040 C_LOGE("Invalid param permission_name (NULL).");
1041 return PC_ERR_INVALID_PARAM;
1044 if (is_enabled == NULL) {
1045 C_LOGE("Invalid param is_enabled (NULL).");
1046 return PC_ERR_INVALID_PARAM;
1049 return rdb_app_has_permission(pkg_id, app_group, permission_name, is_enabled);
1052 API int perm_app_get_permissions(const char *pkg_id, app_type_t app_type, char ***ppp_perm_list)
1054 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d", __func__, pkg_id,
1057 const char *app_group = app_type_group_name(app_type);
1060 if (ppp_perm_list == NULL) {
1061 C_LOGE("Invalid param ppp_perm_list (NULL).");
1062 return PC_ERR_INVALID_PARAM;
1064 // Set the given pointer to NULL in case of future failure.
1065 *ppp_perm_list = NULL;
1067 if (app_group == NULL) {
1068 C_LOGE("Unknown param app type.");
1069 return PC_ERR_INVALID_PARAM;
1072 if (!smack_label_is_valid(pkg_id)) {
1073 C_LOGE("Invalid param app_id.");
1074 return PC_ERR_INVALID_PARAM;
1077 ret = rdb_app_get_permissions(pkg_id, app_group, ppp_perm_list);
1078 if (ret != PC_OPERATION_SUCCESS) {
1079 C_LOGE("RDB rdb_app_get_permissions failed with: %d", ret);
1083 return PC_OPERATION_SUCCESS;
1086 API int perm_get_permissions(char ***ppp_permissions, app_type_t app_type)
1088 SECURE_C_LOGD("Entering function: %s. Params: app_type=%d",
1089 __func__, app_type);
1092 if(ppp_permissions == NULL) {
1093 C_LOGE("Invalid ppp_permissions (NULL).");
1094 return PC_ERR_INVALID_PARAM;
1096 // Set the given pointer to NULL in case of future failure
1097 *ppp_permissions = NULL;
1099 const char *s_permission_type_name = app_type_group_name(app_type);
1101 if(s_permission_type_name == NULL) {
1102 C_LOGE("Unknown param app type.");
1103 return PC_ERR_INVALID_PARAM;
1106 ret = rdb_get_permissions(ppp_permissions, s_permission_type_name);
1108 if(ret != PC_OPERATION_SUCCESS) {
1109 C_LOGE("RDB %s failed with: %d", __func__, ret);
1113 return PC_OPERATION_SUCCESS;
1116 API int perm_get_apps_with_permission(perm_app_status_t **pp_apps,
1117 size_t *pi_apps_number,
1118 app_type_t app_type,
1119 const char *s_permission_name)
1121 SECURE_C_LOGD("Entering function: %s. Params: \
1122 app_type=%d, s_permission_name=%s",
1123 __func__, app_type, s_permission_name);
1126 if(pp_apps == NULL) {
1127 C_LOGE("Invalid ppp_permissions (NULL).");
1128 return PC_ERR_INVALID_PARAM;
1130 // Set the given pointer to NULL in case of future failure
1133 if(pi_apps_number == NULL) {
1134 C_LOGE("Invalid pi_apps_number (NULL).");
1135 return PC_ERR_INVALID_PARAM;
1138 if(s_permission_name == NULL) {
1139 C_LOGE("Invalid s_permission_name (NULL).");
1140 return PC_ERR_INVALID_PARAM;
1143 const char *s_permission_type_name = app_type_group_name(app_type);
1145 if(s_permission_type_name == NULL) {
1146 C_LOGE("Unknown param app type.");
1147 return PC_ERR_INVALID_PARAM;
1150 ret = rdb_get_apps_with_permission(pp_apps,
1152 s_permission_type_name,
1155 if(ret != PC_OPERATION_SUCCESS) {
1156 C_LOGE("RDB %s failed with: %d", __func__, ret);
1160 return PC_OPERATION_SUCCESS;
1163 API void perm_free_apps_list(perm_app_status_t *pp_apps,
1164 size_t i_apps_number)
1166 SECURE_C_LOGD("Entering function: %s. Params: i_apps_number=%d",
1167 __func__, i_apps_number);
1170 if(pp_apps != NULL) {
1171 for(i = 0; i < i_apps_number; ++i) {
1172 free(pp_apps[i].app_id);
1178 API int app_label_dir(const char* label, const char* path)//deprecated
1180 SECURE_C_LOGD("Entering function: %s. Params: label=%s, path=%s",
1181 __func__, label, path);
1183 int ret = PC_OPERATION_SUCCESS;
1186 C_LOGE("Invalid argument path (NULL).");
1187 return PC_ERR_INVALID_PARAM;
1190 if (!smack_label_is_valid(label)) {
1191 C_LOGE("Invalid param label.");
1192 return PC_ERR_INVALID_PARAM;
1195 //setting access label on everything in given directory and below
1196 ret = dir_set_smack_r(path, label, SMACK_LABEL_ACCESS, &label_all);
1197 if (PC_OPERATION_SUCCESS != ret)
1199 C_LOGE("dir_set_smack_r failed.");
1203 //setting execute label for everything with permission to execute
1204 ret = dir_set_smack_r(path, label, SMACK_LABEL_EXEC, &label_execs);
1205 if (PC_OPERATION_SUCCESS != ret)
1207 C_LOGE("dir_set_smack_r failed.");
1211 //setting execute label for everything with permission to execute
1212 ret = dir_set_smack_r(path, label, SMACK_LABEL_EXEC, &label_links_to_execs);
1217 API int app_label_shared_dir(const char* app_label, const char* shared_label, const char* path)//deprecated
1219 SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, shared_label=%s, path=%s",
1220 __func__, app_label, shared_label, path);
1224 C_LOGE("Invalid param path.");
1225 return PC_ERR_INVALID_PARAM;
1228 if(!smack_label_is_valid(app_label)) {
1229 C_LOGE("Invalid param app_label");
1230 return PC_ERR_INVALID_PARAM;
1233 if(!smack_label_is_valid(shared_label)) {
1234 C_LOGE("Invalid param shared_label");
1235 return PC_ERR_INVALID_PARAM;
1238 if (strcmp(app_label, shared_label) == 0) {
1239 C_LOGE("app_label equals shared_label");
1240 return PC_ERR_INVALID_PARAM;
1243 //setting label on everything in given directory and below
1244 ret = dir_set_smack_r(path, shared_label, SMACK_LABEL_ACCESS, label_all);
1245 if(ret != PC_OPERATION_SUCCESS){
1246 C_LOGE("dir_set_smack_r failed.");
1250 //setting transmute on dir
1251 ret = dir_set_smack_r(path, "1", SMACK_LABEL_TRANSMUTE, label_dirs);
1252 if (ret != PC_OPERATION_SUCCESS) {
1253 C_LOGE("dir_set_smack_r failed");
1257 return PC_OPERATION_SUCCESS;
1260 API int add_shared_dir_readers(const char* shared_label UNUSED, const char** app_list UNUSED)//deprecated
1262 SECURE_C_LOGD("Entering function: %s. Params: shared_label=%s",
1263 __func__, shared_label);
1265 C_LOGE("add_shared_dir_readers is deprecated and unimplemented!");
1267 // TODO: This function is not implemented with RDB.
1268 return PC_ERR_INVALID_OPERATION;
1271 static char* smack_label_for_path(const char *app_id, const char *path)
1273 SECURE_C_LOGD("Entering function: %s. Params: app_id=%s, path=%s",
1274 __func__, app_id, path);
1276 char *salt AUTO_FREE;
1280 /* Prefix $1$ causes crypt() to use MD5 function */
1281 if (-1 == asprintf(&salt, "$1$%s", app_id)) {
1282 C_LOGE("asprintf failed");
1286 label = crypt(path, salt);
1287 if (label == NULL) {
1288 C_LOGE("crypt failed");
1292 /* crypt() output may contain slash character,
1293 * which is not legal in Smack labels */
1294 for (x = label; *x; ++x) {
1302 /* FIXME: remove this pragma once deprecated API is deleted */
1303 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1304 static int perm_app_setup_path_internal(const char* pkg_id, const char* path, app_path_type_t app_path_type, va_list ap)
1306 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, path=%s, app_path_type=%d",
1307 __func__, pkg_id, path, app_path_type);
1310 C_LOGE("Invalid argument path.");
1311 return PC_ERR_INVALID_PARAM;
1314 if (!smack_label_is_valid(pkg_id)) {
1315 C_LOGE("Invalid pkg_id.");
1316 SECURE_C_LOGE("Invalid pkg_id %s", pkg_id);
1317 return PC_ERR_INVALID_PARAM;
1320 switch (app_path_type) {
1321 case APP_PATH_PRIVATE:
1322 C_LOGD("app_path_type is APP_PATH_PRIVATE.");
1323 return app_label_dir(pkg_id, path);
1325 case APP_PATH_GROUP: {
1326 C_LOGD("app_path_type is APP_PATH_GROUP.");
1328 const char *shared_label;
1330 shared_label = va_arg(ap, const char *);
1332 if (!smack_label_is_valid(shared_label)) {
1333 C_LOGE("Invalid shared_label.");
1334 return PC_ERR_INVALID_PARAM;
1337 if (strcmp(pkg_id, shared_label) == 0) {
1338 C_LOGE("pkg_id equals shared_label.");
1339 return PC_ERR_INVALID_PARAM;
1342 ret = app_label_shared_dir(pkg_id, shared_label, path);
1343 if (ret != PC_OPERATION_SUCCESS) {
1344 C_LOGE("app_label_shared_dir failed: %d", ret);
1348 // Add the path to the database:
1349 ret = rdb_add_path(pkg_id, shared_label, path, "rwxatl", "-", "GROUP_PATH");
1350 if (ret != PC_OPERATION_SUCCESS) {
1351 C_LOGE("RDB rdb_add_path failed with: %d", ret);
1355 return PC_OPERATION_SUCCESS;
1358 case APP_PATH_PUBLIC: {
1359 C_LOGD("app_path_type is APP_PATH_PUBLIC.");
1363 C_LOGD("New public RO path %s", path);
1366 label = smack_label_for_path(pkg_id, path);
1367 if (label == NULL) {
1368 C_LOGE("smack_label_for_path failed.");
1369 return PC_ERR_INVALID_OPERATION;
1371 C_LOGD("Generated label '%s' for public RO path %s", label, path);
1373 ret = app_label_shared_dir(pkg_id, label, path);
1374 if (ret != PC_OPERATION_SUCCESS) {
1375 C_LOGE("app_label_shared_dir failed.");
1379 // Add the path to the database:
1380 ret = rdb_add_path(pkg_id, label, path, "rwxatl", "-", "PUBLIC_PATH");
1381 if (ret != PC_OPERATION_SUCCESS) {
1382 C_LOGE("RDB rdb_add_path failed with: %d", ret);
1386 return PC_OPERATION_SUCCESS;
1389 case APP_PATH_SETTINGS: {
1390 C_LOGD("app_path_type is APP_PATH_SETTINGS.");
1395 label = smack_label_for_path(pkg_id, path);
1396 if (label == NULL) {
1397 C_LOGE("smack_label_for_path failed.");
1398 return PC_ERR_INVALID_OPERATION;
1400 C_LOGD("Appsetting: generated label '%s' for setting path %s", label, path);
1402 /*set id for path and all subfolders*/
1403 ret = app_label_shared_dir(pkg_id, label, path);
1404 if (ret != PC_OPERATION_SUCCESS) {
1405 C_LOGE("Appsetting: app_label_shared_dir failed (%d)", ret);
1409 // Add the path to the database:
1410 ret = rdb_add_path(pkg_id, label, path, "rwxatl", "-", "SETTINGS_PATH");
1411 if (ret != PC_OPERATION_SUCCESS) {
1412 C_LOGE("RDB rdb_add_path failed with: %d", ret);
1416 return PC_OPERATION_SUCCESS;
1419 case PERM_APP_PATH_NPRUNTIME: {
1420 C_LOGD("app_path_type is PERM_APP_PATH_NPRUNTIME.");
1421 char label[SMACK_LABEL_LEN + 1];
1425 if ((strlen(pkg_id) + strlen(".npruntime")) > SMACK_LABEL_LEN) {
1426 C_LOGE("cannot create npruntime label, pkg_id is too long.");
1427 return PC_ERR_INVALID_PARAM;
1429 ret = sprintf(label, "%s.npruntime", pkg_id);
1431 C_LOGE("creating npruntime label failed.");
1432 return PC_ERR_INVALID_OPERATION;
1434 C_LOGD("Generated npruntime label '%s' for path %s", label, path);
1436 // Label executable/symlink
1437 ret = set_exec_label(label, path);
1438 if (ret != PC_OPERATION_SUCCESS) {
1439 C_LOGE("cannot set executable label '%s' for path %s.", label, path);
1443 // Add the path to the database:
1444 ret = rdb_add_path(pkg_id, label, path, "rw", "rxat", "NPRUNTIME_PATH");
1445 if (ret != PC_OPERATION_SUCCESS) {
1446 C_LOGE("RDB rdb_add_path failed with: %d", ret);
1450 return PC_OPERATION_SUCCESS;
1453 case APP_PATH_ANY_LABEL: {
1454 C_LOGD("app_path_type is APP_PATH_ANY_LABEL.");
1455 const char *label = NULL;
1456 label = va_arg(ap, const char *);
1457 return app_label_dir(label, path);
1461 C_LOGE("app_path_type is invalid.");
1462 return PC_ERR_INVALID_PARAM;
1465 return PC_OPERATION_SUCCESS;
1467 /* FIXME: remove this pragma once deprecated API is deleted */
1468 #pragma GCC diagnostic warning "-Wdeprecated-declarations"
1470 API int app_setup_path(const char* pkg_id, const char* path, app_path_type_t app_path_type, ...)//deprecated
1472 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, path=%s, app_path_type=%d",
1473 __func__, pkg_id, path, app_path_type);
1477 va_start( ap, app_path_type );
1478 ret = perm_app_setup_path_internal( pkg_id, path, app_path_type, ap );
1484 API int perm_app_setup_path(const char* pkg_id, const char* path, app_path_type_t app_path_type, ...)
1486 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, path=%s, app_path_type=%d",
1487 __func__, pkg_id, path, app_path_type);
1491 va_start( ap, app_path_type );
1492 ret = perm_app_setup_path_internal( pkg_id, path, app_path_type, ap );
1497 API int perm_app_get_paths(const char* pkg_id, app_path_type_t app_path_type, char*** ppp_paths)
1499 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_path_type=%d", __func__,
1500 pkg_id, app_path_type);
1502 const char *path_type_name = app_path_type_name(app_path_type);
1505 if (ppp_paths == NULL) {
1506 C_LOGE("Invalid param ppp_paths (NULL).");
1507 return PC_ERR_INVALID_PARAM;
1509 // Set the given pointer to NULL in case of future failure.
1512 if (path_type_name == NULL) {
1513 C_LOGE("Unknown or invalid param app_path_type.");
1514 return PC_ERR_INVALID_PARAM;
1517 if (!smack_label_is_valid(pkg_id)) {
1518 C_LOGE("Invalid param app_id.");
1519 return PC_ERR_INVALID_PARAM;
1522 ret = rdb_get_app_paths(pkg_id, path_type_name, ppp_paths);
1523 if (ret != PC_OPERATION_SUCCESS) {
1524 C_LOGE("RDB rdb_app_get_paths failed with: %d", ret);
1528 return PC_OPERATION_SUCCESS;
1531 API int perm_app_remove_path(const char* pkg_id, const char *path)
1533 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, path=%s", __func__, pkg_id, path);
1538 C_LOGE("Invalid param path (NULL).");
1539 return PC_ERR_INVALID_PARAM;
1542 if (!smack_label_is_valid(pkg_id)) {
1543 C_LOGE("Invalid param app_id.");
1544 return PC_ERR_INVALID_PARAM;
1547 ret = rdb_remove_path(pkg_id, path);
1548 if (ret != PC_OPERATION_SUCCESS) {
1549 C_LOGE("RDB rdb_remove_path failed with %d", ret);
1553 return PC_OPERATION_SUCCESS;
1556 API int app_add_friend(const char* pkg_id1, const char* pkg_id2)//deprecated
1558 SECURE_C_LOGD("Entering function: %s. Params: pkg_id1=%s, pkg_id2=%s",
1559 __func__, pkg_id1, pkg_id2);
1561 return perm_app_add_friend(pkg_id1, pkg_id2);
1564 API int perm_app_add_friend(const char* pkg_id1 UNUSED, const char* pkg_id2 UNUSED)
1566 SECURE_C_LOGD("Entering function: %s. Params: pkg_id1=%s, pkg_id2=%s",
1567 __func__, pkg_id1, pkg_id2);
1569 C_LOGE("app_register_av is deprecated and unimplemented!");
1571 // TODO: This function is not implemented with RDB.
1572 return PC_ERR_INVALID_OPERATION;
1575 API int app_install(const char* pkg_id)//deprecated
1577 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
1580 return perm_app_install(pkg_id);
1583 API int perm_app_install(const char* pkg_id)
1585 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
1589 if (!smack_label_is_valid(pkg_id)) {
1590 C_LOGE("Invalid param pkg_id.");
1591 return PC_ERR_INVALID_PARAM;
1594 // Add application to the database:
1595 ret = rdb_add_application(pkg_id);
1596 if (ret != PC_OPERATION_SUCCESS) {
1597 C_LOGE("RDB rdb_add_application failed with: %d", ret);
1601 return PC_OPERATION_SUCCESS;
1604 API int app_uninstall(const char* pkg_id)//deprecated
1606 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
1609 return perm_app_uninstall(pkg_id);
1612 API int perm_app_uninstall(const char* pkg_id)
1614 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
1617 if (!smack_label_is_valid(pkg_id)) {
1618 C_LOGE("Invalid param pkg_id.");
1619 return PC_ERR_INVALID_PARAM;
1622 // Remove application from the database
1623 ret = rdb_remove_application(pkg_id);
1624 if (ret != PC_OPERATION_SUCCESS) {
1625 C_LOGE("RDB rdb_remove_application failed with: %d", ret);
1629 return PC_OPERATION_SUCCESS;
1632 static int save_gids(FILE* file, const gid_t* list_of_db_gids, size_t list_size) {
1634 SECURE_C_LOGD("Entering function: %s.", __func__);
1635 int ret = PC_OPERATION_SUCCESS;
1640 C_LOGE("Unable to create file. Error: %s", strerror(errno));
1641 return PC_ERR_FILE_OPERATION; // TODO remove smack accesses?
1644 if(-1 == fchmod(fileno(file), 0644)) {
1645 C_LOGE("Unable to chmod file. Error: %s", strerror(errno));
1646 return PC_ERR_FILE_OPERATION;
1649 for (i = 0; i < list_size ; ++i) {
1650 written = fprintf(file, "%u\n", list_of_db_gids[i]);
1652 C_LOGE("fprintf failed for file. Error: %s", strerror(errno));
1653 ret = PC_ERR_FILE_OPERATION;
1660 API int add_api_feature(app_type_t app_type,
1661 const char* api_feature_name,
1662 const char** smack_rules,
1663 const gid_t* list_of_db_gids,
1664 size_t list_size)//deprecated
1666 SECURE_C_LOGD("Entering function: %s. Params: app_type=%d, api_feature_name=%s",
1667 __func__, app_type, api_feature_name);
1669 return perm_add_api_feature(app_type, api_feature_name, smack_rules, list_of_db_gids, list_size);
1672 API int perm_add_api_feature(app_type_t app_type,
1673 const char* api_feature_name,
1674 const char** smack_rules,
1675 const gid_t* list_of_db_gids,
1677 SECURE_C_LOGD("Entering function: %s. Params: app_type=%d, api_feature_name=%s",
1678 __func__, app_type, api_feature_name);
1680 int ret = PC_OPERATION_SUCCESS;
1681 char* dac_file AUTO_FREE;
1682 char * base_api_feature_name AUTO_FREE;
1684 // struct smack_accesses* accesses = NULL;
1685 const char *s_type_name = app_type_name(app_type);
1687 // Check input values
1688 if (s_type_name == NULL || !strcmp(s_type_name, "")) {
1689 C_LOGE("Unknown api type");
1690 return PC_ERR_INVALID_PARAM;
1693 if (api_feature_name == NULL || strlen(api_feature_name) == 0) {
1694 C_LOGE("Api feature name is empty.");
1695 return PC_ERR_INVALID_PARAM;
1698 if (smack_rules && ((ret = validate_all_rules(smack_rules) ) != PC_OPERATION_SUCCESS) ) {
1699 C_LOGE("Error in rules list.");
1703 // check .dac existence only if gids are supported
1704 if (list_of_db_gids && list_size > 0) {
1705 // get feature DAC file name
1706 ret = perm_file_path(&dac_file, app_type, api_feature_name, ".dac", 0);
1707 if (ret != PC_OPERATION_SUCCESS || !dac_file ) {
1708 C_LOGE("perm_file_path failed.");
1715 // go through gid list
1716 if (ret == PC_OPERATION_SUCCESS && list_of_db_gids && list_size > 0) {
1718 SECURE_C_LOGD("Opening file %s.", dac_file);
1719 file = fopen(dac_file, "w+");
1720 ret = save_gids(file, list_of_db_gids, list_size);
1721 if(file) fclose(file);
1724 // remove file in case of failure
1725 if (ret != PC_OPERATION_SUCCESS && dac_file) {
1729 ret = base_name_from_perm(api_feature_name, &base_api_feature_name);
1730 if (ret != PC_OPERATION_SUCCESS){
1731 C_LOGE("Error during creating base name: ", ret);
1735 // Save api feature to the database.
1736 ret = rdb_add_permission_rules(base_api_feature_name, s_type_name, smack_rules);
1737 if (ret != PC_OPERATION_SUCCESS) {
1738 C_LOGE("RDB rdb_add_permission_rules failed with: %d", ret);
1746 * This function is marked as deprecated and will be removed
1748 API int app_register_av(const char* app_av_id UNUSED)//deprecated
1750 SECURE_C_LOGD("Entering function: %s. Params: app_av_id=%s",
1751 __func__, app_av_id);
1753 C_LOGE("app_register_av is deprecated and unimplemented!");
1755 // TODO: This function is not implemented with RDB.
1756 return PC_ERR_INVALID_OPERATION;
1759 API int perm_add_additional_rules(const char** smack_rules){
1760 SECURE_C_LOGD("Entering function: %s.", __func__);
1763 C_LOGE("smack_rules is NULL");
1764 return PC_ERR_INVALID_PARAM;
1767 ret = rdb_add_additional_rules(smack_rules);
1768 if (ret != PC_OPERATION_SUCCESS) {
1769 C_LOGE("RDB rdb_add_additional_rules failed with: %d", ret);
1773 return PC_OPERATION_SUCCESS;
1776 API const char* perm_strerror(int errnum)
1779 case PC_OPERATION_SUCCESS:
1781 case PC_ERR_FILE_OPERATION:
1782 return "File operation error";
1783 case PC_ERR_MEM_OPERATION:
1784 return "Memory operation error";
1785 case PC_ERR_NOT_PERMITTED:
1786 return "Operation not permitted";
1787 case PC_ERR_INVALID_PARAM:
1788 return "Invalid parameter";
1789 case PC_ERR_INVALID_OPERATION:
1790 return "Invalid operation";
1791 case PC_ERR_DB_OPERATION:
1792 return "Database operation error";
1793 case PC_ERR_DB_LABEL_TAKEN:
1794 return "Label taken by another application";
1795 case PC_ERR_DB_QUERY_PREP:
1796 return "Query failure during preparation";
1797 case PC_ERR_DB_QUERY_BIND:
1798 return "Query failure during binding";
1799 case PC_ERR_DB_QUERY_STEP:
1800 return "Query failure during stepping";
1801 case PC_ERR_DB_CONNECTION:
1802 return "Cannot establish a connection";
1803 case PC_ERR_DB_NO_SUCH_APP:
1804 return "No such application";
1805 case PC_ERR_DB_PERM_FORBIDDEN:
1806 return "Duplicate permission";
1808 return "Unknown error";