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