From 9fddab9e58ccd9acdecdbfcf12770c50feac4d2b Mon Sep 17 00:00:00 2001 From: Kyungwook Tak Date: Thu, 8 Dec 2016 10:12:11 +0900 Subject: [PATCH] Refine directory traversing: registering callback There's two part of directory traversing(removing all files in directory and loading preloaded app deks). So duplicated code can be compressed to traverse_directory with entry callback registered. Change-Id: I654bed7f3b4efff75b2853fceb3f9d97b51a85b5 Signed-off-by: Kyungwook Tak --- srcs/key_handler.c | 218 +++++++++++++++++++++++++++-------------------------- 1 file changed, 110 insertions(+), 108 deletions(-) diff --git a/srcs/key_handler.c b/srcs/key_handler.c index d77016f..cdc96af 100644 --- a/srcs/key_handler.c +++ b/srcs/key_handler.c @@ -188,61 +188,87 @@ error: return ret; } -static void _remove_file(const char *path) +typedef int(*entry_callback)(const char *path, const struct dirent *entry, void *user_data); +static int traverse_directory(const char *path, entry_callback ecb, void *user_data) { - unlink(path); -} - -void _remove_directory(const char *path) -{ - char file_path_buff[MAX_PATH_LEN] = {0, }; DIR *dir = opendir(path); if (dir == NULL) { - if (errno == ENOENT) - WAE_SLOGI("directory is not exist already(%s)", path); - else + if (errno == ENOENT) { + // it's not error for current cases of using traverse_directory. + // To open dek store directory for load/remove can be occured in some + // exception(or attacked) cases but we can just ignore it if it isn't the + // first time call load_preloaded_app_deks. + WAE_SLOGI("directory isn't exist(%s).", path); + return WAE_ERROR_NONE; + } else { WAE_SLOGE("Failed to open dir(%s)", path); - - return; + return WAE_ERROR_FILE; + } } + int ret = WAE_ERROR_NONE; struct dirent entry; struct dirent *result = NULL; while (true) { if (readdir_r(dir, &entry, &result) != 0) { + WAE_SLOGE("readdir_r error on dir(%s) errno(%d)", path, errno); break; } else if (result == NULL) { - break; + break; // end of directory } else if (strcmp(entry.d_name, ".") == 0 || strcmp(entry.d_name, "..") == 0) { continue; } - if (snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s", path, entry.d_name) - < 0) - continue; + int _ret = ecb(path, result, user_data); + if (_ret != WAE_ERROR_NONE) + ret = _ret; + } - if (entry.d_type == DT_DIR) { - _remove_directory(file_path_buff); - } else { - WAE_SLOGD("remove file(%s)", file_path_buff); - _remove_file(file_path_buff); - } + closedir(dir); + return ret; +} + +static void _remove_file(const char *path) +{ + unlink(path); +} + +static int _entry_callback_remove_all( + const char *path, const struct dirent *entry, void *user_data) +{ + (void) user_data; // TODO: use UNUSED macro + + char file_path_buff[MAX_PATH_LEN] = {0, }; + if (snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s", path, entry->d_name) < 0) + return WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */ + + int ret = WAE_ERROR_NONE; + if (entry->d_type == DT_DIR) { + int _ret = traverse_directory(file_path_buff, _entry_callback_remove_all, NULL); + if (_ret != WAE_ERROR_NONE) + ret = _ret; + rmdir(file_path_buff); + } else { + _remove_file(file_path_buff); } + return ret; +} + +void _remove_directory(const char *path) +{ + traverse_directory(path, _entry_callback_remove_all, NULL); WAE_SLOGD("remove directory(%s)", path); - closedir(dir); rmdir(path); } int _get_preloaded_app_dek_file_path(const char *pkg_id, size_t size, char *path) { - int ret = snprintf(path, size, "%s/%s_%s.adek", - _get_dek_store_path(), APP_DEK_FILE_PFX, pkg_id); - - if (ret < 0) + if (snprintf(path, size, "%s/%s_%s.adek", + _get_dek_store_path(), APP_DEK_FILE_PFX, pkg_id) < 0) return WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */ - - return WAE_ERROR_NONE; + else + return WAE_ERROR_NONE; } static int _extract_pkg_id_from_file_name(const char *file_name, char *pkg_id) @@ -574,18 +600,56 @@ int _get_app_dek_kek(raw_buffer_s **pdek_kek) #endif } -int load_preloaded_app_deks() +static int _entry_callback_load_preloaded_adeks( + const char *path, const struct dirent *entry, void *prikey) { - WAE_SLOGI("load_preloaded_app_deks start"); + const char *pub_key_path = _get_dek_kek_pub_key_path(); + const char *pri_key_path = _get_dek_kek_pri_key_path(); + + char file_path_buff[MAX_PATH_LEN] = {0, }; + if (snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s", path, entry->d_name) < 0) + return WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */ + + if (strcmp(file_path_buff, pub_key_path) == 0 || + strcmp(file_path_buff, pri_key_path) == 0) + return WAE_ERROR_NONE; /* skip KEK files */ - int global_ret = WAE_ERROR_NONE; + if (entry->d_type != DT_REG || strstr(entry->d_name, APP_DEK_FILE_PFX) == NULL) { + if (entry->d_type == DT_DIR) + WAE_SLOGW( + "Invalid file in dek store(%s). Directory shouldn't be here.", path); + else + WAE_SLOGW( + "Invalid file in dek store(%s). " + "Not regular file or prefix(%s) is invalid.", path, APP_DEK_FILE_PFX); + + return WAE_ERROR_FILE; + } char pkg_id[MAX_PKGID_LEN] = {0, }; - char file_path_buff[MAX_PATH_LEN] = {0, }; + int ret = _extract_pkg_id_from_file_name(entry->d_name, pkg_id); + if (ret != WAE_ERROR_NONE) { + WAE_SLOGW("Failed to extract pkgid from file(%s). It will be ignored.", file_path_buff); + return ret; + } + + ret = _load_preloaded_app_dek((raw_buffer_s *)prikey, file_path_buff, pkg_id); + if (ret == WAE_ERROR_NONE || ret == WAE_ERROR_KEY_EXISTS) { + WAE_SLOGI("Successfully load app dek(%s)", file_path_buff); + return WAE_ERROR_NONE; + } else { + WAE_SLOGW("Failed to load app dek(%s) ret(%d)", file_path_buff, ret); + return ret; + } +} + +int load_preloaded_app_deks() +{ + WAE_SLOGI("load_preloaded_app_deks start"); + + int ret = WAE_ERROR_NONE; const char *dek_store_path = _get_dek_store_path(); - const char *dek_kek_pub_key_path = _get_dek_kek_pub_key_path(); - const char *dek_kek_pri_key_path = _get_dek_kek_pri_key_path(); raw_buffer_s *prikey = NULL; DIR *dir = NULL; @@ -602,86 +666,24 @@ int load_preloaded_app_deks() return WAE_ERROR_NONE; } else { WAE_SLOGE("Fail to open dir. dir=%s", dek_store_path); - global_ret = WAE_ERROR_FILE; + ret = WAE_ERROR_FILE; goto out; } } - global_ret = _get_app_dek_kek(&prikey); - - if (global_ret != WAE_ERROR_NONE) { - WAE_SLOGE("Fail to get APP_DEK_KEK Private Key"); + ret = _get_app_dek_kek(&prikey); + if (ret != WAE_ERROR_NONE) { + WAE_SLOGE("Fail to get APP_DEK_KEK Private Key. ret(%d)", ret); goto out; } - struct dirent entry; - struct dirent *result = NULL; - - while (true) { - int ret = WAE_ERROR_NONE; - if (readdir_r(dir, &entry, &result) != 0) { - global_ret = WAE_ERROR_FILE; - break; - } - - // readdir_r returns NULL in *result if the end - // of the directory stream is reached - if (result == NULL) - break; - - if (strcmp(entry.d_name, ".") == 0 || strcmp(entry.d_name, "..") == 0) - continue; - - if (snprintf(file_path_buff, sizeof(file_path_buff), "%s/%s", - dek_store_path, entry.d_name) < 0) { - WAE_SLOGE("Failed to make file path by snprintf."); - global_ret = WAE_ERROR_INVALID_PARAMETER; /* buffer size too small */ - break; - } - - // skip for KEKs. They'll be deleted after all akek loaded to key-manager. - if (strcmp(file_path_buff, dek_kek_pub_key_path) == 0 || - strcmp(file_path_buff, dek_kek_pri_key_path) == 0) { - WAE_SLOGD("Skip KEK file...(%s)", file_path_buff); - continue; - } - - // regular file && start with KEY_MANAGER_INITIAL_VALUE_FILE_PFX - // clear all invalid cases silently - if (entry.d_type != DT_REG || strstr(entry.d_name, APP_DEK_FILE_PFX) == NULL) { - if (entry.d_type == DT_DIR) { - WAE_SLOGW( - "Invalid file in dek store(%s). Directory shouldn't be here.", - dek_store_path); - global_ret = WAE_ERROR_FILE; - } else { - WAE_SLOGW( - "Invalid file in dek store(%s). " - "Not regular file or prefix(%s) is invalid.", - dek_store_path, APP_DEK_FILE_PFX); - global_ret = WAE_ERROR_FILE; - } - - continue; - } - - ret = _extract_pkg_id_from_file_name(entry.d_name, pkg_id); - - if (ret != WAE_ERROR_NONE) { - WAE_SLOGW("Failed to extract pkgid from file. It will be ignored. file=%s", - file_path_buff); - global_ret = ret; - continue; - } + // close dek store dir fd not to affect the traverse_directory call + closedir(dir); + dir = NULL; - ret = _load_preloaded_app_dek(prikey, file_path_buff, pkg_id); - if (ret != WAE_ERROR_NONE && ret != WAE_ERROR_KEY_EXISTS) { - WAE_SLOGW("Failed to load app dek(%s) ret(%d)", file_path_buff, ret); - global_ret = ret; - } else { - WAE_SLOGI("Successfully load app dek(%s)", file_path_buff); - } - } + ret = traverse_directory(dek_store_path, _entry_callback_load_preloaded_adeks, prikey); + if (ret != WAE_ERROR_NONE) + WAE_SLOGE("Fail when traverse dek store directory. ret(%d)", ret); out: if (prikey != NULL) @@ -699,7 +701,7 @@ out: // initializer service failure. _remove_directory(dek_store_path); - return global_ret; + return ret; } int remove_app_ce(uid_t uid, const char *pkg_id, wae_app_type_e app_type) -- 2.7.4