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>
42 #include "privilege-control.h"
46 #define DEVELOPER_GID 5100
47 #define DEVELOPER_UID 5100
49 #define APP_USER_NAME "app"
50 #define DEV_USER_NAME "developer"
52 #define APP_HOME_DIR TOSTRING(HOMEDIR) "/app"
53 #define DEV_HOME_DIR TOSTRING(HOMEDIR) "/developer"
55 #define APP_GROUP_PATH TOSTRING(SHAREDIR) "/app_group_list"
56 #define DEV_GROUP_PATH TOSTRING(SHAREDIR) "/dev_group_list"
58 #define SMACK_RULES_DIR "/etc/smack/accesses.d/"
60 #define SMACK_APP_LABEL "~APP~"
61 #define SMACK_WRT_LABEL_PREFIX "wrt_widget_"
62 #define SMACK_SRC_FILE_SUFFIX "_src_file"
63 #define SMACK_SRC_DIR_SUFFIX "_src_dir"
64 #define SMACK_DATA_SUFFIX "_data"
65 #define WRT_BASE_DEVCAP "WRT"
66 #define WRT_CLIENT_PATH "/usr/bin/wrt-client"
69 #undef WRT_SMACK_ENABLED
72 #ifdef WRT_SMACK_ENABLED
73 static int set_smack_for_wrt(const char* widget_id);
74 #endif // WRT_SMACK_ENABLED
80 #define LOG_TAG "PRIVILEGE_CONTROL"
83 // conditional_log macro for dlogutil (debug)
85 #define C_LOGD(...) LOGD(__VA_ARGS__)
86 #define C_LOGE(...) LOGE(__VA_ARGS__)
88 #define C_LOGD(...) do { } while(0)
89 #define C_LOGE(...) do { } while(0)
105 API int control_privilege(void)
107 C_LOGD("Enter function: %s", __func__);
108 if(getuid() == APP_UID) // current user is 'app'
109 return PC_OPERATION_SUCCESS;
111 if(set_app_privilege("com.samsung.", NULL, NULL) == PC_OPERATION_SUCCESS)
112 return PC_OPERATION_SUCCESS;
114 return PC_ERR_NOT_PERMITTED;
117 static int set_dac(const char* pkg_name)
119 C_LOGD("Enter function: %s", __func__);
120 FILE* fp_group = NULL; // /etc/group
121 uid_t t_uid = -1; // uid of current process
122 gid_t *glist = NULL; // group list
123 gid_t temp_gid = -1; // for group list
124 char buf[10] = {0, }; // contents in group_list file
125 int glist_cnt = 0; // for group list
131 * initialize user structure
133 C_LOGD("initialize user structure");
134 memset(usr.user_name, 0x00, 10);
135 memset(usr.home_dir, 0x00, 64);
136 memset(usr.group_list, 0x00, 64);
141 C_LOGD("Current uid is %d", t_uid);
143 if(t_uid == 0) // current user is 'root'
145 if(!strncmp(pkg_name, "developer", 9))
147 strncpy(usr.user_name, DEV_USER_NAME, sizeof(usr.user_name));
148 usr.uid = DEVELOPER_UID;
149 usr.gid = DEVELOPER_GID;
150 strncpy(usr.home_dir, DEV_HOME_DIR, sizeof(usr.home_dir));
151 strncpy(usr.group_list, DEV_GROUP_PATH, sizeof(usr.group_list));
155 strncpy(usr.user_name, APP_USER_NAME, sizeof(usr.user_name));
158 strncpy(usr.home_dir, APP_HOME_DIR, sizeof(usr.home_dir));
159 strncpy(usr.group_list, APP_GROUP_PATH, sizeof(usr.group_list));
163 * get group information
165 C_LOGD("get group information");
166 if(!(fp_group = fopen(usr.group_list, "r")))
168 C_LOGE("[ERR] file open error: [%s]\n", usr.group_list);
169 result = PC_ERR_FILE_OPERATION; // return -1
173 while(fgets(buf, 10, fp_group) != NULL)
176 temp_gid = strtoul(buf, 0, 10);
177 if(errno != 0) // error occured during strtoul()
179 C_LOGE("[ERR] cannot change string to integer: [%s]", buf);
180 result = PC_ERR_INVALID_OPERATION;
184 glist = (gid_t*)realloc(glist, sizeof(gid_t) * (glist_cnt + 1));
187 result = PC_ERR_MEM_OPERATION; // return -2
188 C_LOGE("Cannot allocate memory");
191 glist[glist_cnt] = temp_gid;
200 C_LOGD("Adding process to the following groups:");
201 for(i=0; i<glist_cnt; ++i) {
202 C_LOGD("glist [ %d ] = %d", i, glist[i]);
204 C_LOGD("setgroups()");
205 if(setgroups(glist_cnt, glist) != 0)
207 C_LOGE("[ERR] setgrouops fail\n");
208 result = PC_ERR_NOT_PERMITTED; // return -3
218 * setuid() & setgid()
220 C_LOGD("setgid( %d ) & setuid( %d )", usr.gid, usr.uid);
221 if(setgid(usr.gid) != 0) // fail
223 C_LOGE("[ERR] fail to execute setgid().");
224 result = PC_ERR_INVALID_OPERATION;
227 if(setuid(usr.uid) != 0) // fail
229 C_LOGE("[ERR] fail to execute setuid().");
230 result = PC_ERR_INVALID_OPERATION;
234 C_LOGD("setenv(): USER = %s, HOME = %s", usr.user_name, usr.home_dir);
235 if(setenv("USER", usr.user_name, 1) != 0) //fail
237 C_LOGE("[ERR] fail to execute setenv() [USER].");
238 result = PC_ERR_INVALID_OPERATION;
241 if(setenv("HOME", usr.home_dir, 1) != 0) // fail
243 C_LOGE("[ERR] fail to execute setenv() [HOME].");
244 result = PC_ERR_INVALID_OPERATION;
248 else // current user is not only 'root' but 'app'
250 C_LOGE("[ERR] current user is NOT root\n");
251 result = PC_ERR_NOT_PERMITTED; // return -3
255 result = PC_OPERATION_SUCCESS;
268 * Set process SMACK label from EXEC label of a file.
269 * This function is emulating EXEC label behaviour of SMACK for programs
270 * run by dlopen/dlsym instead of execv.
272 * @param path file path to take label from
273 * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
275 static int set_smack_from_binary(const char* path)
277 C_LOGD("Enter function: %s", __func__);
281 C_LOGD("Path: %s", path);
282 ret = smack_lgetlabel(path, &label, SMACK_LABEL_EXEC);
284 C_LOGE("smack_lgetlabel returned PC_ERR_INVALID_OPERATION");
285 return PC_ERR_INVALID_OPERATION;
289 /* No label to set, just return with success */
290 C_LOGD("No label to set, just return with success");
291 ret = PC_OPERATION_SUCCESS;
294 ret = smack_set_label_for_self(label);
295 C_LOGD("label = %s", label);
296 C_LOGD("smack_set_label_for_self returned %d", ret);
303 static int is_widget(const char* path)
305 C_LOGD("Enter function: %s", __func__);
306 char buf[sizeof(WRT_CLIENT_PATH)];
309 ret = readlink(path, buf, sizeof(WRT_CLIENT_PATH));
311 C_LOGD("readlink(%s) returned error: %s. Assuming that app is not a widget", path, strerror(errno));
312 else if (ret == sizeof(WRT_CLIENT_PATH))
313 C_LOGD("%s is not a widget", path);
314 if (ret == -1 || ret == sizeof(WRT_CLIENT_PATH))
317 C_LOGD("buf = %s", buf);
319 ret = !strcmp(WRT_CLIENT_PATH, buf);
320 C_LOGD("%s is %s widget", path, ret ? "a" : "not a");
325 * Partially verify, that the type given for app is correct.
326 * This function will use some heuristics to check whether the app type is right.
327 * It is intended for security hardening to catch privilege setting for the
328 * app type not corresponding to the actual binary.
329 * Beware - when it detects an anomaly, the whole process will be terminated.
331 * @param type claimed application type
332 * @param path file path to executable
333 * @return return void on success, terminate the process on error
335 static pkg_type_t verify_app_type(const char* type, const char* path)
337 C_LOGD("Enter function: %s", __func__);
338 /* TODO: this should actually be treated as error, but until the old
339 * set_privilege API is removed, it must be ignored */
341 C_LOGD("PKG_TYPE_OTHER");
342 return PKG_TYPE_OTHER; /* good */
345 if (is_widget(path)) {
346 if (!strcmp(type, "wgt")) {
347 C_LOGD("PKG_TYPE_WGT");
348 return PKG_TYPE_WGT; /* good */
351 if (type == NULL || strcmp(type, "wgt")){
352 C_LOGD("PKG_TYPE_OTHER");
353 return PKG_TYPE_OTHER; /* good */
358 C_LOGE("EXIT_FAILURE");
362 static const char* parse_widget_id(const char* path)
364 C_LOGD("Enter function: %s", __func__);
365 const char* basename = strrchr(path, '/');
367 if (basename == NULL)
372 C_LOGD("return widget id: %s", basename);
375 #endif // SMACK_ENABLED
377 API int set_app_privilege(const char* name, const char* type, const char* path)
379 C_LOGD("Enter function: %s", __func__);
380 C_LOGD("Function params: name = %s, type = %s, path = %s", name, type, path);
382 const char* widget_id;
383 int ret = PC_OPERATION_SUCCESS;
385 switch(verify_app_type(type, path)) {
387 widget_id = parse_widget_id(path);
388 if (widget_id == NULL) {
389 C_LOGE("PC_ERR_INVALID_PARAM");
390 ret = PC_ERR_INVALID_PARAM;
392 #ifdef WRT_SMACK_ENABLED
394 ret = set_smack_for_wrt(widget_id);
399 ret = set_smack_from_binary(path);
402 if (ret != PC_OPERATION_SUCCESS)
404 #endif // SMACK_ENABLED
406 return set_dac(name);
409 API int set_privilege(const char* pkg_name)
411 C_LOGD("Enter function: %s", __func__);
412 return set_app_privilege(pkg_name, NULL, NULL);
415 API int wrt_set_privilege(const char* widget_id)
417 C_LOGD("Enter function: %s", __func__);
418 #ifdef WRT_SMACK_ENABLED
421 ret = set_smack_for_wrt(widget_id);
422 if (ret != PC_OPERATION_SUCCESS) {
423 C_LOGE("set_smack_for_wrt returned error");
426 #endif // WRT_SMACK_ENABLED
428 return set_dac("com.samsung.");
431 #ifdef WRT_SMACK_ENABLED
432 static inline char* wrt_smack_label(const char* widget_id, const char* suffix)
434 C_LOGD("Enter function: %s", __func__);
438 ret = asprintf(&label, "%s%s%s", SMACK_WRT_LABEL_PREFIX, widget_id,
439 (suffix ? suffix : ""));
442 C_LOGE("asprintf failed");
446 if (strlen(label) > SMACK_LABEL_LEN) {
447 C_LOGE("strlen(label) [%s] > SMACK_LABEL_LEN", label);
454 #endif // WRT_SMACK_ENABLED
456 static inline int perm_to_smack(struct smack_accesses* smack, const char* app_label, const char* perm)
458 C_LOGD("Enter function: %s", __func__);
459 int ret = PC_OPERATION_SUCCESS;
461 char* format_string = NULL;
463 char smack_subject[SMACK_LABEL_LEN + 1];
464 char smack_object[SMACK_LABEL_LEN + 1];
465 char smack_accesses[10];
467 if (asprintf(&path, TOSTRING(SHAREDIR) "/%s.smack", perm) == -1) {
468 C_LOGE("asprintf failed");
469 ret = PC_ERR_MEM_OPERATION;
473 if (asprintf(&format_string,"%%%ds %%%ds %%%ds\n",
474 SMACK_LABEL_LEN, SMACK_LABEL_LEN, sizeof(smack_accesses)) == -1) {
475 C_LOGE("asprintf failed");
476 ret = PC_ERR_MEM_OPERATION;
480 file = fopen(path, "r");
481 C_LOGD("path = %s", path);
483 C_LOGE("fopen failed");
484 ret = PC_ERR_FILE_OPERATION;
489 if (fscanf(file, format_string, smack_subject, smack_object, smack_accesses) != 3) {
490 C_LOGE("fscanf failed");
494 if (!strcmp(smack_subject, SMACK_APP_LABEL))
495 strcpy(smack_subject, app_label);
497 if (!strcmp(smack_object, SMACK_APP_LABEL))
498 strcpy(smack_object, app_label);
500 C_LOGD("smack_accesses_add_modify (subject: %s, object: %s, access: %s)", smack_subject, smack_object, smack_accesses);
501 if (smack_accesses_add_modify(smack, smack_subject, smack_object, smack_accesses, "") != 0) {
502 C_LOGE("smack_accesses_add_modify failed");
503 ret = PC_ERR_INVALID_OPERATION;
516 API int wrt_permissions_reset(const char* widget_id)
518 C_LOGD("Enter function: %s", __func__);
519 int ret = PC_OPERATION_SUCCESS;
520 #ifdef WRT_SMACK_ENABLED
523 label = wrt_smack_label(widget_id, NULL);
525 C_LOGE("wrt_smack_label failed");
526 return PC_ERR_MEM_OPERATION;
529 if (smack_revoke_subject(label)) {
530 C_LOGE("smack_revoke_subject failed");
531 ret = PC_ERR_INVALID_OPERATION;
535 #endif // WRT_SMACK_ENABLED
539 API int wrt_permissions_add(const char* widget_id, const char** devcap_list)
541 C_LOGD("Enter function: %s", __func__);
542 int ret = PC_OPERATION_SUCCESS;
543 #ifdef WRT_SMACK_ENABLED
544 char* widget_label = NULL;
545 struct smack_accesses* smack = NULL;
548 widget_label = wrt_smack_label(widget_id, NULL);
549 if (widget_label == NULL) {
550 C_LOGE("wrt_smack_label failed");
551 return PC_ERR_MEM_OPERATION;
554 if (smack_accesses_new(&smack)) {
555 C_LOGE("smack_accesses_new failed");
556 ret = PC_ERR_MEM_OPERATION;
560 for (i = 0; devcap_list[i] != NULL; ++i) {
563 /* Prepend devcap with "WRT_" */
564 if (asprintf(&perm, "%s_%s", WRT_BASE_DEVCAP, devcap_list[i]) == -1) {
565 C_LOGE("asprintf failed");
566 ret = PC_ERR_MEM_OPERATION;
570 C_LOGD("Adding permission %s", perm);
571 ret = perm_to_smack(smack, widget_label, perm);
573 if (ret != PC_OPERATION_SUCCESS) {
574 C_LOGE("perm_to_smack failed (%d)", ret);
579 if (smack_accesses_apply(smack) != 0) {
580 C_LOGE("smack_accesses_apply failed");
581 ret = PC_ERR_INVALID_OPERATION;
586 smack_accesses_free(smack);
588 #endif // WRT_SMACK_ENABLED
592 static int dir_set_smack_r(const char *path, const char* label,
593 enum smack_label_type type, mode_t type_mask)
595 C_LOGD("Enter function: %s", __func__);
597 const char* path_argv[] = {path, NULL};
601 ret = PC_ERR_FILE_OPERATION;
603 fts = fts_open((char * const *) path_argv, FTS_PHYSICAL | FTS_NOCHDIR, NULL);
605 C_LOGE("fts_open failed");
609 while ((ftsent = fts_read(fts)) != NULL) {
610 /* Check for error (FTS_ERR) or failed stat(2) (FTS_NS) */
611 if (ftsent->fts_info == FTS_ERR || ftsent->fts_info == FTS_NS) {
612 C_LOGE("FTS_ERR error or failed stat(2) (FTS_NS)");
616 C_LOGD("smack_lsetlabel (label: %s (type: %d), path: %s)", label, type, ftsent->fts_path);
617 if (ftsent->fts_statp->st_mode & S_IFMT & type_mask)
618 if (smack_lsetlabel(ftsent->fts_path, label, type) != 0) {
619 C_LOGE("smack_lsetlabel failed");
624 /* If last call to fts_read() set errno, we need to return error. */
626 ret = PC_OPERATION_SUCCESS;
628 C_LOGE("Last errno: %s", strerror(errno));
636 API int wrt_set_src_dir(const char* widget_id, const char *path)
638 C_LOGD("Enter function: %s", __func__);
639 C_LOGD("Path: %s", path);
640 int ret = PC_OPERATION_SUCCESS;
641 #ifdef WRT_SMACK_ENABLED
642 char* src_label_dir = NULL;
643 char* src_label_file = NULL;
645 ret = PC_ERR_MEM_OPERATION;
647 src_label_dir = wrt_smack_label(widget_id, SMACK_SRC_DIR_SUFFIX);
648 if (src_label_dir == NULL) {
649 C_LOGE("src_label_dir is NULL");
653 src_label_file = wrt_smack_label(widget_id, SMACK_SRC_FILE_SUFFIX);
654 if (src_label_file == NULL) {
655 C_LOGE("src_label_file in NULL");
659 /* Set label for directories */
660 ret = dir_set_smack_r(path, src_label_dir, SMACK_LABEL_ACCESS, S_IFDIR);
661 if (ret != PC_OPERATION_SUCCESS) {
662 C_LOGE("dir_set_smack_r failed");
666 /* Set label for non-directories */
667 ret = dir_set_smack_r(path, src_label_file, SMACK_LABEL_ACCESS, ~S_IFDIR);
671 free(src_label_file);
672 #endif // WRT_SMACK_ENABLED
676 API int wrt_set_data_dir(const char* widget_id, const char *path)
678 C_LOGD("Enter function: %s", __func__);
679 C_LOGD("Path: %s", path);
680 int ret = PC_OPERATION_SUCCESS;
681 #ifdef WRT_SMACK_ENABLED
682 char* data_label = NULL;
685 ret = PC_ERR_FILE_OPERATION;
686 /* Check whether path exists */
687 if (lstat(path, &st) == 0) {
688 if (!S_ISDIR(st.st_mode)) {
689 /* Exists, but it's not a directory? */
690 C_LOGE("Exists, but it's not a directory?");
694 if (errno != ENOENT) {
695 /* Some other error than "no such file or directory" */
696 C_LOGE("Other error: %s", strerror(errno));
699 if (mkdir(path, S_IRWXU) != 0) {
700 /* Error while creating the directory */
701 C_LOGE("Error while creating the directory");
704 if (chown(path, APP_UID, APP_GID)) {
705 /* Error while setting the directory owner */
706 C_LOGE("Error while setting the directory owner");
714 ret = PC_ERR_MEM_OPERATION;
716 data_label = wrt_smack_label(widget_id, SMACK_DATA_SUFFIX);
717 if (data_label == NULL) {
718 C_LOGE("data_label is NULL");
722 /* Set label for everything inside data path */
723 ret = dir_set_smack_r(path, data_label, SMACK_LABEL_ACCESS, ~0);
724 if (ret != PC_OPERATION_SUCCESS) {
725 C_LOGE("dir_set_smack_r failed");
729 /* Enable transmute on all directories */
730 ret = dir_set_smack_r(path, "1", SMACK_LABEL_TRANSMUTE, S_IFDIR);
731 if (ret != PC_OPERATION_SUCCESS) {
732 C_LOGE("dir_set_smack_r failed");
738 #endif // WRT_SMACK_ENABLED
742 #ifdef WRT_SMACK_ENABLED
743 static int set_smack_for_wrt(const char* widget_id)
745 C_LOGD("Enter function: %s", __func__);
746 char* widget_label = NULL;
747 char* src_label_file = NULL;
748 char* src_label_dir = NULL;
749 char* data_label = NULL;
750 struct smack_accesses* smack = NULL;
753 ret = PC_ERR_MEM_OPERATION;
755 widget_label = wrt_smack_label(widget_id, NULL);
756 C_LOGD("widget id: %s", widget_id);
757 if (widget_label == NULL) {
758 C_LOGE("widget_label is NULL");
762 src_label_file = wrt_smack_label(widget_id, SMACK_SRC_FILE_SUFFIX);
763 if (src_label_file == NULL) {
764 C_LOGE("src_label_file is NULL");
768 src_label_dir = wrt_smack_label(widget_id, SMACK_SRC_DIR_SUFFIX);
769 if (src_label_file == NULL) {
770 C_LOGE("src_label_file is NULL");
774 data_label = wrt_smack_label(widget_id, SMACK_DATA_SUFFIX);
775 if (data_label == NULL) {
776 C_LOGE("data_label is NULL");
780 if (smack_accesses_new(&smack) != 0) {
781 C_LOGE("smack_accesses_new failed");
785 ret = wrt_permissions_reset(widget_id);
786 if (ret != PC_OPERATION_SUCCESS) {
787 C_LOGE("wrt_permissions_reset failed");
791 ret = PC_ERR_INVALID_OPERATION;
793 if (smack_set_label_for_self(widget_label) != 0) {
794 C_LOGE("smack_set_label_for_self failed");
798 /* Allow widget to only read and execute it's source directories */
799 C_LOGD("Adding implicit Smack rule: %s %s %s", widget_label, src_label_dir, "rx");
800 if (smack_accesses_add(smack, widget_label, src_label_dir, "rx") != 0) {
801 C_LOGE("smack_accesses_add failed (rx)");
805 /* Allow widget to only read read it's source files */
806 C_LOGD("Adding implicit Smack rule: %s %s %s", widget_label, src_label_file, "r");
807 if (smack_accesses_add(smack, widget_label, src_label_file, "r") != 0) {
808 C_LOGE("smack_accesses_add failed (r)");
812 /* Allow widget to do everything with it's data */
814 * FIXME: If a malicious widget finds a way to execute files, it will be
815 * able to execute it's data files, which are fully controlled by the
816 * widget itself. This currently cannot be prevented by SMACK, so other
817 * means must be used.
819 C_LOGD("Adding implicit Smack rule: %s %s %s", widget_label, data_label, "rwxat");
820 if (smack_accesses_add(smack, widget_label, data_label, "rwxat") != 0) {
821 C_LOGE("smack_accesses_add failed (rwxat)");
825 C_LOGD("Adding Smack rules from pseudo-devcap %s", WRT_BASE_DEVCAP);
826 ret = perm_to_smack(smack, widget_label, WRT_BASE_DEVCAP);
827 if (ret != PC_OPERATION_SUCCESS) {
828 C_LOGE("perm_to_smack failed");
832 if (smack_accesses_apply(smack) != 0) {
833 C_LOGE("smack_accesses_apply failed");
834 ret = PC_ERR_INVALID_OPERATION;
838 smack_accesses_free(smack);
840 free(src_label_file);
846 #endif // WRT_SMACK_ENABLED
848 API char* wrt_widget_id_from_socket(int sockfd)
850 C_LOGD("Enter function: %s", __func__);
855 ret = smack_new_label_from_socket(sockfd, &smack_label);
857 C_LOGE("smack_new_label_from_socket failed");
861 if (strncmp(smack_label, SMACK_WRT_LABEL_PREFIX,
862 strlen(SMACK_WRT_LABEL_PREFIX))) {
867 widget_id = strdup(smack_label + strlen(SMACK_WRT_LABEL_PREFIX));
869 C_LOGD("widget id: %s", widget_id);
874 static int load_smack_from_file(const char* app_id, struct smack_accesses** smack, int *fd)
876 C_LOGD("Enter function: %s", __func__);
881 if (asprintf(&path, SMACK_RULES_DIR "/%s", app_id) == -1) {
882 ret = PC_ERR_MEM_OPERATION;
883 C_LOGE("asprintf failed");
887 if (smack_accesses_new(smack)) {
888 ret = PC_ERR_MEM_OPERATION;
889 C_LOGE("smack_accesses_new failed");
893 *fd = open(path, O_CREAT|O_RDWR, 0644);
895 ret = PC_ERR_FILE_OPERATION;
896 C_LOGE("file open failed");
900 if (flock(*fd, LOCK_EX)) {
901 ret = PC_ERR_INVALID_OPERATION;
902 C_LOGE("flock failed");
906 if (smack_accesses_add_from_file(*smack, *fd)) {
907 ret = PC_ERR_INVALID_OPERATION;
908 C_LOGE("smack_accesses_add_from_file failed");
912 /* Rewind the file */
913 if (lseek(*fd, 0, SEEK_SET) == -1) {
914 ret = PC_ERR_FILE_OPERATION;
915 C_LOGE("lseek failed");
919 ret = PC_OPERATION_SUCCESS;
927 static int save_smack_to_file(struct smack_accesses *smack, int fd)
929 if (smack_accesses_apply(smack)) {
930 C_LOGE("smack_accesses_apply failed");
931 return PC_ERR_INVALID_OPERATION;
934 if (smack_accesses_save(smack, fd)) {
935 C_LOGE("smack_accesses_save failed");
936 return PC_ERR_INVALID_OPERATION;
939 return PC_OPERATION_SUCCESS;
943 API int app_add_permissions(const char* app_id, const char** perm_list)
945 C_LOGD("Enter function: %s", __func__);
949 struct smack_accesses *smack = NULL;
953 ret = load_smack_from_file(app_id, &smack, &fd);
954 if (ret != PC_OPERATION_SUCCESS) {
955 C_LOGE("load_smack_from_file failed");
958 for (i = 0; perm_list[i] != NULL; ++i) {
959 ret = perm_to_smack(smack, app_id, perm_list[i]);
960 C_LOGD("perm_to_smack params: app_id: %s, perm_list[%d]: %s", app_id, i, perm_list[i]);
961 if (ret != PC_OPERATION_SUCCESS){
962 C_LOGE("perm_to_smack failed");
967 ret = save_smack_to_file(smack, fd);
968 if(ret != PC_OPERATION_SUCCESS){
969 C_LOGE("save_smack_to_file failed");
974 ret = PC_OPERATION_SUCCESS;
979 smack_accesses_free(smack);
985 API int app_revoke_permissions(const char* app_id)
987 C_LOGD("Enter function: %s", __func__);
991 struct smack_accesses *smack = NULL;
994 if (asprintf(&path, SMACK_RULES_DIR "/%s", app_id) == -1) {
995 ret = PC_ERR_MEM_OPERATION;
996 C_LOGE("asprintf failed");
1000 if (smack_accesses_new(&smack)) {
1001 ret = PC_ERR_MEM_OPERATION;
1002 C_LOGE("smack_accesses_new failed");
1006 fd = open(path, O_RDONLY);
1008 ret = PC_ERR_FILE_OPERATION;
1009 C_LOGE("file open failed");
1013 if (flock(fd, LOCK_EX | LOCK_NB)) {
1014 /* Non-blocking lock request on a file failed. */
1015 ret = PC_ERR_INVALID_OPERATION;
1016 C_LOGE("flock failed");
1021 ret = PC_ERR_INVALID_OPERATION;
1022 C_LOGE("unlink failed");
1026 if (smack_accesses_add_from_file(smack, fd)) {
1027 ret = PC_ERR_INVALID_OPERATION;
1028 C_LOGE("smack_accesses_add_from_file failed");
1032 if (smack_accesses_clear(smack)) {
1033 ret = PC_ERR_INVALID_OPERATION;
1034 C_LOGE("smack_accesses_clear failed");
1038 if (smack_revoke_subject(app_id)) {
1039 ret = PC_ERR_INVALID_OPERATION;
1040 C_LOGE("smack_revoke_subject failed");
1045 ret = PC_OPERATION_SUCCESS;
1050 smack_accesses_free(smack);
1056 API int app_label_dir(const char* label, const char* path)
1058 C_LOGD("Enter function: %s", __func__);
1059 #ifdef SMACK_ENABLED
1061 int ret = PC_OPERATION_SUCCESS;
1063 //setting label on everything in given directory and below
1064 ret = dir_set_smack_r(path, label, SMACK_LABEL_ACCESS, ~0);
1065 if (PC_OPERATION_SUCCESS != ret)
1068 //setting execute label for executable files
1069 ret = dir_set_smack_r(path, label, SMACK_LABEL_EXEC, S_IFREG | S_IXUSR);
1073 return PC_OPERATION_SUCCESS;
1077 API int app_label_shared_dir(const char* app_label, const char* shared_label, const char* path)
1079 C_LOGD("Enter function: %s", __func__);
1080 #ifdef SMACK_ENABLED
1083 struct smack_accesses *smack = NULL;
1086 //setting label on everything in given directory and below
1087 ret = dir_set_smack_r(path, shared_label, SMACK_LABEL_ACCESS, ~0);
1088 if(ret != PC_OPERATION_SUCCESS){
1089 C_LOGE("dir_set_smakc_r failed");
1093 //setting transmute on dir
1094 ret = dir_set_smack_r(path, "1", SMACK_LABEL_TRANSMUTE, S_IFDIR);
1095 if (ret != PC_OPERATION_SUCCESS) {
1096 C_LOGE("dir_set_smakc_r failed");
1100 ret = load_smack_from_file(app_label, &smack, &fd);
1101 if (ret != PC_OPERATION_SUCCESS) {
1102 C_LOGE("load_smack_from_file failed");
1106 //setting access rule for application
1107 if (smack_accesses_add(smack, app_label,shared_label, "wrxat") == -1) {
1108 C_LOGE("smack_accesses_add failed");
1112 ret = save_smack_to_file(smack, fd);
1113 if (ret != PC_OPERATION_SUCCESS) {
1114 C_LOGE("save_smack_to_file failed");
1118 ret = PC_OPERATION_SUCCESS;
1123 smack_accesses_free(smack);
1126 return PC_OPERATION_SUCCESS;