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 if (ftsent->fts_statp->st_mode & type_mask) {
617 C_LOGD("smack_lsetlabel (label: %s (type: %d), path: %s)", label, type, ftsent->fts_path);
618 if (smack_lsetlabel(ftsent->fts_path, label, type) != 0) {
619 C_LOGE("smack_lsetlabel failed");
625 /* If last call to fts_read() set errno, we need to return error. */
627 ret = PC_OPERATION_SUCCESS;
629 C_LOGE("Last errno: %s", strerror(errno));
637 API int wrt_set_src_dir(const char* widget_id, const char *path)
639 C_LOGD("Enter function: %s", __func__);
640 C_LOGD("Path: %s", path);
641 int ret = PC_OPERATION_SUCCESS;
642 #ifdef WRT_SMACK_ENABLED
643 char* src_label_dir = NULL;
644 char* src_label_file = NULL;
646 ret = PC_ERR_MEM_OPERATION;
648 src_label_dir = wrt_smack_label(widget_id, SMACK_SRC_DIR_SUFFIX);
649 if (src_label_dir == NULL) {
650 C_LOGE("src_label_dir is NULL");
654 src_label_file = wrt_smack_label(widget_id, SMACK_SRC_FILE_SUFFIX);
655 if (src_label_file == NULL) {
656 C_LOGE("src_label_file in NULL");
660 /* Set label for directories */
661 ret = dir_set_smack_r(path, src_label_dir, SMACK_LABEL_ACCESS, S_IFDIR);
662 if (ret != PC_OPERATION_SUCCESS) {
663 C_LOGE("dir_set_smack_r failed");
667 /* Set label for non-directories */
668 ret = dir_set_smack_r(path, src_label_file, SMACK_LABEL_ACCESS, ~S_IFDIR);
672 free(src_label_file);
673 #endif // WRT_SMACK_ENABLED
677 API int wrt_set_data_dir(const char* widget_id, const char *path)
679 C_LOGD("Enter function: %s", __func__);
680 C_LOGD("Path: %s", path);
681 int ret = PC_OPERATION_SUCCESS;
682 #ifdef WRT_SMACK_ENABLED
683 char* data_label = NULL;
686 ret = PC_ERR_FILE_OPERATION;
687 /* Check whether path exists */
688 if (lstat(path, &st) == 0) {
689 if (!S_ISDIR(st.st_mode)) {
690 /* Exists, but it's not a directory? */
691 C_LOGE("Exists, but it's not a directory?");
695 if (errno != ENOENT) {
696 /* Some other error than "no such file or directory" */
697 C_LOGE("Other error: %s", strerror(errno));
700 if (mkdir(path, S_IRWXU) != 0) {
701 /* Error while creating the directory */
702 C_LOGE("Error while creating the directory");
705 if (chown(path, APP_UID, APP_GID)) {
706 /* Error while setting the directory owner */
707 C_LOGE("Error while setting the directory owner");
715 ret = PC_ERR_MEM_OPERATION;
717 data_label = wrt_smack_label(widget_id, SMACK_DATA_SUFFIX);
718 if (data_label == NULL) {
719 C_LOGE("data_label is NULL");
723 /* Set label for everything inside data path */
724 ret = dir_set_smack_r(path, data_label, SMACK_LABEL_ACCESS, ~0);
725 if (ret != PC_OPERATION_SUCCESS) {
726 C_LOGE("dir_set_smack_r failed");
730 /* Enable transmute on all directories */
731 ret = dir_set_smack_r(path, "1", SMACK_LABEL_TRANSMUTE, S_IFDIR);
732 if (ret != PC_OPERATION_SUCCESS) {
733 C_LOGE("dir_set_smack_r failed");
739 #endif // WRT_SMACK_ENABLED
743 #ifdef WRT_SMACK_ENABLED
744 static int set_smack_for_wrt(const char* widget_id)
746 C_LOGD("Enter function: %s", __func__);
747 char* widget_label = NULL;
748 char* src_label_file = NULL;
749 char* src_label_dir = NULL;
750 char* data_label = NULL;
751 struct smack_accesses* smack = NULL;
754 ret = PC_ERR_MEM_OPERATION;
756 widget_label = wrt_smack_label(widget_id, NULL);
757 C_LOGD("widget id: %s", widget_id);
758 if (widget_label == NULL) {
759 C_LOGE("widget_label is NULL");
763 src_label_file = wrt_smack_label(widget_id, SMACK_SRC_FILE_SUFFIX);
764 if (src_label_file == NULL) {
765 C_LOGE("src_label_file is NULL");
769 src_label_dir = wrt_smack_label(widget_id, SMACK_SRC_DIR_SUFFIX);
770 if (src_label_file == NULL) {
771 C_LOGE("src_label_file is NULL");
775 data_label = wrt_smack_label(widget_id, SMACK_DATA_SUFFIX);
776 if (data_label == NULL) {
777 C_LOGE("data_label is NULL");
781 if (smack_accesses_new(&smack) != 0) {
782 C_LOGE("smack_accesses_new failed");
786 ret = wrt_permissions_reset(widget_id);
787 if (ret != PC_OPERATION_SUCCESS) {
788 C_LOGE("wrt_permissions_reset failed");
792 ret = PC_ERR_INVALID_OPERATION;
794 if (smack_set_label_for_self(widget_label) != 0) {
795 C_LOGE("smack_set_label_for_self failed");
799 /* Allow widget to only read and execute it's source directories */
800 C_LOGD("Adding implicit Smack rule: %s %s %s", widget_label, src_label_dir, "rx");
801 if (smack_accesses_add(smack, widget_label, src_label_dir, "rx") != 0) {
802 C_LOGE("smack_accesses_add failed (rx)");
806 /* Allow widget to only read read it's source files */
807 C_LOGD("Adding implicit Smack rule: %s %s %s", widget_label, src_label_file, "r");
808 if (smack_accesses_add(smack, widget_label, src_label_file, "r") != 0) {
809 C_LOGE("smack_accesses_add failed (r)");
813 /* Allow widget to do everything with it's data */
815 * FIXME: If a malicious widget finds a way to execute files, it will be
816 * able to execute it's data files, which are fully controlled by the
817 * widget itself. This currently cannot be prevented by SMACK, so other
818 * means must be used.
820 C_LOGD("Adding implicit Smack rule: %s %s %s", widget_label, data_label, "rwxat");
821 if (smack_accesses_add(smack, widget_label, data_label, "rwxat") != 0) {
822 C_LOGE("smack_accesses_add failed (rwxat)");
826 C_LOGD("Adding Smack rules from pseudo-devcap %s", WRT_BASE_DEVCAP);
827 ret = perm_to_smack(smack, widget_label, WRT_BASE_DEVCAP);
828 if (ret != PC_OPERATION_SUCCESS) {
829 C_LOGE("perm_to_smack failed");
833 if (smack_accesses_apply(smack) != 0) {
834 C_LOGE("smack_accesses_apply failed");
835 ret = PC_ERR_INVALID_OPERATION;
839 smack_accesses_free(smack);
841 free(src_label_file);
847 #endif // WRT_SMACK_ENABLED
849 API char* wrt_widget_id_from_socket(int sockfd)
851 C_LOGD("Enter function: %s", __func__);
856 ret = smack_new_label_from_socket(sockfd, &smack_label);
858 C_LOGE("smack_new_label_from_socket failed");
862 if (strncmp(smack_label, SMACK_WRT_LABEL_PREFIX,
863 strlen(SMACK_WRT_LABEL_PREFIX))) {
868 widget_id = strdup(smack_label + strlen(SMACK_WRT_LABEL_PREFIX));
870 C_LOGD("widget id: %s", widget_id);
875 static int load_smack_from_file(const char* app_id, struct smack_accesses** smack, int *fd)
877 C_LOGD("Enter function: %s", __func__);
882 if (asprintf(&path, SMACK_RULES_DIR "/%s", app_id) == -1) {
883 ret = PC_ERR_MEM_OPERATION;
884 C_LOGE("asprintf failed");
888 if (smack_accesses_new(smack)) {
889 ret = PC_ERR_MEM_OPERATION;
890 C_LOGE("smack_accesses_new failed");
894 *fd = open(path, O_CREAT|O_RDWR, 0644);
896 ret = PC_ERR_FILE_OPERATION;
897 C_LOGE("file open failed");
901 if (flock(*fd, LOCK_EX)) {
902 ret = PC_ERR_INVALID_OPERATION;
903 C_LOGE("flock failed");
907 if (smack_accesses_add_from_file(*smack, *fd)) {
908 ret = PC_ERR_INVALID_OPERATION;
909 C_LOGE("smack_accesses_add_from_file failed");
913 /* Rewind the file */
914 if (lseek(*fd, 0, SEEK_SET) == -1) {
915 ret = PC_ERR_FILE_OPERATION;
916 C_LOGE("lseek failed");
920 ret = PC_OPERATION_SUCCESS;
928 static int save_smack_to_file(struct smack_accesses *smack, int fd)
930 if (smack_accesses_apply(smack)) {
931 C_LOGE("smack_accesses_apply failed");
932 return PC_ERR_INVALID_OPERATION;
935 if (smack_accesses_save(smack, fd)) {
936 C_LOGE("smack_accesses_save failed");
937 return PC_ERR_INVALID_OPERATION;
940 return PC_OPERATION_SUCCESS;
944 API int app_add_permissions(const char* app_id, const char** perm_list)
946 C_LOGD("Enter function: %s", __func__);
950 struct smack_accesses *smack = NULL;
954 ret = load_smack_from_file(app_id, &smack, &fd);
955 if (ret != PC_OPERATION_SUCCESS) {
956 C_LOGE("load_smack_from_file failed");
959 for (i = 0; perm_list[i] != NULL; ++i) {
960 ret = perm_to_smack(smack, app_id, perm_list[i]);
961 C_LOGD("perm_to_smack params: app_id: %s, perm_list[%d]: %s", app_id, i, perm_list[i]);
962 if (ret != PC_OPERATION_SUCCESS){
963 C_LOGE("perm_to_smack failed");
968 ret = save_smack_to_file(smack, fd);
969 if(ret != PC_OPERATION_SUCCESS){
970 C_LOGE("save_smack_to_file failed");
975 ret = PC_OPERATION_SUCCESS;
980 smack_accesses_free(smack);
986 API int app_revoke_permissions(const char* app_id)
988 C_LOGD("Enter function: %s", __func__);
992 struct smack_accesses *smack = NULL;
995 if (asprintf(&path, SMACK_RULES_DIR "/%s", app_id) == -1) {
996 ret = PC_ERR_MEM_OPERATION;
997 C_LOGE("asprintf failed");
1001 if (smack_accesses_new(&smack)) {
1002 ret = PC_ERR_MEM_OPERATION;
1003 C_LOGE("smack_accesses_new failed");
1007 fd = open(path, O_RDONLY);
1009 ret = PC_ERR_FILE_OPERATION;
1010 C_LOGE("file open failed");
1014 if (flock(fd, LOCK_EX | LOCK_NB)) {
1015 /* Non-blocking lock request on a file failed. */
1016 ret = PC_ERR_INVALID_OPERATION;
1017 C_LOGE("flock failed");
1022 ret = PC_ERR_INVALID_OPERATION;
1023 C_LOGE("unlink failed");
1027 if (smack_accesses_add_from_file(smack, fd)) {
1028 ret = PC_ERR_INVALID_OPERATION;
1029 C_LOGE("smack_accesses_add_from_file failed");
1033 if (smack_accesses_clear(smack)) {
1034 ret = PC_ERR_INVALID_OPERATION;
1035 C_LOGE("smack_accesses_clear failed");
1039 if (smack_revoke_subject(app_id)) {
1040 ret = PC_ERR_INVALID_OPERATION;
1041 C_LOGE("smack_revoke_subject failed");
1046 ret = PC_OPERATION_SUCCESS;
1051 smack_accesses_free(smack);
1057 API int app_label_dir(const char* label, const char* path)
1059 C_LOGD("Enter function: %s", __func__);
1060 #ifdef SMACK_ENABLED
1062 int ret = PC_OPERATION_SUCCESS;
1064 //setting access label on everything in given directory and below
1065 ret = dir_set_smack_r(path, label, SMACK_LABEL_ACCESS, ~0);
1066 if (PC_OPERATION_SUCCESS != ret)
1069 //setting execute label for everything with permission to execute
1070 ret = dir_set_smack_r(path, label, SMACK_LABEL_EXEC, S_IXUSR);
1071 if (PC_OPERATION_SUCCESS != ret)
1074 //removing execute label from directories
1075 ret = dir_set_smack_r(path, "", SMACK_LABEL_EXEC, S_IFMT & ~S_IFREG);
1079 return PC_OPERATION_SUCCESS;
1083 API int app_label_shared_dir(const char* app_label, const char* shared_label, const char* path)
1085 C_LOGD("Enter function: %s", __func__);
1086 #ifdef SMACK_ENABLED
1089 struct smack_accesses *smack = NULL;
1092 //setting label on everything in given directory and below
1093 ret = dir_set_smack_r(path, shared_label, SMACK_LABEL_ACCESS, ~0);
1094 if(ret != PC_OPERATION_SUCCESS){
1095 C_LOGE("dir_set_smakc_r failed");
1099 //setting transmute on dir
1100 ret = dir_set_smack_r(path, "1", SMACK_LABEL_TRANSMUTE, S_IFDIR);
1101 if (ret != PC_OPERATION_SUCCESS) {
1102 C_LOGE("dir_set_smakc_r failed");
1106 ret = load_smack_from_file(app_label, &smack, &fd);
1107 if (ret != PC_OPERATION_SUCCESS) {
1108 C_LOGE("load_smack_from_file failed");
1112 //setting access rule for application
1113 if (smack_accesses_add(smack, app_label,shared_label, "wrxat") == -1) {
1114 C_LOGE("smack_accesses_add failed");
1118 ret = save_smack_to_file(smack, fd);
1119 if (ret != PC_OPERATION_SUCCESS) {
1120 C_LOGE("save_smack_to_file failed");
1124 ret = PC_OPERATION_SUCCESS;
1129 smack_accesses_free(smack);
1132 return PC_OPERATION_SUCCESS;