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 <linux/xattr.h>
41 #include <sys/capability.h>
46 #include "privilege-control.h"
47 #include "access-db.h"
53 #define DEVELOPER_GID 5100
54 #define DEVELOPER_UID 5100
56 #define APP_USER_NAME "app"
57 #define DEV_USER_NAME "developer"
59 #define APP_HOME_DIR TOSTRING(HOMEDIR) "/app"
60 #define DEV_HOME_DIR TOSTRING(HOMEDIR) "/developer"
62 /* Macro defined below is used to label links to executables */
63 #define XATTR_NAME_TIZENEXEC XATTR_SECURITY_PREFIX "TIZEN_EXEC_LABEL"
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"
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"
88 typedef int (*label_decision_fn)(const FTSENT*);
94 __attribute__ ((destructor))
95 static void libprivilege_destructor()
97 SECURE_C_LOGD("Entering function: %s.", __func__);
101 API int perm_begin(void)
103 SECURE_C_LOGD("Entering function: %s.", __func__);
104 return rdb_modification_start();
107 API int perm_end(void)
109 SECURE_C_LOGD("Entering function: %s.", __func__);
111 return rdb_modification_finish();
114 API int perm_rollback(void)
116 SECURE_C_LOGD("Entering function: %s.", __func__);
118 int ret = rdb_modification_rollback();
120 if (ret != PC_OPERATION_SUCCESS) {
121 C_LOGE("RDB %s failed with: %d", __func__, ret);
125 return PC_OPERATION_SUCCESS;
128 API int control_privilege(void)//deprecated
130 SECURE_C_LOGD("Entering function: %s.", __func__);
132 if(getuid() == APP_UID) // current user is 'app'
133 return PC_OPERATION_SUCCESS;
135 if(perm_app_set_privilege("org.tizen.", NULL, NULL) == PC_OPERATION_SUCCESS)
136 return PC_OPERATION_SUCCESS;
138 C_LOGE("perm_app_set_privilege failed (not permitted).");
139 return PC_ERR_NOT_PERMITTED;
143 static int get_user_groups(uid_t user_id, int *nbgroup, gid_t **groups_list)
145 gid_t *groups = NULL;
147 C_LOGD("Enter function: %s", __func__);
149 if ((!groups_list) || (!nbgroup))
150 return PC_ERR_INVALID_OPERATION;
151 pw = getpwuid(user_id);
153 C_LOGE("getgrouplist fails : Invalid User ID %d",user_id);
154 return PC_ERR_INVALID_OPERATION;
157 //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.
158 if (getgrouplist(pw->pw_name, pw->pw_gid, groups, nbgroup) != -1)
159 return PC_ERR_INVALID_OPERATION;
161 C_LOGD("getgrouplist %s user is member of %d groups ",pw->pw_name,*nbgroup);
162 groups = malloc(*nbgroup * sizeof (gid_t));
164 return PC_ERR_INVALID_OPERATION;
165 //Second call is done with the suitable ngroup value and structure groups allocated.
166 if (getgrouplist(pw->pw_name, pw->pw_gid, groups, nbgroup) == -1) {
168 C_LOGE("getgrouplist fails %d",nbgroup);
169 return PC_ERR_INVALID_OPERATION;
171 *groups_list = groups;
172 return PC_OPERATION_SUCCESS;
175 static int set_dac(const char *smack_label, const char *pkg_name)
177 SECURE_C_LOGD("Entering function: %s. Params: smack_label=%s, pkg_name=%s",
178 __func__, smack_label, pkg_name);
180 uid_t t_uid = -1; // uid of current process
181 gid_t *glist = NULL; // group list
182 int glist_cnt = 0; // for group list
186 unsigned *additional_gids = NULL;
189 * initialize user structure
191 C_LOGD("Initialize user structure");
192 memset(usr.user_name, 0x00, 10);
193 memset(usr.home_dir, 0x00, 64);
198 C_LOGD("Current uid is %d", t_uid);
200 if(t_uid == 0) // current user is 'root'
202 if(!strncmp(pkg_name, "developer", 9))
204 strncpy(usr.user_name, DEV_USER_NAME, sizeof(usr.user_name));
205 usr.uid = DEVELOPER_UID;
206 usr.gid = DEVELOPER_GID;
207 strncpy(usr.home_dir, DEV_HOME_DIR, sizeof(usr.home_dir));
211 strncpy(usr.user_name, APP_USER_NAME, sizeof(usr.user_name));
214 strncpy(usr.home_dir, APP_HOME_DIR, sizeof(usr.home_dir));
218 * get group information
220 C_LOGD("get group information");
221 if (get_user_groups(usr.uid, &glist_cnt, &glist)) {
222 result = PC_ERR_FILE_OPERATION; // return -1
229 result = get_app_gids(smack_label, &additional_gids, &cnt);
230 if (result != PC_OPERATION_SUCCESS)
234 glist_new = (gid_t*)realloc(glist, sizeof(gid_t) * (glist_cnt + cnt));
235 if (glist_new == NULL) {
236 result = PC_ERR_MEM_OPERATION; // return -2
237 C_LOGE("Memory allocation failed");
241 for (i = 0; i < cnt; ++i) {
242 C_LOGD("Additional GID based on enabled permissions: %u", additional_gids[i]);
243 glist[glist_cnt++] = additional_gids[i];
251 C_LOGD("Adding process to the following groups:");
252 for(i=0; i<glist_cnt; ++i) {
253 SECURE_C_LOGD("glist [ %d ] = %d", i, glist[i]);
255 C_LOGD("Calling setgroups()");
256 if(setgroups(glist_cnt, glist) != 0)
258 C_LOGE("setgroups failed");
259 result = PC_ERR_NOT_PERMITTED; // return -3
269 * setuid() & setgid()
271 C_LOGD("setgid( %d ) & setuid( %d )", usr.gid, usr.uid);
272 if(setgid(usr.gid) != 0) // fail
274 C_LOGE("Failed to execute setgid().");
275 result = PC_ERR_INVALID_OPERATION;
278 if(setuid(usr.uid) != 0) // fail
280 C_LOGE("Failed to execute setuid().");
281 result = PC_ERR_INVALID_OPERATION;
285 SECURE_C_LOGD("setenv(): USER = %s, HOME = %s", usr.user_name, usr.home_dir);
286 if(setenv("USER", usr.user_name, 1) != 0) //fail
288 C_LOGE("Failed to execute setenv() [USER].");
289 result = PC_ERR_INVALID_OPERATION;
292 if(setenv("HOME", usr.home_dir, 1) != 0) // fail
294 C_LOGE("Failed to execute setenv() [HOME].");
295 result = PC_ERR_INVALID_OPERATION;
299 else // current user is not only 'root' but 'app'
301 C_LOGE("Current user is NOT root");
302 result = PC_ERR_NOT_PERMITTED; // return -3
306 result = PC_OPERATION_SUCCESS;
311 free(additional_gids);
317 * Get SMACK label from EXEC label of a file.
318 * SMACK label should be freed by caller
320 * @param path file path to take label from
321 * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
323 static int get_smack_from_binary(char **smack_label, const char* path)
325 SECURE_C_LOGD("Entering function: %s. Params: path=%s", __func__, path);
326 char value[SMACK_LABEL_LEN + 1];
329 /* First try: check SMACKEXEC label on binary */
330 ret = getxattr(path, XATTR_NAME_SMACKEXEC, value, SMACK_LABEL_LEN + 1);
333 if (errno != ENODATA)
336 /* Second try: check TIZENEXEC label on binary */
337 ret = getxattr(path, XATTR_NAME_TIZENEXEC, value, SMACK_LABEL_LEN + 1);
340 if (errno != ENODATA)
343 /* Third try: check TIZENEXEC label on symbolic link */
344 ret = lgetxattr(path, XATTR_NAME_TIZENEXEC, value, SMACK_LABEL_LEN + 1);
347 if (errno != ENODATA)
350 /* None of labels found return NULL*/
352 return PC_OPERATION_SUCCESS;
356 value[ret] = '\0'; /* because getxattr does not add 0 at the end! */
357 *smack_label = strdup(value);
358 if (*smack_label == NULL) {
359 C_LOGE("Cannot allocate memory for smack_label");
360 return PC_ERR_MEM_OPERATION;
362 return PC_OPERATION_SUCCESS;
365 C_LOGE("Getting exec label from file %s failed", path);
366 return PC_ERR_INVALID_OPERATION;
370 * Set process SMACK label.
371 * This function is emulating EXEC label behavior of SMACK for programs
372 * run by dlopen/dlsym instead of execv.
375 * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
377 static int set_smack_for_self (char *smack_label)
379 SECURE_C_LOGD("Entering function: %s. Params: smack_label=%s",
380 __func__, smack_label);
383 if (smack_label == NULL) {
384 /* No label to set, just return with success */
385 C_LOGD("No label to set, just return with success.");
386 ret = PC_OPERATION_SUCCESS;
389 SECURE_C_LOGD("smack_label=%s", smack_label);
391 ret = smack_set_label_for_self(smack_label);
392 C_LOGD("smack_set_label_for_self returned %d", ret);
394 ret = PC_OPERATION_SUCCESS;
400 API int set_app_privilege(const char* name, const char* type, const char* path)//deprecated
402 SECURE_C_LOGD("Entering function: %s. Params: name=%s, type=%s, path=%s",
403 __func__, name, type, path);
405 return perm_app_set_privilege(name, type, path);
408 API int perm_app_set_privilege(const char* name, const char* type UNUSED, const char* path)
410 SECURE_C_LOGD("Entering function: %s. Params: name=%s, type=%s, path=%s",
411 __func__, name, type, path);
413 //SECURE_C_LOGD("Function params: name = %s, type = %s, path = %s", name, type, path);
414 int ret = PC_OPERATION_SUCCESS;
415 char *smack_label AUTO_FREE;
418 C_LOGE("Error invalid parameter");
419 return PC_ERR_INVALID_PARAM;
422 if (path != NULL && have_smack()) {
423 ret = get_smack_from_binary(&smack_label, path);
424 if (ret != PC_OPERATION_SUCCESS)
427 ret = set_smack_for_self(smack_label);
428 if (ret != PC_OPERATION_SUCCESS)
432 if (path != NULL && !have_smack()) {
433 ret = get_smack_from_binary(&smack_label, path);
434 if (ret != PC_OPERATION_SUCCESS)
438 return set_dac(smack_label, name);
441 API int set_privilege(const char* pkg_name)//deprecated
443 SECURE_C_LOGD("Entering function: %s. Params: pkg_name=%s",
446 return perm_app_set_privilege(pkg_name, NULL, NULL);
449 static int perm_file_path(char** path, app_type_t app_type, const char* perm, const char *suffix, bool is_early)
451 SECURE_C_LOGD("Entering function: %s. Params: app_type=%d, perm=%s, suffix=%s, is_early=%d",
452 __func__, app_type, perm, suffix, is_early);
454 const char* app_type_prefix = NULL;
455 char* perm_basename = NULL;
458 if (perm == NULL || strlen(perm) == 0) {
459 C_LOGE("Empty permission name.");
460 return PC_ERR_INVALID_PARAM;
463 app_type_prefix = app_type_group_name(app_type);
465 ret = base_name_from_perm(perm, &perm_basename);
466 if (ret != PC_OPERATION_SUCCESS) {
467 C_LOGE("Couldn't get permission basename.");
472 ret = asprintf(path, TOSTRING(SHAREDIR) "/%s%s%s%s%s",
473 app_type_prefix ? app_type_prefix : "", app_type_prefix ? "_" : "",
474 perm_basename, "_early", suffix);
477 ret = asprintf(path, TOSTRING(SHAREDIR) "/%s%s%s%s",
478 app_type_prefix ? app_type_prefix : "", app_type_prefix ? "_" : "",
479 perm_basename, suffix);
482 C_LOGE("asprintf failed.");
483 return PC_ERR_MEM_OPERATION;
486 C_LOGD("Path=%s", *path);
488 return PC_OPERATION_SUCCESS;
491 static int perm_to_dac(const char* app_label, app_type_t app_type, const char* perm)
493 SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, app_type=%d, perm=%s",
494 __func__, app_label, app_type, perm);
497 char* path AUTO_FREE;
498 FILE* file AUTO_FCLOSE;
501 ret = perm_file_path(&path, app_type, perm, ".dac", 0);
502 if (ret != PC_OPERATION_SUCCESS) {
503 C_LOGD("No dac config file for permission %s", perm);
507 SECURE_C_LOGD("Opening file %s.", path);
508 file = fopen(path, "r");
510 C_LOGW("fopen failed.");
511 return PC_OPERATION_SUCCESS;
514 while (fscanf(file, "%d\n", &gid) == 1) {
515 SECURE_C_LOGD("Adding app_id %s to group %d", app_label, gid);
516 ret = add_app_gid(app_label, gid);
517 if (ret != PC_OPERATION_SUCCESS) {
518 C_LOGE("add_app_gid failed");
523 return PC_OPERATION_SUCCESS;
526 static int label_all(const FTSENT* ftsent UNUSED)
528 SECURE_C_LOGD("Entering function: %s.", __func__);
530 return DECISION_LABEL;
533 static int label_execs(const FTSENT* ftsent)
535 SECURE_C_LOGD("Entering function: %s.", __func__);
537 C_LOGD("Mode = %d", ftsent->fts_statp->st_mode);
538 // label only regular executable files
539 if (S_ISREG(ftsent->fts_statp->st_mode) && (ftsent->fts_statp->st_mode & S_IXUSR))
540 return DECISION_LABEL;
541 return DECISION_SKIP;
544 static int label_dirs(const FTSENT* ftsent)
546 SECURE_C_LOGD("Entering function: %s.", __func__);
548 // label only directories
549 if (S_ISDIR(ftsent->fts_statp->st_mode))
550 return DECISION_LABEL;
551 return DECISION_SKIP;
554 static int label_links_to_execs(const FTSENT* ftsent)
556 SECURE_C_LOGD("Entering function: %s.", __func__);
559 char* target AUTO_FREE;
561 // check if it's a link
562 if ( !S_ISLNK(ftsent->fts_statp->st_mode))
563 return DECISION_SKIP;
565 target = realpath(ftsent->fts_path, NULL);
567 SECURE_C_LOGE("Getting link target for %s failed (Error = %s)", ftsent->fts_path, strerror(errno));
568 return PC_ERR_FILE_OPERATION;
570 if (-1 == stat(target, &buf)) {
571 SECURE_C_LOGE("stat failed for %s (Error = %s", target, strerror(errno));
572 return PC_ERR_FILE_OPERATION;
574 // skip if link target is not a regular executable file
575 if (buf.st_mode != (buf.st_mode | S_IXUSR | S_IFREG)) {
576 SECURE_C_LOGD("%s is not a regular executable file. Skipping.", target);
577 return DECISION_SKIP;
580 return DECISION_LABEL;
583 static int dir_set_smack_r(const char *path, const char* label,
584 const char *xattr_name, label_decision_fn fn)
586 SECURE_C_LOGD("Entering function: %s. Params: path=%s, label=%s, xattr_name=%s",
587 __func__, path, label, xattr_name);
589 const char* path_argv[] = {path, NULL};
590 FTS *fts AUTO_FTS_CLOSE;
594 int len = strnlen(label, SMACK_LABEL_LEN + 1);
595 if (len > SMACK_LABEL_LEN) {
596 C_LOGE("parameter \"label\" is to long.");
597 return PC_ERR_INVALID_PARAM;
600 fts = fts_open((char * const *) path_argv, FTS_PHYSICAL | FTS_NOCHDIR, NULL);
602 C_LOGE("fts_open failed.");
603 return PC_ERR_FILE_OPERATION;
606 while ((ftsent = fts_read(fts)) != NULL) {
607 /* Check for error (FTS_ERR) or failed stat(2) (FTS_NS) */
608 if (ftsent->fts_info == FTS_ERR || ftsent->fts_info == FTS_NS) {
609 C_LOGE("FTS_ERR error or failed stat(2) (FTS_NS)");
610 return PC_ERR_FILE_OPERATION;
615 C_LOGE("fn(ftsent) failed.");
619 if (ret == DECISION_LABEL) {
620 C_LOGD("lsetxattr (path: %s, xattr_name: %s, label: %s len: %d, 0",
621 ftsent->fts_path, xattr_name, label, len);
623 if (lsetxattr(ftsent->fts_path, xattr_name, label, len, 0) != 0) {
624 C_LOGE("lsetxattr failed.");
625 return PC_ERR_FILE_OPERATION;
630 /* If last call to fts_read() set errno, we need to return error. */
632 C_LOGE("Last errno from fts_read: %s", strerror(errno));
633 return PC_ERR_FILE_OPERATION;
635 return PC_OPERATION_SUCCESS;
637 API char* app_id_from_socket(int sockfd)//deprecated
639 SECURE_C_LOGD("Entering function: %s. Params: sockfd=%d",
642 return perm_app_id_from_socket(sockfd);
645 API char* perm_app_id_from_socket(int sockfd)
647 SECURE_C_LOGD("Entering function: %s. Params: sockfd=%d",
651 C_LOGD("No SMACK. Returning NULL.");
658 ret = smack_new_label_from_socket(sockfd, &app_id);
660 C_LOGE("smack_new_label_from_socket failed");
664 SECURE_C_LOGD("app_id = %s", app_id);
670 API int app_add_permissions(const char* app_id, const char** perm_list)//deprecated
672 SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
675 return perm_app_enable_permissions(app_id, APP_TYPE_OTHER, perm_list, true);
678 API int app_add_volatile_permissions(const char* app_id, const char** perm_list)//deprecated
680 SECURE_C_LOGD("Entering function: %s. Params: app_id=%s",
683 return perm_app_enable_permissions(app_id, APP_TYPE_OTHER, perm_list, false);
686 API int app_enable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list, bool persistent)//deprecated
688 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d, persistent=%d",
689 __func__, pkg_id, app_type, persistent);
691 return perm_app_enable_permissions(pkg_id, app_type, perm_list, persistent);
694 API int perm_app_enable_permissions(const char* pkg_id, app_type_t app_type,
695 const char** perm_list, bool persistent)
697 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d, persistent=%d",
698 __func__, pkg_id, app_type, persistent);
701 const char *app_label AUTO_FREE;
703 if (!smack_label_is_valid(pkg_id)) {
704 C_LOGE("Invalid param app_id.");
705 return PC_ERR_INVALID_PARAM;
708 if (perm_list == NULL) {
709 C_LOGE("Invalid perm_list (NULL).");
710 return PC_ERR_INVALID_PARAM;
713 if (app_type_group_name(app_type) == NULL) {
714 C_LOGE("Unknown app type.");
715 return PC_ERR_INVALID_PARAM;
718 app_label = generate_app_label(pkg_id);
719 if (app_label == NULL) {
720 C_LOGE("generate_app_label returned NULL.");
721 return PC_ERR_MEM_OPERATION;
724 /* Add permission to DAC */
725 for (i = 0; perm_list[i] != NULL; ++i) {
726 ret = perm_to_dac(pkg_id, app_type, perm_list[i]);
727 if (ret != PC_OPERATION_SUCCESS) {
728 C_LOGE("perm_to_dac failed");
733 /* Enable the permissions: */
734 ret = rdb_enable_app_permissions(app_label, app_type, perm_list,
735 !((bool)persistent));
736 if (ret != PC_OPERATION_SUCCESS) {
737 C_LOGE("RDB rdb_enable_app_permissions failed with: %d", ret);
741 return PC_OPERATION_SUCCESS;
744 API int app_disable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list)//deprecated
746 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d",
747 __func__, pkg_id, app_type);
749 return perm_app_disable_permissions(pkg_id, app_type, perm_list);
752 API int perm_app_disable_permissions(const char* pkg_id, app_type_t app_type, const char** perm_list)
754 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, app_type=%d",
755 __func__, pkg_id, app_type);
758 const char *app_label AUTO_FREE;
759 if (!smack_label_is_valid(pkg_id)) {
760 C_LOGE("Invalid param app_id.");
761 return PC_ERR_INVALID_PARAM;
764 if (perm_list == NULL) {
765 C_LOGE("Invalid perm_list (NULL).");
766 return PC_ERR_INVALID_PARAM;
769 if (app_type_group_name(app_type) == NULL) {
770 C_LOGE("Unknown app type.");
771 return PC_ERR_INVALID_PARAM;
774 app_label = generate_app_label(pkg_id);
775 if (app_label == NULL) {
776 C_LOGE("generate_app_label returned NULL.");
777 return PC_ERR_MEM_OPERATION;
780 ret = rdb_disable_app_permissions(app_label, app_type, perm_list);
781 if (ret != PC_OPERATION_SUCCESS) {
782 C_LOGE("RDB rdb_disable_app_permissions failed with: %d", ret);
786 return PC_OPERATION_SUCCESS;
789 API int app_revoke_permissions(const char* pkg_id)//deprecated
791 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
792 return perm_app_revoke_permissions(pkg_id);
795 API int perm_app_revoke_permissions(const char* pkg_id)
797 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
798 /* TODO Please uncomment this when db is prepared for single "User" label for all apps */
800 const char *app_label AUTO_FREE;*/
802 if (!smack_label_is_valid(pkg_id)) {
803 C_LOGE("Invalid param app_id.");
804 return PC_ERR_INVALID_PARAM;
807 SECURE_C_LOGD("This function is currently only a stub. Returning PC_OPERATION_SUCCESS.");
808 /* TODO Please uncomment this when db is prepared for single "User" label for all apps */
809 /*app_label = generate_app_label(pkg_id);
810 if (app_label == NULL) {
811 C_LOGE("generate_app_label returned NULL.");
812 return PC_ERR_MEM_OPERATION;
815 ret = rdb_revoke_app_permissions(app_label);
816 if (ret != PC_OPERATION_SUCCESS) {
817 C_LOGE("RDB rdb_disable_app_permissions failed with: %d", ret);
821 return PC_OPERATION_SUCCESS;
824 API int app_reset_permissions(const char* pkg_id)//deprecated
826 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
829 return perm_app_reset_permissions(pkg_id);
832 API int perm_app_reset_permissions(const char* pkg_id)
834 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
837 const char *app_label AUTO_FREE;
839 if (!smack_label_is_valid(pkg_id)) {
840 C_LOGE("Invalid param pkg_id.");
841 return PC_ERR_INVALID_PARAM;
844 app_label = generate_app_label(pkg_id);
845 if (app_label == NULL) {
846 C_LOGE("generate_app_label returned NULL.");
847 return PC_ERR_MEM_OPERATION;
850 ret = rdb_reset_app_permissions(app_label);
851 if (ret != PC_OPERATION_SUCCESS) {
852 C_LOGE("RDB rdb_disable_app_permissions failed with: %d", ret);
856 return PC_OPERATION_SUCCESS;
859 API int app_label_dir(const char* label, const char* path)//deprecated
861 SECURE_C_LOGD("Entering function: %s. Params: label=%s, path=%s",
862 __func__, label, path);
864 int ret = PC_OPERATION_SUCCESS;
867 C_LOGE("Invalid argument path (NULL).");
868 return PC_ERR_INVALID_PARAM;
871 if (!smack_label_is_valid(label)) {
872 C_LOGE("Invalid param label.");
873 return PC_ERR_INVALID_PARAM;
876 //setting access label on everything in given directory and below
877 ret = dir_set_smack_r(path, label, XATTR_NAME_SMACK, &label_all);
878 if (PC_OPERATION_SUCCESS != ret)
880 C_LOGE("dir_set_smack_r failed.");
884 //setting execute label for everything with permission to execute
885 ret = dir_set_smack_r(path, label, XATTR_NAME_SMACKEXEC, &label_execs);
886 if (PC_OPERATION_SUCCESS != ret)
888 C_LOGE("dir_set_smack_r failed.");
892 //setting execute label for everything with permission to execute
893 ret = dir_set_smack_r(path, label, XATTR_NAME_TIZENEXEC, &label_links_to_execs);
897 API int app_label_shared_dir(const char* app_label, const char* shared_label, const char* path)//deprecated
899 SECURE_C_LOGD("Entering function: %s. Params: app_label=%s, shared_label=%s, path=%s",
900 __func__, app_label, shared_label, path);
904 C_LOGE("Invalid param path.");
905 return PC_ERR_INVALID_PARAM;
908 if(!smack_label_is_valid(app_label)) {
909 C_LOGE("Invalid param app_label");
910 return PC_ERR_INVALID_PARAM;
913 if(!smack_label_is_valid(shared_label)) {
914 C_LOGE("Invalid param shared_label");
915 return PC_ERR_INVALID_PARAM;
918 if (strcmp(app_label, shared_label) == 0) {
919 C_LOGE("app_label equals shared_label");
920 return PC_ERR_INVALID_PARAM;
923 //setting label on everything in given directory and below
924 ret = dir_set_smack_r(path, shared_label, XATTR_NAME_SMACK, label_all);
925 if(ret != PC_OPERATION_SUCCESS){
926 C_LOGE("dir_set_smack_r failed.");
930 //setting transmute on dir
931 ret = dir_set_smack_r(path, "TRUE", XATTR_NAME_SMACKTRANSMUTE, label_dirs);
932 if (ret != PC_OPERATION_SUCCESS) {
933 C_LOGE("dir_set_smack_r failed");
937 return PC_OPERATION_SUCCESS;
940 API int add_shared_dir_readers(const char* shared_label UNUSED, const char** app_list UNUSED)//deprecated
942 SECURE_C_LOGD("Entering function: %s. Params: shared_label=%s",
943 __func__, shared_label);
945 C_LOGE("add_shared_dir_readers is deprecated and unimplemented!");
947 // TODO: This function is not implemented with RDB.
948 return PC_ERR_INVALID_OPERATION;
951 static char* smack_label_for_path(const char *app_id, const char *path)
953 SECURE_C_LOGD("Entering function: %s. Params: app_id=%s, path=%s",
954 __func__, app_id, path);
956 char *salt AUTO_FREE;
960 /* Prefix $1$ causes crypt() to use MD5 function */
961 if (-1 == asprintf(&salt, "$1$%s", app_id)) {
962 C_LOGE("asprintf failed");
966 label = crypt(path, salt);
968 C_LOGE("crypt failed");
972 /* crypt() output may contain slash character,
973 * which is not legal in Smack labels */
974 for (x = label; *x; ++x) {
982 /* FIXME: remove this pragma once deprecated API is deleted */
983 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
984 static int perm_app_setup_path_internal(const char* pkg_id, const char* path, app_path_type_t app_path_type, va_list ap)
986 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, path=%s, app_path_type=%d",
987 __func__, pkg_id, path, app_path_type);
988 const char *app_label AUTO_FREE;
991 C_LOGE("Invalid argument path.");
992 return PC_ERR_INVALID_PARAM;
995 if (!smack_label_is_valid(pkg_id)) {
996 C_LOGE("Invalid pkg_id.");
997 SECURE_C_LOGE("Invalid pkg_id %s", pkg_id);
998 return PC_ERR_INVALID_PARAM;
1001 app_label = generate_app_label(pkg_id);
1002 if (app_label == NULL) {
1003 C_LOGE("generate_app_label returned NULL.");
1004 return PC_ERR_MEM_OPERATION;
1007 switch (app_path_type) {
1008 case APP_PATH_PRIVATE:
1009 C_LOGD("app_path_type is APP_PATH_PRIVATE.");
1010 return app_label_dir(app_label, path);
1012 case APP_PATH_GROUP_RW: {
1013 C_LOGD("app_path_type is APP_PATH_GROUP.");
1015 const char *shared_label;
1017 shared_label = va_arg(ap, const char *);
1019 if (!smack_label_is_valid(shared_label)) {
1020 C_LOGE("Invalid shared_label.");
1021 return PC_ERR_INVALID_PARAM;
1024 if (strcmp(app_label, shared_label) == 0) {
1025 C_LOGE("app_label equals shared_label.");
1026 return PC_ERR_INVALID_PARAM;
1029 ret = app_label_shared_dir(app_label, shared_label, path);
1030 if (ret != PC_OPERATION_SUCCESS) {
1031 C_LOGE("app_label_shared_dir failed: %d", ret);
1035 // Add the path to the database:
1036 ret = rdb_add_path(app_label, shared_label, path, "rwxatl", "-", "GROUP_PATH");
1037 if (ret != PC_OPERATION_SUCCESS) {
1038 C_LOGE("RDB rdb_add_path failed with: %d", ret);
1042 return PC_OPERATION_SUCCESS;
1045 case APP_PATH_PUBLIC_RO: {
1046 C_LOGD("app_path_type is APP_PATH_PUBLIC.");
1050 C_LOGD("New public RO path %s", path);
1053 label = smack_label_for_path(app_label, path);
1054 if (label == NULL) {
1055 C_LOGE("smack_label_for_path failed.");
1056 return PC_ERR_INVALID_OPERATION;
1058 C_LOGD("Generated label '%s' for public RO path %s", label, path);
1060 ret = app_label_shared_dir(app_label, label, path);
1061 if (ret != PC_OPERATION_SUCCESS) {
1062 C_LOGE("app_label_shared_dir failed.");
1066 // Add the path to the database:
1067 ret = rdb_add_path(app_label, label, path, "rwxatl", "-", "PUBLIC_PATH");
1068 if (ret != PC_OPERATION_SUCCESS) {
1069 C_LOGE("RDB rdb_add_path failed with: %d", ret);
1073 return PC_OPERATION_SUCCESS;
1076 case APP_PATH_SETTINGS_RW: {
1077 C_LOGD("app_path_type is APP_PATH_SETTINGS.");
1082 label = smack_label_for_path(app_label, path);
1083 if (label == NULL) {
1084 C_LOGE("smack_label_for_path failed.");
1085 return PC_ERR_INVALID_OPERATION;
1087 C_LOGD("Appsetting: generated label '%s' for setting path %s", label, path);
1089 /*set id for path and all subfolders*/
1090 ret = app_label_shared_dir(app_label, label, path);
1091 if (ret != PC_OPERATION_SUCCESS) {
1092 C_LOGE("Appsetting: app_label_shared_dir failed (%d)", ret);
1096 // Add the path to the database:
1097 ret = rdb_add_path(app_label, label, path, "rwxatl", "-", "SETTINGS_PATH");
1098 if (ret != PC_OPERATION_SUCCESS) {
1099 C_LOGE("RDB rdb_add_path failed with: %d", ret);
1103 return PC_OPERATION_SUCCESS;
1106 case APP_PATH_ANY_LABEL: {
1107 C_LOGD("app_path_type is APP_PATH_ANY_LABEL.");
1108 const char *label = NULL;
1109 label = va_arg(ap, const char *);
1110 return app_label_dir(label, path);
1114 C_LOGE("app_path_type is invalid.");
1115 return PC_ERR_INVALID_PARAM;
1118 return PC_OPERATION_SUCCESS;
1120 /* FIXME: remove this pragma once deprecated API is deleted */
1121 #pragma GCC diagnostic warning "-Wdeprecated-declarations"
1123 API int app_setup_path(const char* pkg_id, const char* path, app_path_type_t app_path_type, ...)//deprecated
1125 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, path=%s, app_path_type=%d",
1126 __func__, pkg_id, path, app_path_type);
1130 va_start( ap, app_path_type );
1131 ret = perm_app_setup_path_internal( pkg_id, path, app_path_type, ap );
1136 API int perm_app_setup_path(const char* pkg_id, const char* path, app_path_type_t app_path_type, ...)
1138 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s, path=%s, app_path_type=%d",
1139 __func__, pkg_id, path, app_path_type);
1143 va_start( ap, app_path_type );
1144 ret = perm_app_setup_path_internal( pkg_id, path, app_path_type, ap );
1149 API int app_add_friend(const char* pkg_id1, const char* pkg_id2)//deprecated
1151 SECURE_C_LOGD("Entering function: %s. Params: pkg_id1=%s, pkg_id2=%s",
1152 __func__, pkg_id1, pkg_id2);
1154 return perm_app_add_friend(pkg_id1, pkg_id2);
1157 API int perm_app_add_friend(const char* pkg_id1 UNUSED, const char* pkg_id2 UNUSED)
1159 SECURE_C_LOGD("Entering function: %s. Params: pkg_id1=%s, pkg_id2=%s",
1160 __func__, pkg_id1, pkg_id2);
1162 C_LOGE("app_register_av is deprecated and unimplemented!");
1164 // TODO: This function is not implemented with RDB.
1165 return PC_ERR_INVALID_OPERATION;
1168 API int app_install(const char* pkg_id)//deprecated
1170 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
1173 return perm_app_install(pkg_id);
1176 API int perm_app_install(const char* pkg_id)
1178 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
1181 const char *app_label AUTO_FREE;
1183 if (!smack_label_is_valid(pkg_id)) {
1184 C_LOGE("Invalid param pkg_id.");
1185 return PC_ERR_INVALID_PARAM;
1188 app_label = generate_app_label(pkg_id);
1189 if (app_label == NULL) {
1190 C_LOGE("generate_app_label returned NULL.");
1191 return PC_ERR_MEM_OPERATION;
1194 // Add application to the database:
1195 ret = rdb_add_application(app_label);
1196 if (ret != PC_OPERATION_SUCCESS) {
1197 C_LOGE("RDB rdb_add_application failed with: %d", ret);
1201 return PC_OPERATION_SUCCESS;
1204 API int app_uninstall(const char* pkg_id)//deprecated
1206 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s",
1209 return perm_app_uninstall(pkg_id);
1212 API int perm_app_uninstall(const char* pkg_id)
1214 SECURE_C_LOGD("Entering function: %s. Params: pkg_id=%s", __func__, pkg_id);
1215 /* TODO Please uncomment this when db is prepared for single "User" label for all apps */
1217 const char *app_label AUTO_FREE;*/
1219 if (!smack_label_is_valid(pkg_id)) {
1220 C_LOGE("Invalid param pkg_id.");
1221 return PC_ERR_INVALID_PARAM;
1224 SECURE_C_LOGD("This function is currently only a stub. Returning PC_OPERATION_SUCCESS.");
1225 /* TODO Please uncomment this when db is prepared for single "User" label for all apps */
1226 /*app_label = generate_app_label(pkg_id);
1227 if (app_label == NULL) {
1228 C_LOGE("generate_app_label returned NULL.");
1229 return PC_ERR_MEM_OPERATION;
1232 // Remove application from the database
1233 ret = rdb_remove_application(app_label);
1234 if (ret != PC_OPERATION_SUCCESS) {
1235 C_LOGE("RDB rdb_remove_application failed with: %d", ret);
1239 return PC_OPERATION_SUCCESS;
1242 static int save_gids(FILE* file, const gid_t* list_of_db_gids, size_t list_size) {
1244 SECURE_C_LOGD("Entering function: %s.", __func__);
1245 int ret = PC_OPERATION_SUCCESS;
1250 C_LOGE("Unable to create file. Error: %s", strerror(errno));
1251 return PC_ERR_FILE_OPERATION; // TODO remove smack accesses?
1254 if(-1 == fchmod(fileno(file), 0644)) {
1255 C_LOGE("Unable to chmod file. Error: %s", strerror(errno));
1256 return PC_ERR_FILE_OPERATION;
1259 for (i = 0; i < list_size ; ++i) {
1260 written = fprintf(file, "%u\n", list_of_db_gids[i]);
1262 C_LOGE("fprintf failed for file. Error: %s", strerror(errno));
1263 ret = PC_ERR_FILE_OPERATION;
1270 API int add_api_feature(app_type_t app_type,
1271 const char* api_feature_name,
1272 const char** smack_rules,
1273 const gid_t* list_of_db_gids,
1274 size_t list_size)//deprecated
1276 SECURE_C_LOGD("Entering function: %s. Params: app_type=%d, api_feature_name=%s",
1277 __func__, app_type, api_feature_name);
1279 return perm_add_api_feature(app_type, api_feature_name, smack_rules, list_of_db_gids, list_size);
1282 API int perm_add_api_feature(app_type_t app_type,
1283 const char* api_feature_name,
1284 const char** smack_rules,
1285 const gid_t* list_of_db_gids,
1287 SECURE_C_LOGD("Entering function: %s. Params: app_type=%d, api_feature_name=%s",
1288 __func__, app_type, api_feature_name);
1290 int ret = PC_OPERATION_SUCCESS;
1291 char* dac_file AUTO_FREE;
1292 char * base_api_feature_name AUTO_FREE;
1294 // struct smack_accesses* accesses = NULL;
1295 const char *s_type_name = app_type_name(app_type);
1297 // Check input values
1298 if (s_type_name == NULL || !strcmp(s_type_name, "")) {
1299 C_LOGE("Unknown api type");
1300 return PC_ERR_INVALID_PARAM;
1303 if (api_feature_name == NULL || strlen(api_feature_name) == 0) {
1304 C_LOGE("Api feature name is empty.");
1305 return PC_ERR_INVALID_PARAM;
1308 if (smack_rules && ((ret = validate_all_rules(smack_rules) ) != PC_OPERATION_SUCCESS) ) {
1309 C_LOGE("Error in rules list.");
1313 // check .dac existence only if gids are supported
1314 if (list_of_db_gids && list_size > 0) {
1315 // get feature DAC file name
1316 ret = perm_file_path(&dac_file, app_type, api_feature_name, ".dac", 0);
1317 if (ret != PC_OPERATION_SUCCESS || !dac_file ) {
1318 C_LOGE("perm_file_path failed.");
1325 // go through gid list
1326 if (ret == PC_OPERATION_SUCCESS && list_of_db_gids && list_size > 0) {
1328 SECURE_C_LOGD("Opening file %s.", dac_file);
1329 file = fopen(dac_file, "w+");
1330 ret = save_gids(file, list_of_db_gids, list_size);
1331 if(file) fclose(file);
1334 // remove file in case of failure
1335 if (ret != PC_OPERATION_SUCCESS && dac_file) {
1339 ret = base_name_from_perm(api_feature_name, &base_api_feature_name);
1340 if (ret != PC_OPERATION_SUCCESS){
1341 C_LOGE("Error during creating base name: ", ret);
1345 // Save api feature to the database.
1346 ret = rdb_add_permission_rules(base_api_feature_name, s_type_name, smack_rules);
1347 if (ret != PC_OPERATION_SUCCESS) {
1348 C_LOGE("RDB rdb_add_permission_rules failed with: %d", ret);
1356 * This function is marked as deprecated and will be removed
1358 API int app_register_av(const char* app_av_id UNUSED)//deprecated
1360 SECURE_C_LOGD("Entering function: %s. Params: app_av_id=%s",
1361 __func__, app_av_id);
1363 C_LOGE("app_register_av is deprecated and unimplemented!");
1365 // TODO: This function is not implemented with RDB.
1366 return PC_ERR_INVALID_OPERATION;
1369 API const char* perm_strerror(int errnum)
1372 case PC_OPERATION_SUCCESS:
1374 case PC_ERR_FILE_OPERATION:
1375 return "File operation error";
1376 case PC_ERR_MEM_OPERATION:
1377 return "Memory operation error";
1378 case PC_ERR_NOT_PERMITTED:
1379 return "Operation not permitted";
1380 case PC_ERR_INVALID_PARAM:
1381 return "Invalid parameter";
1382 case PC_ERR_INVALID_OPERATION:
1383 return "Invalid operation";
1384 case PC_ERR_DB_OPERATION:
1385 return "Database operation error";
1386 case PC_ERR_DB_LABEL_TAKEN:
1387 return "Label taken by another application";
1388 case PC_ERR_DB_QUERY_PREP:
1389 return "Query failure during preparation";
1390 case PC_ERR_DB_QUERY_BIND:
1391 return "Query failure during binding";
1392 case PC_ERR_DB_QUERY_STEP:
1393 return "Query failure during stepping";
1394 case PC_ERR_DB_CONNECTION:
1395 return "Cannot establish a connection";
1396 case PC_ERR_DB_NO_SUCH_APP:
1397 return "No such application";
1398 case PC_ERR_DB_PERM_FORBIDDEN:
1399 return "Duplicate permission";
1401 return "Unknown error";
1405 int app_give_access(const char* subject UNUSED, const char* object UNUSED, const char* permission UNUSED) {
1407 return PC_ERR_INVALID_OPERATION;
1410 int app_revoke_access(const char* subject UNUSED, const char* object UNUSED) {
1411 return PC_ERR_INVALID_OPERATION;