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>
44 #include "privilege-control.h"
45 #include "access-db.h"
50 #define DEVELOPER_GID 5100
51 #define DEVELOPER_UID 5100
53 #define APP_USER_NAME "app"
54 #define DEV_USER_NAME "developer"
56 #define APP_HOME_DIR TOSTRING(HOMEDIR) "/app"
57 #define DEV_HOME_DIR TOSTRING(HOMEDIR) "/developer"
59 #define APP_GROUP_PATH TOSTRING(SHAREDIR) "/app_group_list"
60 #define DEV_GROUP_PATH TOSTRING(SHAREDIR) "/dev_group_list"
62 #define SMACK_RULES_DIR "/etc/smack/accesses.d/"
64 #define SMACK_APP_LABEL_TEMPLATE "~APP~"
65 #define SMACK_SRC_FILE_SUFFIX "_src_file"
66 #define SMACK_SRC_DIR_SUFFIX "_src_dir"
67 #define SMACK_DATA_SUFFIX "_data"
68 #define WRT_BASE_DEVCAP "WRT"
69 #define WRT_CLIENT_PATH "/usr/bin/wrt-client"
71 #define TIZEN_PRIVILEGE_ANTIVIRUS "http://tizen.org/privilege/antivirus"
81 typedef struct state_node_t {
85 static void *state_tree = NULL;
93 typedef int (*label_decision_fn)(const FTSENT*);
99 int state_tree_cmp(const void *first, const void *second)
101 return strcmp(((state_node*)first)->key,
102 ((state_node*)second)->key);
105 int state_tree_push(const char* key_param, const char* value_param)
107 state_node *node = malloc(sizeof(state_node));
108 char *key = strdup(key_param);
109 char *value = strdup(value_param);
111 if (!node || !key || !value) {
115 return PC_ERR_MEM_OPERATION;
121 if (NULL != tfind(node, &state_tree, state_tree_cmp)){
125 return PC_OPERATION_SUCCESS; // 04.2013 Temporary fix. Allow for multiple call of app_give_access
128 tsearch(node, &state_tree, state_tree_cmp);
129 return PC_OPERATION_SUCCESS;
132 char* state_tree_pop_new(char *key)
134 state_node search, *node;
140 wtf = tfind(&search, &state_tree, state_tree_cmp);
144 node = *(state_node**)wtf;
148 tdelete(node, &state_tree, state_tree_cmp);
156 int state_save(const char *subject, const char *object, const char *perm)
159 if (-1 == asprintf(&key, "%s|%s", subject, object))
160 return PC_ERR_INVALID_OPERATION;
161 int ret = state_tree_push(key, perm);
166 int state_restore(const char* subject, const char* object)
169 char *perm AUTO_FREE;
170 struct smack_accesses *smack AUTO_SMACK_FREE;
172 if (-1 == asprintf(&key, "%s|%s", subject, object))
173 return PC_ERR_INVALID_OPERATION;
175 perm = state_tree_pop_new(key);
177 return PC_ERR_INVALID_OPERATION;
179 if (smack_accesses_new(&smack))
180 return PC_ERR_MEM_OPERATION;
182 if (smack_accesses_add(smack, subject, object, perm))
183 return PC_ERR_MEM_OPERATION;
185 if (smack_accesses_apply(smack))
186 return PC_ERR_NOT_PERMITTED;
188 return PC_OPERATION_SUCCESS;
191 static inline int have_smack(void)
193 static int have_smack = -1;
195 if (-1 == have_smack) {
196 if (NULL == smack_smackfs_path()) {
197 C_LOGD("Libprivilage-control: no smack found on phone");
200 C_LOGD("Libprivilege-control: found smack on phone");
208 API int control_privilege(void)
210 C_LOGD("Enter function: %s", __func__);
211 if(getuid() == APP_UID) // current user is 'app'
212 return PC_OPERATION_SUCCESS;
214 if(set_app_privilege("org.tizen.", NULL, NULL) == PC_OPERATION_SUCCESS)
215 return PC_OPERATION_SUCCESS;
217 return PC_ERR_NOT_PERMITTED;
221 * TODO: this function should be moved to libsmack in open-source.
223 API int get_smack_label_from_process(pid_t pid, char smack_label[SMACK_LABEL_LEN + 1])
225 C_LOGD("Enter function: %s", __func__);
228 int PATH_MAX_LEN = 64;
229 char path[PATH_MAX_LEN + 1];
232 ret = PC_ERR_INVALID_PARAM;
236 bzero(smack_label, SMACK_LABEL_LEN + 1);
237 if (!have_smack()) { // If no smack just return success with empty label
238 C_LOGD("No SMACK. Return empty label");
239 ret = PC_OPERATION_SUCCESS;
243 bzero(path, PATH_MAX_LEN + 1);
244 snprintf(path, PATH_MAX_LEN, "/proc/%d/attr/current", pid);
245 fd = open(path, O_RDONLY);
247 C_LOGE("cannot open file %s (errno: %s)", path, strerror(errno));
248 ret = PC_ERR_FILE_OPERATION;
252 ret = read(fd, smack_label, SMACK_LABEL_LEN);
254 C_LOGE("cannot read from file %s", path);
255 ret = PC_ERR_FILE_OPERATION;
259 ret = PC_OPERATION_SUCCESS;
265 API int smack_pid_have_access(pid_t pid,
267 const char *access_type)
269 C_LOGD("Enter function: %s", __func__);
271 char pid_subject_label[SMACK_LABEL_LEN + 1];
273 cap_flag_value_t cap_v;
276 C_LOGD("No SMACK. Return access granted");
280 if (pid < 0 || object == NULL || strlen(object) == 0 ||
281 access_type == NULL || strlen(access_type) == 0) {
282 C_LOGE("Invalid param");
286 //get SMACK label of process
287 ret = get_smack_label_from_process(pid, pid_subject_label);
288 if (PC_OPERATION_SUCCESS != ret) {
289 C_LOGE("get_smack_label_from_process %d failed: %d", pid, ret);
292 C_LOGD("pid %d have label: %s", pid, pid_subject_label);
294 // if read empty label then do not call smack_have_access()
295 if (pid_subject_label[0] != '\0') {
296 ret = smack_have_access(pid_subject_label, object, access_type);
298 C_LOGE("smack_have_access failed");
301 if ( 1 == ret ) { // smack_have_access return 1 (access granted)
302 C_LOGD("smack_have_access return 1 (access granted)");
307 // smack_have_access return 0 (access denied). Now CAP_MAC_OVERRIDE should be checked
308 C_LOGD("smack_have_access return 0 (access denied)");
309 cap = cap_get_pid(pid);
311 C_LOGE("cap_get_pid failed");
314 ret = cap_get_flag(cap, CAP_MAC_OVERRIDE, CAP_EFFECTIVE, &cap_v);
316 C_LOGE("cap_get_flag failed");
320 if (cap_v == CAP_SET) {
321 C_LOGD("pid %d have CAP_MAC_OVERRIDE", pid);
325 C_LOGD("pid %d have no CAP_MAC_OVERRIDE", pid);
330 static int set_dac(const char *smack_label, const char *pkg_name)
332 C_LOGD("Enter function: %s", __func__);
333 FILE* fp_group = NULL; // /etc/group
334 uid_t t_uid = -1; // uid of current process
335 gid_t *glist = NULL; // group list
336 gid_t temp_gid = -1; // for group list
337 char buf[10] = {0, }; // contents in group_list file
338 int glist_cnt = 0; // for group list
342 unsigned *additional_gids = NULL;
345 * initialize user structure
347 C_LOGD("initialize user structure");
348 memset(usr.user_name, 0x00, 10);
349 memset(usr.home_dir, 0x00, 64);
350 memset(usr.group_list, 0x00, 64);
355 C_LOGD("Current uid is %d", t_uid);
357 if(t_uid == 0) // current user is 'root'
359 if(!strncmp(pkg_name, "developer", 9))
361 strncpy(usr.user_name, DEV_USER_NAME, sizeof(usr.user_name));
362 usr.uid = DEVELOPER_UID;
363 usr.gid = DEVELOPER_GID;
364 strncpy(usr.home_dir, DEV_HOME_DIR, sizeof(usr.home_dir));
365 strncpy(usr.group_list, DEV_GROUP_PATH, sizeof(usr.group_list));
369 strncpy(usr.user_name, APP_USER_NAME, sizeof(usr.user_name));
372 strncpy(usr.home_dir, APP_HOME_DIR, sizeof(usr.home_dir));
373 strncpy(usr.group_list, APP_GROUP_PATH, sizeof(usr.group_list));
377 * get group information
379 C_LOGD("get group information");
380 if(!(fp_group = fopen(usr.group_list, "r")))
382 C_LOGE("[ERR] file open error: [%s]\n", usr.group_list);
383 result = PC_ERR_FILE_OPERATION; // return -1
387 while(fgets(buf, 10, fp_group) != NULL)
390 temp_gid = strtoul(buf, 0, 10);
391 if(errno != 0) // error occured during strtoul()
393 C_LOGE("[ERR] cannot change string to integer: [%s]", buf);
394 result = PC_ERR_INVALID_OPERATION;
398 glist = (gid_t*)realloc(glist, sizeof(gid_t) * (glist_cnt + 1));
401 result = PC_ERR_MEM_OPERATION; // return -2
402 C_LOGE("Cannot allocate memory");
405 glist[glist_cnt] = temp_gid;
415 result = get_app_gids(smack_label, &additional_gids, &cnt);
416 if (result != PC_OPERATION_SUCCESS)
420 glist_new = (gid_t*)realloc(glist, sizeof(gid_t) * (glist_cnt + cnt));
421 if (glist_new == NULL) {
422 result = PC_ERR_MEM_OPERATION; // return -2
423 C_LOGE("Cannot allocate memory");
427 for (i = 0; i < cnt; ++i) {
428 C_LOGD("Additional GID based on enabled permissions: %u", additional_gids[i]);
429 glist[glist_cnt++] = additional_gids[i];
437 C_LOGD("Adding process to the following groups:");
438 for(i=0; i<glist_cnt; ++i) {
439 C_LOGD("glist [ %d ] = %d", i, glist[i]);
441 C_LOGD("setgroups()");
442 if(setgroups(glist_cnt, glist) != 0)
444 C_LOGE("[ERR] setgrouops fail\n");
445 result = PC_ERR_NOT_PERMITTED; // return -3
455 * setuid() & setgid()
457 C_LOGD("setgid( %d ) & setuid( %d )", usr.gid, usr.uid);
458 if(setgid(usr.gid) != 0) // fail
460 C_LOGE("[ERR] fail to execute setgid().");
461 result = PC_ERR_INVALID_OPERATION;
464 if(setuid(usr.uid) != 0) // fail
466 C_LOGE("[ERR] fail to execute setuid().");
467 result = PC_ERR_INVALID_OPERATION;
471 C_LOGD("setenv(): USER = %s, HOME = %s", usr.user_name, usr.home_dir);
472 if(setenv("USER", usr.user_name, 1) != 0) //fail
474 C_LOGE("[ERR] fail to execute setenv() [USER].");
475 result = PC_ERR_INVALID_OPERATION;
478 if(setenv("HOME", usr.home_dir, 1) != 0) // fail
480 C_LOGE("[ERR] fail to execute setenv() [HOME].");
481 result = PC_ERR_INVALID_OPERATION;
485 else // current user is not only 'root' but 'app'
487 C_LOGE("[ERR] current user is NOT root\n");
488 result = PC_ERR_NOT_PERMITTED; // return -3
492 result = PC_OPERATION_SUCCESS;
499 free(additional_gids);
505 * Set process SMACK label from EXEC label of a file.
506 * This function is emulating EXEC label behaviour of SMACK for programs
507 * run by dlopen/dlsym instead of execv.
509 * @param path file path to take label from
510 * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
512 static int set_smack_from_binary(char **smack_label, const char* path, app_type_t type)
514 C_LOGD("Enter function: %s", __func__);
517 C_LOGD("Path: %s", path);
520 if(type == APP_TYPE_WGT) {
521 ret = smack_lgetlabel(path, smack_label, SMACK_LABEL_EXEC);
523 ret = smack_getlabel(path, smack_label, SMACK_LABEL_EXEC);
526 C_LOGE("Getting exec label from file %s failed", path);
527 return PC_ERR_INVALID_OPERATION;
530 if (*smack_label == NULL) {
531 /* No label to set, just return with success */
532 C_LOGD("No label to set, just return with success");
533 ret = PC_OPERATION_SUCCESS;
536 C_LOGD("label = %s", *smack_label);
538 ret = smack_set_label_for_self(*smack_label);
539 C_LOGD("smack_set_label_for_self returned %d", ret);
541 ret = PC_OPERATION_SUCCESS;
547 static int is_widget(const char* path)
549 C_LOGD("Enter function: %s", __func__);
550 char buf[sizeof(WRT_CLIENT_PATH)];
553 ret = readlink(path, buf, sizeof(WRT_CLIENT_PATH));
555 C_LOGD("readlink(%s) returned error: %s. Assuming that app is not a widget", path, strerror(errno));
556 else if (ret == sizeof(WRT_CLIENT_PATH))
557 C_LOGD("%s is not a widget", path);
558 if (ret == -1 || ret == sizeof(WRT_CLIENT_PATH))
561 C_LOGD("buf = %s", buf);
563 ret = !strcmp(WRT_CLIENT_PATH, buf);
564 C_LOGD("%s is %s widget", path, ret ? "a" : "not a");
569 * Partially verify, that the type given for app is correct.
570 * This function will use some heuristics to check whether the app type is right.
571 * It is intended for security hardening to catch privilege setting for the
572 * app type not corresponding to the actual binary.
573 * Beware - when it detects an anomaly, the whole process will be terminated.
575 * @param type claimed application type
576 * @param path file path to executable
577 * @return return void on success, terminate the process on error
579 static app_type_t verify_app_type(const char* type, const char* path)
581 C_LOGD("Enter function: %s", __func__);
582 /* TODO: this should actually be treated as error, but until the old
583 * set_privilege API is removed, it must be ignored */
585 C_LOGD("PKG_TYPE_OTHER");
586 return APP_TYPE_OTHER; /* good */
589 if (is_widget(path)) {
590 if (!strcmp(type, "wgt")) {
591 C_LOGD("PKG_TYPE_WGT");
592 return APP_TYPE_WGT; /* good */
595 if (type == NULL || strcmp(type, "wgt")){
596 C_LOGD("PKG_TYPE_OTHER");
597 return APP_TYPE_OTHER; /* good */
602 C_LOGE("EXIT_FAILURE");
606 API int set_app_privilege(const char* name, const char* type, const char* path)
608 C_LOGD("Enter function: %s", __func__);
609 C_LOGD("Function params: name = %s, type = %s, path = %s", name, type, path);
610 char *smack_label AUTO_FREE;
611 int ret = PC_OPERATION_SUCCESS;
614 app_type = verify_app_type(type, path);
616 ret = set_smack_from_binary(&smack_label, path, app_type);
617 if (ret != PC_OPERATION_SUCCESS)
620 return set_dac(smack_label, name);
623 API int set_privilege(const char* pkg_name)
625 C_LOGD("Enter function: %s", __func__);
626 return set_app_privilege(pkg_name, NULL, NULL);
629 static inline const char* app_type_name(app_type_t app_type)
641 static int perm_file_path(char** path, app_type_t app_type, const char* perm, const char *suffix)
643 const char* app_type_prefix = NULL;
644 const char* perm_basename = NULL;
647 if (perm == NULL || strlen(perm) == 0) {
648 C_LOGE("empty permission name");
649 return PC_ERR_INVALID_PARAM;
652 app_type_prefix = app_type_name(app_type);
654 perm_basename = strrchr(perm, '/');
658 perm_basename = perm;
660 ret = asprintf(path, TOSTRING(SHAREDIR) "/%s%s%s%s",
661 app_type_prefix ? app_type_prefix : "", app_type_prefix ? "_" : "",
662 perm_basename, suffix);
664 C_LOGE("asprintf failed");
665 return PC_ERR_MEM_OPERATION;
668 return PC_OPERATION_SUCCESS;
671 static bool file_exists(const char* path) {
672 FILE* file = fopen(path, "r");
680 static int perm_to_smack(struct smack_accesses* smack, const char* app_label, app_type_t app_type, const char* perm)
682 C_LOGD("Enter function: %s", __func__);
684 char* path AUTO_FREE;
685 char* format_string AUTO_FREE;
686 FILE* file AUTO_FCLOSE;
687 char smack_subject[SMACK_LABEL_LEN + 1];
688 char smack_object[SMACK_LABEL_LEN + 1];
689 char smack_accesses[10];
691 // get file name for permission (devcap)
692 ret = perm_file_path(&path, app_type, perm, ".smack");
693 if (ret != PC_OPERATION_SUCCESS) {
694 C_LOGD("No smack config file for permission %s", perm);
698 if (asprintf(&format_string,"%%%ds %%%ds %%%lus\n",
699 SMACK_LABEL_LEN, SMACK_LABEL_LEN, (unsigned long)sizeof(smack_accesses)) == -1) {
700 C_LOGE("asprintf failed");
701 return PC_ERR_MEM_OPERATION;
704 file = fopen(path, "r");
705 C_LOGD("path = %s", path);
707 C_LOGE("fopen failed");
708 return PC_OPERATION_SUCCESS;
711 while (fscanf(file, format_string, smack_subject, smack_object, smack_accesses) == 3) {
712 if (!strcmp(smack_subject, SMACK_APP_LABEL_TEMPLATE))
713 strcpy(smack_subject, app_label);
715 if (!strcmp(smack_object, SMACK_APP_LABEL_TEMPLATE))
716 strcpy(smack_object, app_label);
718 C_LOGD("smack_accesses_add_modify (subject: %s, object: %s, access: %s)", smack_subject, smack_object, smack_accesses);
719 if (smack_accesses_add_modify(smack, smack_subject, smack_object, smack_accesses, "") != 0) {
720 C_LOGE("smack_accesses_add_modify failed");
721 return PC_ERR_INVALID_OPERATION;
725 return PC_OPERATION_SUCCESS;
728 static int perm_to_dac(const char* app_label, app_type_t app_type, const char* perm)
730 C_LOGD("Enter function: %s", __func__);
732 char* path AUTO_FREE;
733 FILE* file AUTO_FCLOSE;
736 ret = perm_file_path(&path, app_type, perm, ".dac");
737 if (ret != PC_OPERATION_SUCCESS) {
738 C_LOGD("No dac config file for permission %s", perm);
742 file = fopen(path, "r");
743 C_LOGD("path = %s", path);
745 C_LOGE("fopen failed");
746 return PC_OPERATION_SUCCESS;
749 while (fscanf(file, "%d\n", &gid) == 1) {
750 C_LOGD("Adding app_id %s to group %d", app_label, gid);
751 ret = add_app_gid(app_label, gid);
752 if (ret != PC_OPERATION_SUCCESS) {
753 C_LOGE("sadd_app_gid failed");
758 return PC_OPERATION_SUCCESS;
761 static int label_all(const FTSENT* ftsent)
763 return DECISION_LABEL;
766 static int label_execs(const FTSENT* ftsent)
768 C_LOGD("Mode: %d", ftsent->fts_statp->st_mode);
769 // label only regular executable files
770 if (S_ISREG(ftsent->fts_statp->st_mode) && (ftsent->fts_statp->st_mode & S_IXUSR))
771 return DECISION_LABEL;
772 return DECISION_SKIP;
775 static int label_dirs(const FTSENT* ftsent)
777 // label only directories
778 if (S_ISDIR(ftsent->fts_statp->st_mode))
779 return DECISION_LABEL;
780 return DECISION_SKIP;
783 static int label_links_to_execs(const FTSENT* ftsent)
786 char* target AUTO_FREE;
788 // check if it's a link
789 if ( !S_ISLNK(ftsent->fts_statp->st_mode))
790 return DECISION_SKIP;
792 target = realpath(ftsent->fts_path, NULL);
794 C_LOGE("Getting link target for %s failed. Error %s", ftsent->fts_path, strerror(errno));
795 return PC_ERR_FILE_OPERATION;
797 if (-1 == stat(target, &buf)) {
798 C_LOGE("stat failed for %s, error: %s",target, strerror(errno));
799 return PC_ERR_FILE_OPERATION;
801 // skip if link target is not a regular executable file
802 if (buf.st_mode != (buf.st_mode | S_IXUSR | S_IFREG)) {
803 C_LOGD("%s Is not a regular executable file. Skipping.", target);
804 return DECISION_SKIP;
807 return DECISION_LABEL;
810 static int dir_set_smack_r(const char *path, const char* label,
811 enum smack_label_type type, label_decision_fn fn)
813 C_LOGD("Enter function: %s", __func__);
814 const char* path_argv[] = {path, NULL};
815 FTS *fts AUTO_FTS_CLOSE;
819 fts = fts_open((char * const *) path_argv, FTS_PHYSICAL | FTS_NOCHDIR, NULL);
821 C_LOGE("fts_open failed");
822 return PC_ERR_FILE_OPERATION;
825 while ((ftsent = fts_read(fts)) != NULL) {
826 /* Check for error (FTS_ERR) or failed stat(2) (FTS_NS) */
827 if (ftsent->fts_info == FTS_ERR || ftsent->fts_info == FTS_NS) {
828 C_LOGE("FTS_ERR error or failed stat(2) (FTS_NS)");
829 return PC_ERR_FILE_OPERATION;
837 if (ret == DECISION_LABEL) {
838 C_LOGD("smack_lsetlabel (label: %s (type: %d), path: %s)", label, type, ftsent->fts_path);
839 if (smack_lsetlabel(ftsent->fts_path, label, type) != 0) {
840 C_LOGE("smack_lsetlabel failed");
841 return PC_ERR_FILE_OPERATION;
846 /* If last call to fts_read() set errno, we need to return error. */
848 C_LOGE("Last errno: %s", strerror(errno));
849 return PC_ERR_FILE_OPERATION;
851 return PC_OPERATION_SUCCESS;
854 API char* app_id_from_socket(int sockfd)
856 C_LOGD("Enter function: %s", __func__);
863 ret = smack_new_label_from_socket(sockfd, &app_id);
865 C_LOGE("smack_new_label_from_socket failed");
869 C_LOGD("app_id: %s", app_id);
874 static int smack_file_name(const char* app_id, char** path)
876 if (asprintf(path, SMACK_RULES_DIR "/%s", app_id) == -1) {
877 C_LOGE("asprintf failed");
879 return PC_ERR_MEM_OPERATION;
882 return PC_OPERATION_SUCCESS;
885 static int load_smack_from_file(const char* app_id, struct smack_accesses** smack, int *fd, char** path)
887 C_LOGD("Enter function: %s", __func__);
890 ret = smack_file_name(app_id, path);
891 if (ret != PC_OPERATION_SUCCESS)
894 if (smack_accesses_new(smack)) {
895 C_LOGE("smack_accesses_new failed");
896 return PC_ERR_MEM_OPERATION;
899 *fd = open(*path, O_CREAT|O_RDWR, 0644);
901 C_LOGE("file open failed: %s", strerror(errno));
902 return PC_ERR_FILE_OPERATION;
905 if (flock(*fd, LOCK_EX)) {
906 C_LOGE("flock failed");
907 return PC_ERR_INVALID_OPERATION;
910 if (smack_accesses_add_from_file(*smack, *fd)) {
911 C_LOGE("smack_accesses_add_from_file failed");
912 return PC_ERR_INVALID_OPERATION;
915 /* Rewind the file */
916 if (lseek(*fd, 0, SEEK_SET) == -1) {
917 C_LOGE("lseek failed");
918 return PC_ERR_FILE_OPERATION;
921 return PC_OPERATION_SUCCESS;
924 static int app_add_rule(const char *app_id, const char *object, const char *perm)
926 C_LOGD("Enter function: %s", __func__);
929 char *smack_path AUTO_FREE;
930 struct smack_accesses* smack AUTO_SMACK_FREE;
932 ret = load_smack_from_file(app_id, &smack, &fd, &smack_path);
933 if (ret != PC_OPERATION_SUCCESS) {
934 C_LOGE("load_smack_from_file failed");
938 ret = smack_accesses_add(smack, app_id, object, perm);
940 C_LOGE("smack_accesses_add failed");
941 return PC_ERR_INVALID_OPERATION;
944 if (have_smack() && smack_accesses_apply(smack)) {
945 C_LOGE("smack_accesses_apply failed");
946 return PC_ERR_INVALID_OPERATION;
949 if (smack_accesses_save(smack, fd)) {
950 C_LOGE("smack_accesses_save failed");
951 return PC_ERR_INVALID_OPERATION;
954 return PC_OPERATION_SUCCESS;
957 static int app_register_av_internal(const char *app_av_id, struct smack_accesses* smack)
959 C_LOGD("Enter function: %s", __func__);
963 char** smack_label_app_list AUTO_FREE;
964 int smack_label_app_list_len = 0;
966 if (!smack_label_is_valid(app_av_id) || NULL == smack)
967 return PC_ERR_INVALID_PARAM;
969 // writing anti_virus_id (app_av_id) to "database"
970 ret = add_av_id_to_databse(app_av_id);
971 if (ret != PC_OPERATION_SUCCESS )
974 // Reading labels of all installed apps from "database"
975 ret = get_all_apps_ids(&smack_label_app_list, &smack_label_app_list_len);
976 if (ret != PC_OPERATION_SUCCESS ) {
977 C_LOGE("Error while geting data from database");
980 for (i = 0; i < smack_label_app_list_len; ++i) {
981 C_LOGD("Applying rwx rule for %s", smack_label_app_list[i]);
982 if (smack_accesses_add(smack, app_av_id, smack_label_app_list[i], "wrx") == -1) {
983 C_LOGE("smack_accesses_add failed");
984 ret = PC_ERR_INVALID_OPERATION;
986 // Should we abort adding rules if once smack_accesses_add will fail?
991 for (i = 0; i < smack_label_app_list_len; ++i) {
992 free(smack_label_app_list[i]);
999 * This function will check in database labels of all anti viruses
1000 * and for all anti viruses will add a rule "anti_virus_label app_id rwx".
1001 * This should be call in app_install function.
1003 static int register_app_for_av(const char * app_id)
1006 char** smack_label_av_list AUTO_FREE;
1007 int smack_label_av_list_len = 0;
1009 // Reading labels of all installed anti viruses from "database"
1010 ret = get_all_avs_ids(&smack_label_av_list, &smack_label_av_list_len);
1011 if (ret != PC_OPERATION_SUCCESS) {
1012 C_LOGE("Error while geting data from database");
1016 // for each anti-virus put rule: "anti_virus_id app_id rwx"
1017 for (i = 0; i < smack_label_av_list_len; ++i) {
1018 ret = app_add_rule(smack_label_av_list[i], app_id, "wrx");
1019 if (ret != PC_OPERATION_SUCCESS) {
1020 C_LOGE("app_add_rule failed");
1024 free(smack_label_av_list[i]);
1027 ret = PC_OPERATION_SUCCESS;
1030 // If something failed, then no all char* smack_label_av_list[i]
1031 // are deallocated. They must be freed
1032 for(; i<smack_label_av_list_len; ++i) {
1033 free(smack_label_av_list[i]);
1040 * This function will grant app_id RX access to all public directories and
1041 * files, previously designated by app_setup_path(APP_PATH_PUBLIC_RO)
1042 * This should be call in app_install function.
1044 static int register_app_for_public_dirs(const char *app_id, struct smack_accesses *smack)
1046 C_LOGD("Enter function: %s", __func__);
1048 char **public_dirs AUTO_FREE;
1049 int public_dirs_cnt = 0;
1051 ret = db_get_public_dirs(&public_dirs, &public_dirs_cnt);
1052 if (ret != PC_OPERATION_SUCCESS) {
1053 C_LOGE("Error while geting data from database");
1057 for (i = 0; i < public_dirs_cnt; ++i) {
1058 C_LOGD("Allowing app %s to access public path %s", app_id, public_dirs[i]);
1059 if (smack_accesses_add(smack, app_id, public_dirs[i], "rx")) {
1060 C_LOGE("app_add_rule failed");
1061 while (i < public_dirs_cnt)
1062 free(public_dirs[i++]);
1063 return PC_ERR_INVALID_OPERATION;
1065 free(public_dirs[i]);
1068 return PC_OPERATION_SUCCESS;
1071 static int app_add_permissions_internal(const char* app_id, app_type_t app_type, const char** perm_list, int permanent)
1073 C_LOGD("Enter function: %s", __func__);
1074 char* smack_path AUTO_FREE;
1077 struct smack_accesses *smack AUTO_SMACK_FREE;
1078 const char* base_perm = NULL;
1080 if (!smack_label_is_valid(app_id))
1081 return PC_ERR_INVALID_PARAM;
1083 ret = load_smack_from_file(app_id, &smack, &fd, &smack_path);
1084 if (ret != PC_OPERATION_SUCCESS) {
1085 C_LOGE("load_smack_from_file failed");
1089 /* Implicitly enable base permission for an app_type */
1090 base_perm = app_type_name(app_type);
1092 C_LOGD("perm_to_smack params: app_id: %s, %s", app_id, base_perm);
1093 ret = perm_to_smack(smack, app_id, APP_TYPE_OTHER, base_perm);
1094 if (ret != PC_OPERATION_SUCCESS){
1095 C_LOGE("perm_to_smack failed");
1099 for (i = 0; perm_list[i] != NULL; ++i) {
1100 C_LOGD("perm_to_smack params: app_id: %s, perm_list[%d]: %s", app_id, i, perm_list[i]);
1101 if (strcmp(perm_list[i], TIZEN_PRIVILEGE_ANTIVIRUS) == 0) {
1102 ret = app_register_av_internal(app_id, smack);
1103 if (ret != PC_OPERATION_SUCCESS) {
1104 C_LOGE("app_register_av_internal failed");
1108 ret = perm_to_smack(smack, app_id, app_type, perm_list[i]);
1109 if (ret != PC_OPERATION_SUCCESS){
1110 C_LOGE("perm_to_smack failed");
1114 ret = perm_to_dac(app_id, app_type, perm_list[i]);
1115 if (ret != PC_OPERATION_SUCCESS){
1116 C_LOGE("perm_to_dac failed");
1121 if (have_smack() && smack_accesses_apply(smack)) {
1122 C_LOGE("smack_accesses_apply failed");
1123 return PC_ERR_INVALID_OPERATION;
1126 if (permanent && smack_accesses_save(smack, fd)) {
1127 C_LOGE("smack_accesses_save failed");
1128 return PC_ERR_INVALID_OPERATION;
1131 return PC_OPERATION_SUCCESS;
1134 API int app_add_permissions(const char* app_id, const char** perm_list)
1136 C_LOGD("Enter function: %s", __func__);
1137 return app_add_permissions_internal(app_id, APP_TYPE_OTHER, perm_list, 1);
1140 API int app_add_volatile_permissions(const char* app_id, const char** perm_list)
1142 C_LOGD("Enter function: %s", __func__);
1143 return app_add_permissions_internal(app_id, APP_TYPE_OTHER, perm_list, 0);
1146 API int app_enable_permissions(const char* app_id, app_type_t app_type, const char** perm_list, bool persistent)
1148 C_LOGD("Enter function: %s", __func__);
1149 return app_add_permissions_internal(app_id, app_type, perm_list, persistent);
1152 /* FIXME: this function is only a stub */
1153 API int app_disable_permissions(const char* app_id, app_type_t app_type, const char** perm_list)
1155 C_LOGD("Enter function: %s", __func__);
1156 return PC_OPERATION_SUCCESS;
1159 static int app_revoke_permissions_internal(const char* app_id, bool persistent)
1161 C_LOGD("Enter function: %s", __func__);
1162 char* smack_path AUTO_FREE;
1165 struct smack_accesses *smack AUTO_SMACK_FREE;
1167 if (!smack_label_is_valid(app_id))
1168 return PC_ERR_INVALID_PARAM;
1170 ret = load_smack_from_file(app_id, &smack, &fd, &smack_path);
1171 if (ret != PC_OPERATION_SUCCESS) {
1172 C_LOGE("load_smack_from_file failed");
1176 if (have_smack() && smack_accesses_clear(smack)) {
1177 ret = PC_ERR_INVALID_OPERATION;
1178 C_LOGE("smack_accesses_clear failed");
1182 if (have_smack() && smack_revoke_subject(app_id)) {
1183 ret = PC_ERR_INVALID_OPERATION;
1184 C_LOGE("smack_revoke_subject failed");
1188 if (persistent && ftruncate(fd, 0) == -1)
1189 C_LOGE("file truncate failed");
1191 return PC_OPERATION_SUCCESS;
1194 API int app_revoke_permissions(const char* app_id)
1196 C_LOGD("Enter function: %s", __func__);
1199 if (!smack_label_is_valid(app_id))
1200 return PC_ERR_INVALID_PARAM;
1202 ret = app_revoke_permissions_internal(app_id, true);
1204 C_LOGE("Revoking permissions failed");
1208 return PC_OPERATION_SUCCESS;
1211 API int app_reset_permissions(const char* app_id)
1213 C_LOGD("Enter function: %s", __func__);
1216 if (!smack_label_is_valid(app_id))
1217 return PC_ERR_INVALID_PARAM;
1219 ret = app_revoke_permissions_internal(app_id, false);
1221 C_LOGE("Revoking permissions failed");
1225 /* Add empty permissions set to trigger re-read of rules */
1226 return app_enable_permissions(app_id, APP_TYPE_OTHER, (const char*[]){NULL}, 0);
1229 API int app_label_dir(const char* label, const char* path)
1231 C_LOGD("Enter function: %s", __func__);
1233 int ret = PC_OPERATION_SUCCESS;
1235 if (!smack_label_is_valid(label))
1236 return PC_ERR_INVALID_PARAM;
1238 //setting access label on everything in given directory and below
1239 ret = dir_set_smack_r(path, label, SMACK_LABEL_ACCESS, &label_all);
1240 if (PC_OPERATION_SUCCESS != ret)
1243 //setting execute label for everything with permission to execute
1244 ret = dir_set_smack_r(path, label, SMACK_LABEL_EXEC, &label_execs);
1245 if (PC_OPERATION_SUCCESS != ret)
1248 //setting execute label for everything with permission to execute
1249 ret = dir_set_smack_r(path, label, SMACK_LABEL_EXEC, &label_links_to_execs);
1253 int smack_get_access_new(const char* subject, const char* object, char** label)
1255 char buff[ACC_LEN] = {'r', 'w', 'x', 'a', 't'};
1256 char perm[2] = {'-'};
1259 if(!smack_label_is_valid(subject) || !smack_label_is_valid(object) || !label)
1260 return PC_ERR_INVALID_PARAM;
1262 for (i=0; i<ACC_LEN; ++i) {
1264 int ret = smack_have_access(subject, object, perm);
1266 return PC_ERR_INVALID_OPERATION;
1271 *label = malloc(ACC_LEN+1);
1273 return PC_ERR_MEM_OPERATION;
1275 memcpy(*label, buff, ACC_LEN);
1276 (*label)[ACC_LEN] = 0;
1277 return PC_OPERATION_SUCCESS;
1281 * This function will be used to allow direct communication between 2 OSP application.
1282 * This function requires to store "state" with list of added label.
1284 * Full implementation requires some kind of database. This implemetation works without
1285 * database so you wont be able to revoke permissions added by different process.
1287 API int app_give_access(const char* subject, const char* object, const char* permissions)
1289 C_LOGD("Enter function: %s", __func__);
1290 int ret = PC_OPERATION_SUCCESS;
1291 struct smack_accesses *smack AUTO_SMACK_FREE;
1292 static const char * const revoke = "-----";
1293 char *current_permissions AUTO_FREE;
1296 return PC_OPERATION_SUCCESS;
1298 if (!smack_label_is_valid(subject) || !smack_label_is_valid(object))
1299 return PC_ERR_INVALID_PARAM;
1301 if (PC_OPERATION_SUCCESS != (ret = smack_get_access_new(subject, object, ¤t_permissions)))
1304 if (smack_accesses_new(&smack))
1305 return PC_ERR_MEM_OPERATION;
1307 if (smack_accesses_add_modify(smack, subject, object, permissions, revoke))
1308 return PC_ERR_MEM_OPERATION;
1310 if (smack_accesses_apply(smack))
1311 return PC_ERR_NOT_PERMITTED;
1313 ret = state_save(subject, object, current_permissions);
1319 * This function will be used to revoke direct communication between 2 OSP application.
1321 * Full implementation requires some kind of database. This implemetation works without
1322 * database so you wont be able to revoke permissions added by different process.
1324 API int app_revoke_access(const char* subject, const char* object)
1326 C_LOGD("Enter function: %s", __func__);
1328 return PC_OPERATION_SUCCESS;
1330 if (!smack_label_is_valid(subject) || !smack_label_is_valid(object))
1331 return PC_ERR_INVALID_PARAM;
1333 return state_restore(subject, object);
1336 API int app_label_shared_dir(const char* app_label, const char* shared_label, const char* path)
1338 C_LOGD("Enter function: %s", __func__);
1341 if (!smack_label_is_valid(app_label) || !smack_label_is_valid(shared_label))
1342 return PC_ERR_INVALID_PARAM;
1344 if (strcmp(app_label, shared_label) == 0) {
1345 C_LOGE("app_label equals shared_label");
1346 return PC_ERR_INVALID_PARAM;
1349 //setting label on everything in given directory and below
1350 ret = dir_set_smack_r(path, shared_label, SMACK_LABEL_ACCESS, label_all);
1351 if(ret != PC_OPERATION_SUCCESS){
1352 C_LOGE("dir_set_smakc_r failed");
1356 //setting transmute on dir
1357 ret = dir_set_smack_r(path, "1", SMACK_LABEL_TRANSMUTE, label_dirs);
1358 if (ret != PC_OPERATION_SUCCESS) {
1359 C_LOGE("dir_set_smakc_r failed");
1363 ret = app_add_rule(app_label, shared_label, "rwxat");
1364 if (ret != PC_OPERATION_SUCCESS) {
1365 C_LOGE("app_add_rule failed");
1369 return PC_OPERATION_SUCCESS;
1372 API int add_shared_dir_readers(const char* shared_label, const char** app_list)
1374 C_LOGD("Enter function: %s", __func__);
1378 if (!smack_label_is_valid(shared_label))
1379 return PC_ERR_INVALID_PARAM;
1381 for (i = 0; app_list[i] != NULL; i++) {
1383 if (!smack_label_is_valid(app_list[i]))
1384 return PC_ERR_INVALID_PARAM;
1386 ret = app_add_rule(app_list[i], shared_label, "rx");
1387 if (ret != PC_OPERATION_SUCCESS) {
1388 C_LOGE("app_add_rule failed");
1393 return PC_OPERATION_SUCCESS;
1396 static char* smack_label_for_path(const char *app_id, const char *path)
1398 C_LOGD("Enter function: %s", __func__);
1399 char *salt AUTO_FREE;
1403 /* Prefix $1$ causes crypt() to use MD5 function */
1404 if (-1 == asprintf(&salt, "$1$%s", app_id)) {
1405 C_LOGE("asprintf failed");
1409 label = crypt(path, salt);
1410 if (label == NULL) {
1411 C_LOGE("crypt failed");
1415 /* crypt() output may contain slash character,
1416 * which is not legal in Smack labels */
1417 for (x = label; *x; ++x) {
1425 /* FIXME: remove this pragma once deprecated API is deleted */
1426 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
1427 API int app_setup_path(const char* app_id, const char* path, app_path_type_t app_path_type, ...)
1429 C_LOGD("Enter function: %s", __func__);
1432 if (!smack_label_is_valid(app_id)) {
1433 C_LOGE("Invalid app_id %s", app_id);
1434 return PC_ERR_INVALID_PARAM;
1437 switch (app_path_type) {
1438 case APP_PATH_PRIVATE:
1439 va_start(ap, app_path_type);
1441 return app_label_dir(app_id, path);
1443 case APP_PATH_GROUP_RW: {
1444 const char *shared_label;
1446 va_start(ap, app_path_type);
1447 shared_label = va_arg(ap, const char *);
1450 if (!smack_label_is_valid(shared_label)) {
1451 C_LOGE("Invalid shared_label %s", shared_label);
1452 return PC_ERR_INVALID_PARAM;
1455 if (strcmp(app_id, shared_label) == 0) {
1456 C_LOGE("app_id equals shared_label");
1457 return PC_ERR_INVALID_PARAM;
1460 return app_label_shared_dir(app_id, shared_label, path);
1463 case APP_PATH_PUBLIC_RO: {
1464 char **app_ids AUTO_FREE;
1465 int app_ids_cnt = 0;
1469 va_start(ap, app_path_type);
1472 C_LOGD("New public RO path %s", path);
1473 label = smack_label_for_path(app_id, path);
1475 return PC_ERR_INVALID_OPERATION;
1477 C_LOGD("Generated label '%s' for public RO path %s", label, path);
1478 ret = app_label_shared_dir(app_id, label, path);
1479 if (ret != PC_OPERATION_SUCCESS)
1482 /* FIXME: This should be in some kind of transaction/lock */
1483 ret = db_add_public_dir(label);
1484 if (ret != PC_OPERATION_SUCCESS)
1487 ret = get_all_apps_ids(&app_ids, &app_ids_cnt);
1488 if (ret != PC_OPERATION_SUCCESS)
1491 for (i = 0; i < app_ids_cnt; ++i) {
1492 C_LOGD("Allowing app %s to access public path %s", app_id, label[i]);
1493 ret = app_add_rule(app_ids[i], label, "rx");
1494 if (ret != PC_OPERATION_SUCCESS) {
1495 C_LOGE("smack_accesses_new failed");
1496 while (i < app_ids_cnt)
1503 return PC_OPERATION_SUCCESS;
1506 case APP_PATH_SETTINGS_RW:
1507 va_start(ap, app_path_type);
1513 va_start(ap, app_path_type);
1515 return PC_ERR_INVALID_PARAM;
1518 return PC_OPERATION_SUCCESS;
1520 /* FIXME: remove this pragma once deprecated API is deleted */
1521 #pragma GCC diagnostic warning "-Wdeprecated-declarations"
1523 API int app_add_friend(const char* app_id1, const char* app_id2)
1525 C_LOGD("Enter function: %s", __func__);
1528 if (!smack_label_is_valid(app_id1) || !smack_label_is_valid(app_id2))
1529 return PC_ERR_INVALID_PARAM;
1531 ret = app_add_rule(app_id1, app_id2, "rwxat");
1532 if (ret != PC_OPERATION_SUCCESS) {
1533 C_LOGE("app_add_rule failed");
1537 ret = app_add_rule(app_id2, app_id1, "rwxat");
1538 if (ret != PC_OPERATION_SUCCESS) {
1539 C_LOGE("app_add_rule failed");
1543 return PC_OPERATION_SUCCESS;
1546 API int app_install(const char* app_id)
1548 C_LOGD("Enter function: %s", __func__);
1551 char* smack_path AUTO_FREE;
1552 struct smack_accesses *smack AUTO_SMACK_FREE;
1554 if (!smack_label_is_valid(app_id))
1555 return PC_ERR_INVALID_PARAM;
1557 ret = smack_file_name(app_id, &smack_path);
1558 if (ret != PC_OPERATION_SUCCESS)
1561 fd = open(smack_path, O_RDWR|O_CREAT, 0644);
1563 C_LOGE("file open failed: %s", strerror(errno));
1564 return PC_ERR_FILE_OPERATION;
1567 if (smack_accesses_new(&smack)) {
1568 C_LOGE("smack_accesses_new failed");
1569 return PC_ERR_MEM_OPERATION;
1572 ret = add_app_id_to_databse(app_id);
1573 if (ret != PC_OPERATION_SUCCESS ) {
1574 C_LOGE("Error while adding app %s to database: %s ", app_id, strerror(errno));
1578 ret = register_app_for_av(app_id);
1579 if (ret != PC_OPERATION_SUCCESS) {
1580 C_LOGE("Error while adding rules for anti viruses to app %s: %s ", app_id, strerror(errno));
1584 ret = register_app_for_public_dirs(app_id, smack);
1585 if (ret != PC_OPERATION_SUCCESS) {
1586 C_LOGE("Error while adding rules for access to public dirs for app %s: %s ", app_id, strerror(errno));
1590 if (have_smack() && smack_accesses_apply(smack)) {
1591 C_LOGE("smack_accesses_apply failed");
1592 return PC_ERR_INVALID_OPERATION;
1595 if (smack_accesses_save(smack, fd)) {
1596 C_LOGE("smack_accesses_save failed");
1597 return PC_ERR_INVALID_OPERATION;
1600 return PC_OPERATION_SUCCESS;
1603 API int app_uninstall(const char* app_id)
1605 // TODO: When real database will be used, then this function should remove app_id
1607 // It also should remove rules looks like: "anti_virus_label app_id rwx".
1608 C_LOGD("Enter function: %s", __func__);
1609 char* smack_path AUTO_FREE;
1612 if (!smack_label_is_valid(app_id))
1613 return PC_ERR_INVALID_PARAM;
1615 ret = smack_file_name(app_id, &smack_path);
1616 if (ret != PC_OPERATION_SUCCESS)
1619 if (unlink(smack_path)) {
1620 C_LOGE("unlink failed: ", strerror(errno));
1621 return PC_OPERATION_SUCCESS;
1624 return PC_OPERATION_SUCCESS;
1627 static int save_rules(int fd, struct smack_accesses* accesses) {
1628 if (flock(fd, LOCK_EX)) {
1629 C_LOGE("flock failed, error %s", strerror(errno));
1630 return PC_ERR_FILE_OPERATION;
1633 if (smack_accesses_save(accesses, fd)) {
1634 C_LOGE("smack_accesses_save failed");
1635 return PC_ERR_FILE_OPERATION;
1637 return PC_OPERATION_SUCCESS ;
1640 static int validate_and_add_rule(char* rule, struct smack_accesses* accesses) {
1641 const char* subject = NULL;
1642 const char* object = NULL;
1643 const char* access = NULL;
1644 char* saveptr = NULL;
1646 subject = strtok_r(rule, " \t\n", &saveptr);
1647 object = strtok_r(NULL, " \t\n", &saveptr);
1648 access = strtok_r(NULL, " \t\n", &saveptr);
1650 // check rule validity
1651 if (subject == NULL ||
1654 strtok_r(NULL, " \t\n", &saveptr) != NULL ||
1655 !smack_label_is_valid(subject) ||
1656 !smack_label_is_valid(object))
1658 C_LOGE("Incorrect rule format: %s", rule);
1659 return PC_ERR_INVALID_PARAM;
1662 if (smack_accesses_add(accesses, subject, object, access)) {
1663 C_LOGE("smack_accesses_add failed");
1664 return PC_ERR_INVALID_OPERATION;
1666 return PC_OPERATION_SUCCESS ;
1669 static int parse_and_save_rules(const char** smack_rules,
1670 struct smack_accesses* accesses, const char* feature_file) {
1673 int ret = PC_OPERATION_SUCCESS;
1676 for (i = 0; smack_rules[i] != NULL ; i++) {
1677 // ignore empty lines
1678 if (strspn(smack_rules[i], " \t\n") == strlen(smack_rules[i]))
1681 tmp = strdup(smack_rules[i]);
1682 ret = validate_and_add_rule(tmp, accesses);
1684 if (ret != PC_OPERATION_SUCCESS )
1689 fd = open(feature_file, O_CREAT | O_WRONLY, 0644);
1691 C_LOGE("Unable to create file %s. Error: %s", feature_file, strerror(errno));
1692 return PC_ERR_FILE_OPERATION;
1695 ret = save_rules(fd, accesses);
1700 static int save_gids(FILE* file, const gid_t* list_of_db_gids, size_t list_size) {
1701 int ret = PC_OPERATION_SUCCESS;
1706 C_LOGE("Unable to create file. Error: %s", strerror(errno));
1707 return PC_ERR_FILE_OPERATION; // TODO remove smack accesses?
1710 if(-1 == fchmod(fileno(file), 0644)) {
1711 C_LOGE("Unable to chmod file. Error: %s", strerror(errno));
1712 return PC_ERR_FILE_OPERATION;
1715 for (i = 0; i < list_size ; ++i) {
1716 written = fprintf(file, "%u\n", list_of_db_gids[i]);
1718 C_LOGE("fprintf failed for file. Error: %s", strerror(errno));
1719 ret = PC_ERR_FILE_OPERATION;
1726 API int add_api_feature(app_type_t app_type,
1727 const char* api_feature_name,
1728 const char** smack_rules,
1729 const gid_t* list_of_db_gids,
1731 C_LOGD("Enter function: %s", __func__);
1733 int ret = PC_OPERATION_SUCCESS;
1734 char* smack_file AUTO_FREE;
1735 char* dac_file AUTO_FREE;
1736 struct smack_accesses* accesses = NULL;
1739 // TODO check process capabilities
1741 // get feature SMACK file name
1742 ret = perm_file_path(&smack_file, app_type, api_feature_name, ".smack");
1743 if (ret != PC_OPERATION_SUCCESS || !smack_file ) {
1747 // check if feature exists
1748 if (file_exists(smack_file)) {
1749 C_LOGE("Feature file %s already exists", smack_file);
1750 return PC_ERR_INVALID_PARAM;
1753 // check .dac existence only if gids are supported
1754 if (list_of_db_gids && list_size > 0) {
1755 // get feature DAC file name
1756 ret = perm_file_path(&dac_file, app_type, api_feature_name, ".dac");
1757 if (ret != PC_OPERATION_SUCCESS || !dac_file ) {
1761 // check if feature exists
1762 if (file_exists(dac_file)) {
1763 C_LOGE("Feature file %s already exists", dac_file);
1764 return PC_ERR_INVALID_PARAM;
1768 // parse & save rules
1770 if (smack_accesses_new(&accesses)) {
1771 C_LOGE("smack_acceses_new failed");
1772 return PC_ERR_MEM_OPERATION;
1775 ret = parse_and_save_rules(smack_rules, accesses, smack_file);
1776 smack_accesses_free(accesses);
1779 // go through gid list
1780 if (ret == PC_OPERATION_SUCCESS && list_of_db_gids && list_size > 0) {
1782 file = fopen(dac_file, "w+");
1783 ret = save_gids(file, list_of_db_gids, list_size);
1787 // remove both files in case of failure
1788 if (ret != PC_OPERATION_SUCCESS) {
1797 * This function is marked as deprecated and will be removed
1799 API int app_register_av(const char* app_av_id)
1803 char* smack_path AUTO_FREE;
1804 struct smack_accesses* smack AUTO_SMACK_FREE;
1806 ret = load_smack_from_file(app_av_id, &smack, &fd, &smack_path);
1807 if (ret != PC_OPERATION_SUCCESS ) {
1808 C_LOGE("load_smack_from_file failed");
1812 ret = app_register_av_internal(app_av_id, smack);
1813 if (PC_OPERATION_SUCCESS != ret) {
1814 C_LOGE("app_register_av_internal failed");
1818 // Add permisions from OSP_antivirus.samck file
1819 ret = perm_to_smack(smack, app_av_id, APP_TYPE_OSP, TIZEN_PRIVILEGE_ANTIVIRUS);
1820 if (PC_OPERATION_SUCCESS != ret) {
1821 C_LOGE("perm_to_smack failed");
1825 // Add permisions from OSP_antivirus.dac file
1826 ret = perm_to_dac(app_av_id, APP_TYPE_OSP, TIZEN_PRIVILEGE_ANTIVIRUS);
1827 if (ret != PC_OPERATION_SUCCESS) {
1828 C_LOGE("perm_to_dac failed");
1832 if (have_smack() && smack_accesses_apply(smack)) {
1833 C_LOGE("smack_accesses_apply failed");
1834 ret = PC_ERR_INVALID_OPERATION;
1838 if (smack_accesses_save(smack, fd)) {
1839 C_LOGE("smack_accesses_save failed");
1840 ret = PC_ERR_INVALID_OPERATION;