From e3989328c0e432930767d1b5e155220841c6cb17 Mon Sep 17 00:00:00 2001 From: Pawel Polawski Date: Mon, 3 Jun 2013 14:22:23 +0200 Subject: [PATCH] Implementation of background rule loading [Issue#] SSDWSSP-298 [Bug/Feature] Loading SMACK rules in background during device start [Cause] Loading rules during boot take to much time [Solution] Rukles loaded for all apps after boot [Verification] Compile. After homescreen shows up rules should load automaticly Change-Id: Ie84aad8e35761a22d1197e994d3eb89ec31587d4 --- CMakeLists.txt | 3 + include/common.h | 13 +++ packaging/libprivilege-control.spec | 10 +++ rule_loader/CMakeLists.txt | 72 ++++++++++++++++ rule_loader/load_rules.sh | 4 + rule_loader/rule_loader.c | 69 +++++++++++++++ src/common.c | 163 +++++++++++++++++++++++++++++++++++ src/privilege-control.c | 165 ------------------------------------ 8 files changed, 334 insertions(+), 165 deletions(-) create mode 100644 rule_loader/CMakeLists.txt create mode 100644 rule_loader/load_rules.sh create mode 100644 rule_loader/rule_loader.c diff --git a/CMakeLists.txt b/CMakeLists.txt index e10b5a8..7c5b0ea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -65,6 +65,9 @@ TARGET_LINK_LIBRARIES(slp-su ${pkgs_LDFLAGS} ${pkgs_LIBRARIES} privilege-control SET_TARGET_PROPERTIES(slp-su PROPERTIES COMPILE_FLAGS "${slp-su_CFLAGS}") ################################################################################################### +#for rule_loader binary, which loads rules after home screen shows up +ADD_SUBDIRECTORY(rule_loader) + CONFIGURE_FILE(libprivilege-control.pc.in libprivilege-control.pc @ONLY) INSTALL(TARGETS privilege-control DESTINATION ${LIB_INSTALL_DIR} COMPONENT RuntimeLibraries) diff --git a/include/common.h b/include/common.h index cb952e1..512ed1a 100644 --- a/include/common.h +++ b/include/common.h @@ -25,6 +25,7 @@ #include #include #include +#include #ifdef LOG_TAG #undef LOG_TAG @@ -85,6 +86,18 @@ void fts_closep(FTS **f); #define AUTO_SMACK_FREE __attribute__ ((cleanup(smack_freep))) = NULL #define AUTO_FTS_CLOSE __attribute__ ((cleanup(fts_closep))) = NULL +#define SMACK_RULES_DIR "/opt/etc/smack-app/accesses.d/" +#define SMACK_LOADED_APP_RULES "/var/run/smack-app/" + int smack_label_is_valid(const char* smack_label); +int load_smack_from_file(const char* app_id, struct smack_accesses** smack, int *fd, char** path); +int check_if_rules_were_loaded(const char *app_id); +int add_app_first_run_rules(const char *app_id); +void mark_rules_as_loaded(const char *app_id); +int smack_mark_file_name(const char *app_id, char **path); +bool file_exists(const char* path); +int smack_file_name(const char* app_id, char** path); +inline int have_smack(void); + #endif /* COMMON_H_ */ diff --git a/packaging/libprivilege-control.spec b/packaging/libprivilege-control.spec index d9c6ccb..3591ca6 100644 --- a/packaging/libprivilege-control.spec +++ b/packaging/libprivilege-control.spec @@ -58,13 +58,19 @@ mv %{buildroot}/opt/etc/passwd %{buildroot}/etc/passwd mv %{buildroot}/opt/etc/group %{buildroot}/etc/group cp -a %{SOURCE1} %{buildroot}%{_datadir}/ +cp -a %{SOURCE2} %{buildroot}%{_datadir}/ + install -D -d %{buildroot}/etc/rc.d/rc3.d/ install -D -d %{buildroot}/etc/rc.d/rc4.d/ + ln -sf ../init.d/smack_default_labeling %{buildroot}/etc/rc.d/rc3.d/S45smack_default_labeling ln -sf ../init.d/smack_default_labeling %{buildroot}/etc/rc.d/rc4.d/S45smack_default_labeling ln -sf ../init.d/smack_rules %{buildroot}/etc/rc.d/rc3.d/S02smack_rules ln -sf ../init.d/smack_rules %{buildroot}/etc/rc.d/rc4.d/S02smack_rules +mkdir -p %{buildroot}/etc/rc.d/sdrc.d +ln -sf /etc/init.d/load_rules.sh %{buildroot}/etc/rc.d/sdrc.d/S99load_rules + mkdir -p %{buildroot}/usr/lib/systemd/system/basic.target.wants install -m 644 %{SOURCE2} %{buildroot}/usr/lib/systemd/system/ ln -s ../smack-default-labeling.service %{buildroot}/usr/lib/systemd/system/basic.target.wants/ @@ -97,11 +103,15 @@ fi #%{udev_libdir}/rules.d/* #%attr(755,root,root) %{udev_libdir}/uname_env %{_datadir}/license/%{name} +/etc/init.d/load_rules.sh +/usr/bin/rule_loader +/etc/rc.d/sdrc.d/S99load_rules %files conf /etc/group /etc/passwd %attr(755,root,root) /etc/rc.d/* +/usr/share/smack-default-labeling.service /usr/lib/systemd/system/smack-default-labeling.service /usr/lib/systemd/system/basic.target.wants/smack-default-labeling.service %manifest %{_datadir}/%{name}-conf.manifest diff --git a/rule_loader/CMakeLists.txt b/rule_loader/CMakeLists.txt new file mode 100644 index 0000000..93ac71b --- /dev/null +++ b/rule_loader/CMakeLists.txt @@ -0,0 +1,72 @@ +#Copyright (c) 2012 Samsung Electronics Co., Ltd All Rights Reserved +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# @file CMakeLists.txt +# @author Pawel Polawski (p.polawski@samsung.com) +# @version 0.1 +# @brief +# +INCLUDE(FindPkgConfig) +SET(TARGET "rule_loader") + +#dependencies +PKG_CHECK_MODULES(TARGET_DEP + libsmack + REQUIRED + ) + +#files to compile +SET(TARGET_SOURCES + ${PROJECT_SOURCE_DIR}/rule_loader/rule_loader.c + ${PROJECT_SOURCE_DIR}/src/access-db.c + ${PROJECT_SOURCE_DIR}/src/common.c + ${PROJECT_SOURCE_DIR}/src/privilege-control.c + ) + +#header directories +INCLUDE_DIRECTORIES( + ${TARGET_DEP_INCLUDE_DIRS} + ${PROJECT_SOURCE_DIR}/include + ) + +#preprocessor definitions +#ADD_DEFINITIONS("-DDPL_LOGS_ENABLED") + +#output format +ADD_EXECUTABLE(${TARGET} ${TARGET_SOURCES}) + +#linker directories +TARGET_LINK_LIBRARIES(${TARGET} + ${TARGET_DEP_LIBRARIES} + privilege-control + ) + +#place for output file +INSTALL(TARGETS ${TARGET} + DESTINATION /usr/bin + PERMISSIONS + OWNER_READ + OWNER_WRITE + OWNER_EXECUTE + ) + +#place for additional script +INSTALL(FILES + ${PROJECT_SOURCE_DIR}/rule_loader/load_rules.sh + DESTINATION /etc/init.d + PERMISSIONS + OWNER_READ + OWNER_WRITE + OWNER_EXECUTE + ) diff --git a/rule_loader/load_rules.sh b/rule_loader/load_rules.sh new file mode 100644 index 0000000..7149ba7 --- /dev/null +++ b/rule_loader/load_rules.sh @@ -0,0 +1,4 @@ +#/bin/bash + +#load rules of all installed apps +/usr/bin/rule_loader & diff --git a/rule_loader/rule_loader.c b/rule_loader/rule_loader.c new file mode 100644 index 0000000..eaf9514 --- /dev/null +++ b/rule_loader/rule_loader.c @@ -0,0 +1,69 @@ +#include +#include + +#include +#include +#include + +int main(int argc, char * argv[]) +{ + FILE * log_file = NULL; + char ** installed_app_list = NULL; + int app_list_len = 0; + int i = 0; + int ret = 0; + + log_file = fopen("/root/rules_loader_log.txt", "w"); + if (log_file == NULL) + goto error; + fprintf(log_file, "Loading rules for all installed apps:\n"); + + //getting app list from database + ret = get_all_apps_ids(&installed_app_list, &app_list_len); + if (ret != PC_OPERATION_SUCCESS) { + fprintf(log_file, "Unable to load applications list!\n);"); + ret = -1; + goto error; + } + + //checking if database is not empty + if (app_list_len == 0) { + fprintf(log_file, "App database empty, no apps installed\n"); + goto error; + } + + //loading rules for each app + for (i = 0; i < app_list_len; i++) { + fprintf(log_file, "Loading rules for app_id: %s...\n", installed_app_list[i]); + + //checking if rules are loaded + ret = check_if_rules_were_loaded(installed_app_list[i]); + if (ret < 0) { + fprintf(log_file,"Error in check_if_rules_were_loaded()\n"); + //we skipping to the next app_id + } else if (ret == 0) { + //if not load rules + ret = add_app_first_run_rules(installed_app_list[i]); + if (ret < 0) + fprintf(log_file,"Error in add_app_first_run_rules()\n"); + else + //mark rules as loaded + mark_rules_as_loaded(installed_app_list[i]); + } else { + fprintf(log_file,"Rules already loaded\n"); + } + + fprintf(log_file, "DONE\n"); + } + +error: + //cleaning up + if (installed_app_list != NULL) { + for (i = 0; i < app_list_len; i++) + free(installed_app_list[i]); + free(installed_app_list); + } + + fclose(log_file); + return ret; +} diff --git a/src/common.c b/src/common.c index 1767fe7..b86835f 100644 --- a/src/common.c +++ b/src/common.c @@ -19,10 +19,17 @@ * */ +#define _GNU_SOURCE #include +#include +#include #include #include +#include +#include + #include "common.h" +#include "privilege-control.h" /* TODO: implement such function in libsmack instead */ int smack_label_is_valid(const char* smack_label) @@ -84,3 +91,159 @@ void fts_closep(FTS **f) fts_close(*f); } + +/** + * This function check if application SMACK rules was already loaded + * by checking if specific file exist. This Function desn't create such file. + * It returns: + * 0 if rules weren't yet loaded, + * 1 if rules were loaded + * -1 if error occurs while checking + */ +int check_if_rules_were_loaded(const char *app_id) +{ + C_LOGD("Enter function: %s", __func__); + int ret; + char *path AUTO_FREE; + + ret = smack_mark_file_name(app_id, &path); + if(PC_OPERATION_SUCCESS != ret) { + return -1; + } + + return file_exists(path); +} + +/** + * This function creates a (empty) file for app if rules for this app + * were loaded. + */ +void mark_rules_as_loaded(const char *app_id) +{ + struct stat s; + char *path AUTO_FREE; + FILE *file = NULL; + + if(smack_mark_file_name(app_id, &path)) { + C_LOGE("Error in smack_mark_file_name"); + return; + } + + if (-1 == stat(SMACK_LOADED_APP_RULES, &s)) { + if (ENOENT == errno) { + C_LOGD("Creating dir %s", SMACK_LOADED_APP_RULES); + mkdir(SMACK_LOADED_APP_RULES, S_IRWXU | S_IRWXG | S_IRWXO); + } + } + + file = fopen(path, "w"); + fclose(file); +} + +int add_app_first_run_rules(const char *app_id) +{ + C_LOGD("Enter function: %s", __func__); + int ret; + int fd AUTO_CLOSE; + char *smack_path AUTO_FREE; + struct smack_accesses* smack AUTO_SMACK_FREE; + + ret = load_smack_from_file(app_id, &smack, &fd, &smack_path); + if (ret != PC_OPERATION_SUCCESS) { + C_LOGE("Error while load_smack_from_file"); + return ret; + } + if (have_smack() && smack_accesses_apply(smack)) { + C_LOGE("smack_accesses_apply failed"); + return PC_ERR_INVALID_OPERATION; + } + + return PC_OPERATION_SUCCESS; +} + +int load_smack_from_file(const char* app_id, struct smack_accesses** smack, int *fd, char** path) +{ + C_LOGD("Enter function: %s", __func__); + int ret; + + ret = smack_file_name(app_id, path); + if (ret != PC_OPERATION_SUCCESS) + return ret; + + if (smack_accesses_new(smack)) { + C_LOGE("smack_accesses_new failed"); + return PC_ERR_MEM_OPERATION; + } + + *fd = open(*path, O_CREAT|O_RDWR, 0644); + if (*fd == -1) { + C_LOGE("file open failed: %s", strerror(errno)); + return PC_ERR_FILE_OPERATION; + } + + if (flock(*fd, LOCK_EX)) { + C_LOGE("flock failed"); + return PC_ERR_INVALID_OPERATION; + } + + if (smack_accesses_add_from_file(*smack, *fd)) { + C_LOGE("smack_accesses_add_from_file failed"); + return PC_ERR_INVALID_OPERATION; + } + + /* Rewind the file */ + if (lseek(*fd, 0, SEEK_SET) == -1) { + C_LOGE("lseek failed"); + return PC_ERR_FILE_OPERATION; + } + + return PC_OPERATION_SUCCESS; +} + +int smack_mark_file_name(const char *app_id, char **path) +{ + if (asprintf(path, SMACK_LOADED_APP_RULES "/%s", app_id) == -1) { + C_LOGE("asprintf failed"); + *path = NULL; + return PC_ERR_MEM_OPERATION; + } + + return PC_OPERATION_SUCCESS; +} + +bool file_exists(const char* path) { + FILE* file = fopen(path, "r"); + if (file) { + fclose(file); + return true; + } + return false; +} + +int smack_file_name(const char* app_id, char** path) +{ + if (asprintf(path, SMACK_RULES_DIR "/%s", app_id) == -1) { + C_LOGE("asprintf failed"); + *path = NULL; + return PC_ERR_MEM_OPERATION; + } + + return PC_OPERATION_SUCCESS; +} + +inline int have_smack(void) +{ + static int have_smack = -1; + + if (-1 == have_smack) { + if (NULL == smack_smackfs_path()) { + C_LOGD("Libprivilage-control: no smack found on phone"); + have_smack = 0; + } else { + C_LOGD("Libprivilege-control: found smack on phone"); + have_smack = 1; + } + } + + return have_smack; +} diff --git a/src/privilege-control.c b/src/privilege-control.c index d0def55..a86c718 100644 --- a/src/privilege-control.c +++ b/src/privilege-control.c @@ -60,9 +60,6 @@ #define APP_GROUP_PATH TOSTRING(SHAREDIR) "/app_group_list" #define DEV_GROUP_PATH TOSTRING(SHAREDIR) "/dev_group_list" -#define SMACK_RULES_DIR "/opt/etc/smack/accesses.d/" -#define SMACK_LOADED_APP_RULES "/var/run/smack-app/" - #define SMACK_APP_LABEL_TEMPLATE "~APP~" #define SMACK_SRC_FILE_SUFFIX "_src_file" #define SMACK_SRC_DIR_SUFFIX "_src_dir" @@ -74,7 +71,6 @@ #define TIZEN_PRIVILEGE_APPSETTING "http://tizen.org/privilege/appsetting" - typedef struct { char user_name[10]; int uid; @@ -101,9 +97,6 @@ enum { DECISION_LABEL = 1 }; -static int load_smack_from_file(const char* app_id, struct smack_accesses** smack, int *fd, char** path); -static bool file_exists(const char* path); - int state_tree_cmp(const void *first, const void *second) { return strcmp(((state_node*)first)->key, @@ -208,23 +201,6 @@ int state_restore(const char* subject, const char* object) return PC_OPERATION_SUCCESS; } -static inline int have_smack(void) -{ - static int have_smack = -1; - - if (-1 == have_smack) { - if (NULL == smack_smackfs_path()) { - C_LOGD("Libprivilage-control: no smack found on phone"); - have_smack = 0; - } else { - C_LOGD("Libprivilege-control: found smack on phone"); - have_smack = 1; - } - } - - return have_smack; -} - API int control_privilege(void) { C_LOGD("Enter function: %s", __func__); @@ -237,17 +213,6 @@ API int control_privilege(void) return PC_ERR_NOT_PERMITTED; } -static int smack_mark_file_name(const char *app_id, char **path) -{ - if (asprintf(path, SMACK_LOADED_APP_RULES "/%s", app_id) == -1) { - C_LOGE("asprintf failed"); - *path = NULL; - return PC_ERR_MEM_OPERATION; - } - - return PC_OPERATION_SUCCESS; -} - /** * TODO: this function should be moved to libsmack in open-source. */ @@ -660,77 +625,6 @@ static app_type_t verify_app_type(const char* type, const char* path) exit(EXIT_FAILURE); } -static int add_app_first_run_rules(const char *app_id) -{ - C_LOGD("Enter function: %s", __func__); - int ret; - int fd AUTO_CLOSE; - char *smack_path AUTO_FREE; - struct smack_accesses* smack AUTO_SMACK_FREE; - - ret = load_smack_from_file(app_id, &smack, &fd, &smack_path); - if (ret != PC_OPERATION_SUCCESS) { - C_LOGE("Error while load_smack_from_file"); - return ret; - } - if (have_smack() && smack_accesses_apply(smack)) { - C_LOGE("smack_accesses_apply failed"); - return PC_ERR_INVALID_OPERATION; - } - - return PC_OPERATION_SUCCESS; -} - -/** - * This function check if application SMACK rules was already loaded - * by checking if specific file exist. This Function desn't create such file. - * It returns: - * 0 if rules weren't yet loaded, - * 1 if rules were loaded - * -1 if error occurs while checking - */ -static int check_if_rules_were_loaded(const char *app_id) -{ - C_LOGD("Enter function: %s", __func__); - int ret; - char *path AUTO_FREE; - - ret = smack_mark_file_name(app_id, &path); - if(PC_OPERATION_SUCCESS != ret) { - return -1; - } - - return file_exists(path); -} - -/** - * This function creates a (empty) file for app if rules for this app - * were loaded. - */ -static void mark_rules_as_loaded(const char *app_id) -{ - struct stat s; - char *path AUTO_FREE; - FILE *file = NULL; - - if(smack_mark_file_name(app_id, &path)) { - C_LOGW("Warning: smack_mark_file_name failed"); - return; - } - - if (-1 == stat(SMACK_LOADED_APP_RULES, &s)) { - if (ENOENT == errno) { - C_LOGD("Creating dir %s", SMACK_LOADED_APP_RULES); - if(-1 == mkdir(SMACK_LOADED_APP_RULES, S_IRWXU | S_IRWXG | S_IRWXO)) { - C_LOGD("mkdir failed. Errno: %d", errno); - } - } - } - - file = fopen(path, "w"); - fclose(file); -} - API int set_app_privilege(const char* name, const char* type, const char* path) { C_LOGD("Enter function: %s", __func__); @@ -890,15 +784,6 @@ static int perm_file_path(char** path, app_type_t app_type, const char* perm, co return PC_OPERATION_SUCCESS; } -static bool file_exists(const char* path) { - FILE* file = fopen(path, "r"); - if (file) { - fclose(file); - return true; - } - return false; -} - static int perm_to_smack(struct smack_accesses* smack, const char* app_label, app_type_t app_type, const char* perm) { C_LOGD("Enter function: %s", __func__); @@ -1093,56 +978,6 @@ API char* app_id_from_socket(int sockfd) return app_id; } -static int smack_file_name(const char* app_id, char** path) -{ - if (asprintf(path, SMACK_RULES_DIR "/%s", app_id) == -1) { - C_LOGE("asprintf failed"); - *path = NULL; - return PC_ERR_MEM_OPERATION; - } - - return PC_OPERATION_SUCCESS; -} - -static int load_smack_from_file(const char* app_id, struct smack_accesses** smack, int *fd, char** path) -{ - C_LOGD("Enter function: %s", __func__); - int ret; - - ret = smack_file_name(app_id, path); - if (ret != PC_OPERATION_SUCCESS) - return ret; - - if (smack_accesses_new(smack)) { - C_LOGE("smack_accesses_new failed"); - return PC_ERR_MEM_OPERATION; - } - - *fd = open(*path, O_CREAT|O_RDWR, 0644); - if (*fd == -1) { - C_LOGE("file open failed: %s", strerror(errno)); - return PC_ERR_FILE_OPERATION; - } - - if (flock(*fd, LOCK_EX)) { - C_LOGE("flock failed"); - return PC_ERR_INVALID_OPERATION; - } - - if (smack_accesses_add_from_file(*smack, *fd)) { - C_LOGE("smack_accesses_add_from_file failed"); - return PC_ERR_INVALID_OPERATION; - } - - /* Rewind the file */ - if (lseek(*fd, 0, SEEK_SET) == -1) { - C_LOGE("lseek failed"); - return PC_ERR_FILE_OPERATION; - } - - return PC_OPERATION_SUCCESS; -} - static int app_add_rule(const char *app_id, const char *object, const char *perm) { C_LOGD("Enter function: %s", __func__); -- 2.7.4