From: Rafal Krypa Date: Wed, 17 Apr 2013 15:54:30 +0000 (+0200) Subject: Implement adding apps to additional groups based on enabled permissions. X-Git-Tag: submit/tizen_2.2/20130714.151203~7^2~51 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=8a02204b0a3a1b47e677dfd3e54514845b00689b;p=framework%2Fsecurity%2Flibprivilege-control.git Implement adding apps to additional groups based on enabled permissions. [Issue#] SSDWSSP-175 [Feature] Mixing DAC and SMACK for proper database access control. [Cause] SQlite databases require SMACK write permissions to be readable (locking). [Solution] Use both DAC and SMACK to control access to databases. [Verification] Build, install, reboot target, run tests. Change-Id: Ic5c7da4484d857513f0015582c6ea15dfe8d0d18 --- diff --git a/.privilege_control_app_gids.db b/.privilege_control_app_gids.db new file mode 100644 index 0000000..e69de29 diff --git a/CMakeLists.txt b/CMakeLists.txt index c404abb..e0e0cbb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,5 +82,6 @@ INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/app_group_list DESTINATION ${SHAREDIR} INSTALL(FILES ${CMAKE_CURRENT_SOURCE_DIR}/dev_group_list DESTINATION ${SHAREDIR}) INSTALL(FILES .privilege_control_all_apps_id.db DESTINATION /opt/dbspace) INSTALL(FILES .privilege_control_all_avs_id.db DESTINATION /opt/dbspace) +INSTALL(FILES .privilege_control_app_gids.db DESTINATION /opt/dbspace) #INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/udev/ DESTINATION lib/udev) INSTALL(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/slp-su DESTINATION bin) diff --git a/include/access-db.h b/include/access-db.h index 5c27b91..8a48bf8 100644 --- a/include/access-db.h +++ b/include/access-db.h @@ -46,4 +46,17 @@ int get_all_apps_ids(char *** apps_ids, int * len); */ int get_all_avs_ids(char *** av_ids, int * len); +/** + * This function adds an app to a suplementary group identified by gid + */ +int add_app_gid(const char *app_id, unsigned gid); + +/** + * This function returns (in params) suplementary group ids that an app + * has been assigned to. + * gids should be freed by caller. + */ +int get_app_gids(const char *app_id, unsigned **gids, int *len); + + #endif // _ACCESS_DB_H_ diff --git a/packaging/libprivilege-control-conf.manifest b/packaging/libprivilege-control-conf.manifest index 1be03c8..5eedf3e 100644 --- a/packaging/libprivilege-control-conf.manifest +++ b/packaging/libprivilege-control-conf.manifest @@ -28,5 +28,6 @@ + diff --git a/src/access-db.c b/src/access-db.c index 46343e2..fc51cfc 100644 --- a/src/access-db.c +++ b/src/access-db.c @@ -26,12 +26,10 @@ #include #include #include +#include #include "privilege-control.h" -#define SMACK_APPS_LABELS_DATABASE "/opt/dbspace/.privilege_control_all_apps_id.db" -#define SMACK_AVS_LABELS_DATABASE "/opt/dbspace/.privilege_control_all_avs_id.db" - #ifdef LOG_TAG #undef LOG_TAG #endif // LOG_TAG @@ -56,8 +54,16 @@ typedef enum { DB_APP_TYPE_APPLICATION, DB_APP_TYPE_ANTIVIRUS, + DB_APP_TYPE_GROUPS, + DB_APP_TYPE_COUNT /* Dummy enum element to get number of elements */ } db_app_type_t; +const char* db_file_names[DB_APP_TYPE_COUNT] = { + "/opt/dbspace/.privilege_control_all_apps_id.db", + "/opt/dbspace/.privilege_control_all_avs_id.db", + "/opt/dbspace/.privilege_control_app_gids.db", +}; + typedef struct element_s { struct element_s* next; char* value; @@ -136,21 +142,11 @@ static int add_id_to_database_internal(const char * id, db_app_type_t app_type) C_LOGD("Enter function: %s", __func__); int ret; FILE* file_db = NULL; - char* db_type; + const char* db_file_name = db_file_names[app_type]; - if (DB_APP_TYPE_APPLICATION == app_type) { - db_type = SMACK_APPS_LABELS_DATABASE; - } - else if (DB_APP_TYPE_ANTIVIRUS == app_type) { - db_type = SMACK_AVS_LABELS_DATABASE; - } - else { - return PC_ERR_INVALID_PARAM; - } - - file_db = fopen(db_type, "a"); + file_db = fopen(db_file_name, "a"); if (NULL == file_db) { - C_LOGE("Error while opening database file: %s", db_type); + C_LOGE("Error while opening database file: %s", db_file_name); ret = PC_ERR_FILE_OPERATION; goto out; } @@ -175,27 +171,19 @@ static int get_all_ids_internal (char *** ids, int * len, db_app_type_t app_type int ret; char* scanf_label_format = NULL; FILE* file_db = NULL; - char* db_type; + const char* db_file_name = db_file_names[app_type]; char smack_label[SMACK_LABEL_LEN + 1]; element_t* begin_of_list = NULL; - if (DB_APP_TYPE_APPLICATION == app_type) { - db_type = SMACK_APPS_LABELS_DATABASE; - } else if (DB_APP_TYPE_ANTIVIRUS == app_type) { - db_type = SMACK_AVS_LABELS_DATABASE; - } else { - return PC_ERR_INVALID_PARAM; - } - if (asprintf(&scanf_label_format, "%%%ds\\n", SMACK_LABEL_LEN) < 0) { C_LOGE("Error while creating scanf input label format"); ret = PC_ERR_MEM_OPERATION; goto out; } - file_db = fopen(db_type, "r"); + file_db = fopen(db_file_name, "r"); if (NULL == file_db) { - C_LOGE("Error while opening antivirus_ids database file: %s", db_type); + C_LOGE("Error while opening antivirus_ids database file: %s", db_file_name); ret = PC_ERR_FILE_OPERATION; goto out; } @@ -305,3 +293,75 @@ int add_av_id_to_databse (const char * av_id) return PC_OPERATION_SUCCESS; } + +int add_app_gid(const char *app_id, unsigned gid) +{ + C_LOGD("Enter function: %s", __func__); + char *field = NULL; + int ret; + + ret = asprintf(&field, "%u:%s", gid, app_id); + if (ret == -1) + return PC_ERR_MEM_OPERATION; + + ret = add_id_to_database_internal(field, DB_APP_TYPE_GROUPS); + free(field); + + return ret; +} + +int get_app_gids(const char *app_id, unsigned **gids, int *len) +{ + char** fields; + int len_tmp, ret, i; + + ret = get_all_ids_internal(&fields, &len_tmp, DB_APP_TYPE_GROUPS); + if (ret != PC_OPERATION_SUCCESS) + return ret; + + *len = 0; + *gids = NULL; + for (i = 0; i < len_tmp; ++i) { + const char *field = fields[i]; + const char *app_id_tmp = NULL; + unsigned gid = 0; + + for (; *field; ++field) { + if (*field == ':') { + app_id_tmp = field + 1; + break; + } + if (isdigit(*field)) { + gid = gid * 10 + *field - '0'; + } else { + C_LOGE("Invalid line read: %s", fields[i]); + ret = PC_ERR_FILE_OPERATION; + goto out; + } + } + + if (!strcmp(app_id, app_id_tmp)) { + unsigned *gids_realloc = realloc(*gids, sizeof(unsigned) * (*len + 1)); + if (gids_realloc == NULL) { + C_LOGE("Memory allocation failed"); + ret = PC_ERR_MEM_OPERATION; + goto out; + } + *gids = gids_realloc; + (*gids)[(*len)++] = gid; + } + } + + ret = PC_OPERATION_SUCCESS; +out: + for (i = 0; i < len_tmp; ++i) + free(fields[i]); + free(fields); + + if (ret != PC_OPERATION_SUCCESS) { + free(*gids); + *len = 0; + } + + return ret; +} diff --git a/src/privilege-control.c b/src/privilege-control.c index 54e8e4f..5e7002e 100644 --- a/src/privilege-control.c +++ b/src/privilege-control.c @@ -45,6 +45,7 @@ #define APP_GID 5000 #define APP_UID 5000 +#define ADMIN_GROUP 6504 #define DEVELOPER_GID 5100 #define DEVELOPER_UID 5100 @@ -247,6 +248,8 @@ static int set_dac(const char* pkg_name) int result; int i; new_user usr; + char *current_smack = NULL; + unsigned *additional_gids = NULL; /* * initialize user structure @@ -316,6 +319,55 @@ static int set_dac(const char* pkg_name) fp_group = NULL; /* + * in case of dialer, add admin to glist + */ + if(!strncmp(pkg_name, "com.samsung.phone", 17) || !strncmp(pkg_name, "com.samsung.call", 16) || + !strncmp(pkg_name, "phone-tabui-efl", 15)) + { + gid_t *glist_new; + C_LOGD("Dialer app - add admin to glist"); + glist_new = (gid_t*)realloc(glist, sizeof(gid_t) * (glist_cnt + 1)); + if (glist_new == NULL) { + result = PC_ERR_MEM_OPERATION; // return -2 + C_LOGE("Cannot allocate memory"); + goto error; + } + glist = glist_new; + glist[glist_cnt] = ADMIN_GROUP; // 6504 + glist_cnt++; + } + +#ifdef SMACK_ENABLED + { + gid_t *glist_new; + int i, cnt; + + if (smack_new_label_from_self(¤t_smack)) { + C_LOGE("smack_new_label_from_self failed"); + result = PC_ERR_MEM_OPERATION; + goto error; + } + result = get_app_gids(current_smack, &additional_gids, &cnt); + if (result != PC_OPERATION_SUCCESS) + goto error; + + if (cnt > 0) { + glist_new = (gid_t*)realloc(glist, sizeof(gid_t) * (glist_cnt + cnt)); + if (glist_new == NULL) { + result = PC_ERR_MEM_OPERATION; // return -2 + C_LOGE("Cannot allocate memory"); + goto error; + } + glist = glist_new; + for (i = 0; i < cnt; ++i) { + C_LOGD("Additional GID based on enabled permissions: %u", additional_gids[i]); + glist[glist_cnt++] = additional_gids[i]; + } + } + } +#endif + + /* * setgroups() */ C_LOGD("Adding process to the following groups:"); @@ -380,6 +432,8 @@ error: fclose(fp_group); if(glist != NULL) free(glist); + free(additional_gids); + free(current_smack); return result; } @@ -566,7 +620,6 @@ API int set_privilege(const char* pkg_name) return set_app_privilege(pkg_name, NULL, NULL); } -#ifdef SMACK_ENABLED static inline const char* app_type_name(app_type_t app_type) { switch (app_type) { @@ -579,34 +632,37 @@ static inline const char* app_type_name(app_type_t app_type) } } -static int perm_file(app_type_t app_type, const char* devcap, char** path) { +static int perm_file_path(char** path, app_type_t app_type, const char* perm, const char *suffix) +{ const char* app_type_prefix = NULL; - const char* perm_suffix = NULL; + const char* perm_basename = NULL; int ret = 0; - if (devcap == NULL || strlen(devcap) == 0) { - C_LOGE("empty devcap"); + if (perm == NULL || strlen(perm) == 0) { + C_LOGE("empty permission name"); return PC_ERR_INVALID_PARAM; } app_type_prefix = app_type_name(app_type); - perm_suffix = strrchr(devcap, '/'); - if (perm_suffix) - ++perm_suffix; + perm_basename = strrchr(perm, '/'); + if (perm_basename) + ++perm_basename; else - perm_suffix = devcap; + perm_basename = perm; - ret = asprintf(path, TOSTRING(SHAREDIR) "/%s%s%s.smack", + ret = asprintf(path, TOSTRING(SHAREDIR) "/%s%s%s%s", app_type_prefix ? app_type_prefix : "", app_type_prefix ? "_" : "", - perm_suffix); + perm_basename, suffix); if (ret == -1) { C_LOGE("asprintf failed"); return PC_ERR_MEM_OPERATION; } + return PC_OPERATION_SUCCESS; } +#ifdef SMACK_ENABLED static bool file_exists(const char* path) { FILE* file = fopen(path, "r"); if (file) { @@ -628,11 +684,10 @@ static int perm_to_smack(struct smack_accesses* smack, const char* app_label, ap char smack_accesses[10]; // get file name for permission (devcap) - ret = perm_file(app_type, perm, &path); - if (ret != PC_OPERATION_SUCCESS) - { - free(path); - return ret; + ret = perm_file_path(&path, app_type, perm, ".smack"); + if (ret != PC_OPERATION_SUCCESS) { + C_LOGD("No smack config file for permission %s", perm); + goto out; } if (asprintf(&format_string,"%%%ds %%%ds %%%lus\n", @@ -673,7 +728,49 @@ out: fclose(file); return ret; } +#endif //SMACK_ENABLED + +static int perm_to_dac(const char* app_label, app_type_t app_type, const char* perm) +{ + C_LOGD("Enter function: %s", __func__); + int ret; + char* path = NULL; + FILE* file = NULL; + int gid; + + ret = perm_file_path(&path, app_type, perm, ".dac"); + if (ret != PC_OPERATION_SUCCESS) { + C_LOGD("No dac config file for permission %s", perm); + goto out; + } + + file = fopen(path, "r"); + C_LOGD("path = %s", path); + if (file == NULL) { + C_LOGE("fopen failed"); + ret = PC_OPERATION_SUCCESS; + goto out; + } + + while (fscanf(file, "%d\n", &gid) == 1) { + C_LOGD("Adding app_id %s to group %d", app_label, gid); + ret = add_app_gid(app_label, gid); + if (ret != PC_OPERATION_SUCCESS) { + C_LOGE("sadd_app_gid failed"); + goto out; + } + } + + ret = PC_OPERATION_SUCCESS; + +out: + free(path); + if (file != NULL) + fclose(file); + return ret; +} +#ifdef SMACK_ENABLED static int dir_set_smack_r(const char *path, const char* label, enum smack_label_type type, mode_t type_mask) { @@ -904,10 +1001,10 @@ out: static int app_add_permissions_internal(const char* app_id, app_type_t app_type, const char** perm_list, int permanent) { C_LOGD("Enter function: %s", __func__); + int i, ret = PC_OPERATION_SUCCESS; #ifdef SMACK_ENABLED - char* smack_path = NULL; - int i, ret; int fd = -1; + char* smack_path = NULL; struct smack_accesses *smack = NULL; const char* base_perm = NULL; @@ -927,16 +1024,23 @@ static int app_add_permissions_internal(const char* app_id, app_type_t app_type, goto out; } } - +#endif // SMACK_ENABLED for (i = 0; perm_list[i] != NULL; ++i) { +#ifdef SMACK_ENABLED C_LOGD("perm_to_smack params: app_id: %s, perm_list[%d]: %s", app_id, i, perm_list[i]); ret = perm_to_smack(smack, app_id, app_type, perm_list[i]); if (ret != PC_OPERATION_SUCCESS){ C_LOGE("perm_to_smack failed"); goto out; } +#endif //SMACK_ENABLED + ret = perm_to_dac(app_id, app_type, perm_list[i]); + if (ret != PC_OPERATION_SUCCESS){ + C_LOGE("perm_to_dac failed"); + return ret; + } } - +#ifdef SMACK_ENABLED if (have_smack() && smack_accesses_apply(smack)) { C_LOGE("smack_accesses_apply failed"); ret = PC_ERR_INVALID_OPERATION; @@ -956,11 +1060,9 @@ out: if (smack != NULL) smack_accesses_free(smack); free(smack_path); +#endif //SMACK_ENABLED return ret; -#else - return PC_OPERATION_SUCCESS; -#endif } API int app_add_permissions(const char* app_id, const char** perm_list) @@ -1456,7 +1558,7 @@ API int add_api_feature(app_type_t app_type, const char* api_feature_name, // TODO check process capabilities // get feature file name - ret = perm_file(app_type, api_feature_name, &feature_file); + ret = perm_file_path(&feature_file, app_type, api_feature_name, ".smack"); if (ret != PC_OPERATION_SUCCESS ) { return ret; }