New API for labeling directories and files.
authorRafal Krypa <r.krypa@samsung.com>
Thu, 23 May 2013 09:54:34 +0000 (11:54 +0200)
committerGerrit Code Review <gerrit2@kim11>
Wed, 29 May 2013 15:27:22 +0000 (00:27 +0900)
[Issue#]       SSDWSSP-240
[Feature]      New API for labeling directories and files
[Cause]        Redesigned with new requested feature implementation
[Solution]     Provide new function app_setup_path(), deprecate app_label_dir(), app_label_shared_dir() and app_add_shared_dir_readers()
[Verification] Build, install, reboot target. Run libprivilege-control tests.

Change-Id: I9e8ad0c279fc8edfe2ef3764382d6726f5615dcc

.privilege_control_public_dirs.db [new file with mode: 0644]
CMakeLists.txt
include/access-db.h
include/privilege-control.h
packaging/libprivilege-control-conf.manifest
src/access-db.c
src/privilege-control.c

diff --git a/.privilege_control_public_dirs.db b/.privilege_control_public_dirs.db
new file mode 100644 (file)
index 0000000..e69de29
index afc2af2..9be5a98 100644 (file)
@@ -44,7 +44,7 @@ SET(libprivilege-control_SOURCES
        )
 SET(libprivilege-control_LDFLAGS " -module -avoid-version ")
 SET(libprivilege-control_CFLAGS  " ${CFLAGS} -fPIC -I${include_dir}")
-SET(libprivilege-control_LIBADD  "${pkgs_LDFLAGS} -lcap")
+SET(libprivilege-control_LIBADD  "${pkgs_LDFLAGS} -lcap -lcrypt")
 
 ADD_LIBRARY(privilege-control SHARED ${libprivilege-control_SOURCES})
 TARGET_LINK_LIBRARIES(privilege-control ${libprivilege-control_LIBADD} ${pkgs_LIBRARIES})
@@ -83,5 +83,6 @@ 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(FILES .privilege_control_public_dirs.db DESTINATION /opt/dbspace)
 #INSTALL(DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/udev/ DESTINATION lib/udev)
 INSTALL(PROGRAMS ${CMAKE_CURRENT_SOURCE_DIR}/slp-su DESTINATION bin)
index 8a48bf8..c0e688c 100644 (file)
@@ -58,5 +58,15 @@ int add_app_gid(const char *app_id, unsigned gid);
  */
 int get_app_gids(const char *app_id, unsigned **gids, int *len);
 
+/**
+ * This functions add public RO path to the database.
+ */
+int db_add_public_dir(const char *dir_label);
+
+/**
+ * This function returns (in params) list of public RO paths
+ * dir_labels should be freed by caller.
+ */
+int db_get_public_dirs(char ***dir_labels, int *len);
 
 #endif // _ACCESS_DB_H_
index 311c546..bfa06ce 100644 (file)
@@ -38,6 +38,8 @@ extern "C" {
 #define API __attribute__((visibility("default")))
 #endif // API
 
+#define DEPRECATED __attribute__((deprecated));
+
 /* error codes */
 #define        PC_OPERATION_SUCCESS            ((int)0)
 #define PC_ERR_FILE_OPERATION          -1
@@ -53,10 +55,17 @@ typedef enum {
        APP_TYPE_OTHER,
 } app_type_t;
 
+typedef enum {
+       APP_PATH_PRIVATE,
+       APP_PATH_GROUP_RW,
+       APP_PATH_PUBLIC_RO,
+       APP_PATH_SETTINGS_RW
+} app_path_type_t;
+
 /* APIs - used by applications */
-int control_privilege(void) __attribute__((deprecated));
+int control_privilege(void) DEPRECATED;
 
-int set_privilege(const char* pkg_name) __attribute__((deprecated));
+int set_privilege(const char* pkg_name) DEPRECATED;
 
 /**
  * Function get process smack label base on pid.
@@ -142,7 +151,7 @@ int app_uninstall(const char* app_id);
  * @param app_id application identifier
  * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error.
  */
-int app_register_av(const char* app_av_id) __attribute__((deprecated));
+int app_register_av(const char* app_av_id) DEPRECATED;
 
 /**
  * Grant SMACK permissions based on permissions list.
@@ -158,7 +167,7 @@ int app_register_av(const char* app_av_id) __attribute__((deprecated));
  * @param perm_list array of permission names, last element must be NULL
  * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
  */
-int app_add_permissions(const char* app_id, const char** perm_list)  __attribute__((deprecated));
+int app_add_permissions(const char* app_id, const char** perm_list) DEPRECATED;
 
 /**
  * Grant temporary SMACK permissions based on permissions list.
@@ -172,7 +181,7 @@ int app_add_permissions(const char* app_id, const char** perm_list)  __attribute
  * @param perm_list array of permission names, last element must be NULL
  * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
  */
-int app_add_volatile_permissions(const char* app_id, const char** perm_list)  __attribute__((deprecated));
+int app_add_volatile_permissions(const char* app_id, const char** perm_list) DEPRECATED;
 
 /**
  * Grant SMACK permissions based on permissions list.
@@ -233,12 +242,13 @@ int app_reset_permissions(const char* app_id);
  * This function should be called once during app installation.
  * Results will be persistent on the file system.
  * It must be called by privileged user.
+ * THIS FUNCTION IS NOW DEPRECATED. app_setup_path() SHOULD BE USED INSTEAD.
  *
  * @param app_label label name
  * @param path directory path
  * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
  */
-int app_label_dir(const char* app_label, const char* path);
+int app_label_dir(const char* app_label, const char* path) DEPRECATED;
 
 /**
  * Recursively set SMACK access and transmute labels for an application
@@ -247,6 +257,7 @@ int app_label_dir(const char* app_label, const char* path);
  * Results will be persistent on the file system.
  * It must be called by privileged user.
  * Labels app_label and shared_label should not be equal.
+ * THIS FUNCTION IS NOW DEPRECATED. app_setup_path() SHOULD BE USED INSTEAD.
  *
  * @param app_label label name, used as subject for SMACK rule
  * @param shared_label, used as object for SMACK rule
@@ -254,20 +265,49 @@ int app_label_dir(const char* app_label, const char* path);
  * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
  */
 int app_label_shared_dir(const char* app_label, const char* shared_label,
-                                                const char* path);
-
-
+                                                const char* path) DEPRECATED;
 
 /**
  * Add SMACK rx rules for application identifiers to shared_label.
  * This function should be called during app installation.
  * It must be called by privileged user.
+ * THIS FUNCTION IS NOW DEPRECATED. NO REPLACEMENT IS NEEDED.
  *
  * @param shared_label label of the shared resource
  * @param app_list list of application SMACK identifiers
  * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
  */
-int add_shared_dir_readers(const char* shared_label, const char** app_list);
+int add_shared_dir_readers(const char* shared_label, const char** app_list) DEPRECATED;
+
+/**
+ * Recursively set SMACK labels for an application directory. The exact behavior
+ * depends on app_path_type argument:
+ *     - APP_PATH_PRIVATE: label with app's label, set access label on everything
+ *    and execute label on executable files and symlinks to executable files
+ *
+ *     - APP_PATH_GROUP_RW: label with given shared_label, set access label on
+ *       everything and enable transmute on directories. Also give app_id full access
+ *       to the shared label.
+ *
+ *     - APP_PATH_PUBLIC_RO: label with autogenerated label, set access label on
+ *       everything and enable transmute on directories. Give full access to the label to
+ *       app_id and RX access to all other apps.
+ *
+ *     - APP_PATH_SETTINGS_RW: label with autogenerated label, set access label on
+ *       everything and enable transmute on directories. Give full access to the label to
+ *       app_id and RWX access to all appsetting apps.
+ *
+ * This function should be called during app installation.
+ * Results will be persistent on the file system.
+ * It must be called by privileged user.
+ *
+ * @param app_id
+ * @param path
+ * @param app_path_type
+ * @param shared_label (optional argument for APP_PATH_GROUP_RW path type)
+ * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
+ */
+int app_setup_path(const char* app_id, const char* path, app_path_type_t app_path_type, ...);
 
 /**
  * Make two applications "friends", by giving them both full permissions on
index 543822a..fd401ab 100644 (file)
@@ -38,5 +38,6 @@
                <filesystem path="/opt/dbspace/.privilege_control_all_apps_id.db" label="system::privilege_control::db"/>
                <filesystem path="/opt/dbspace/.privilege_control_all_avs_id.db" label="system::privilege_control::db"/>
                <filesystem path="/opt/dbspace/.privilege_control_app_gids.db" label="system::privilege_control::db"/>
+               <filesystem path="/opt/dbspace/.privilege_control_public_dirs.db" label="system::privilege_control::db"/>
        </assign>
 </manifest>
index 61609ec..05d0bd4 100644 (file)
@@ -36,6 +36,7 @@ typedef enum {
        DB_APP_TYPE_APPLICATION,
        DB_APP_TYPE_ANTIVIRUS,
        DB_APP_TYPE_GROUPS,
+       DB_APP_TYPE_PUBLIC_DIRS,
        DB_APP_TYPE_COUNT /* Dummy enum element to get number of elements */
 } db_app_type_t;
 
@@ -43,6 +44,7 @@ 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",
+               "/opt/dbspace/.privilege_control_public_dirs.db",
 };
 
 typedef struct element_s {
@@ -310,3 +312,23 @@ out:
 
        return ret;
 }
+
+int db_add_public_dir(const char *dir_label)
+{
+       C_LOGD("Enter function: %s", __func__);
+
+       if (add_id_to_database_internal(dir_label, DB_APP_TYPE_PUBLIC_DIRS))
+               return PC_ERR_DB_OPERATION;
+
+       return PC_OPERATION_SUCCESS;
+}
+
+int db_get_public_dirs(char ***dir_labels, int *len)
+{
+       C_LOGD("Enter function: %s", __func__);
+
+       if (get_all_ids_internal(dir_labels, len, DB_APP_TYPE_PUBLIC_DIRS))
+               return PC_ERR_DB_OPERATION;
+
+       return PC_OPERATION_SUCCESS;
+}
index 3615465..1e6dc14 100644 (file)
@@ -1036,6 +1036,38 @@ out:
        return ret;
 }
 
+/**
+ *  This function will grant app_id RX access to all public directories and
+ *  files, previously designated by app_setup_path(APP_PATH_PUBLIC_RO)
+ *  This should be call in app_install function.
+ */
+static int register_app_for_public_dirs(const char *app_id, struct smack_accesses *smack)
+{
+       C_LOGD("Enter function: %s", __func__);
+       int ret, i;
+       char **public_dirs AUTO_FREE;
+       int public_dirs_cnt = 0;
+
+       ret = db_get_public_dirs(&public_dirs, &public_dirs_cnt);
+       if (ret != PC_OPERATION_SUCCESS) {
+               C_LOGE("Error while geting data from database");
+               return ret;
+       }
+
+       for (i = 0; i < public_dirs_cnt; ++i) {
+               C_LOGD("Allowing app %s to access public path %s", app_id, public_dirs[i]);
+               if (smack_accesses_add(smack, app_id, public_dirs[i], "rx")) {
+                       C_LOGE("app_add_rule failed");
+                       while (i < public_dirs_cnt)
+                               free(public_dirs[i++]);
+                       return PC_ERR_INVALID_OPERATION;
+               }
+               free(public_dirs[i]);
+       }
+
+       return PC_OPERATION_SUCCESS;
+}
+
 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__);
@@ -1361,6 +1393,133 @@ API int add_shared_dir_readers(const char* shared_label, const char** app_list)
        return PC_OPERATION_SUCCESS;
 }
 
+static char* smack_label_for_path(const char *app_id, const char *path)
+{
+       C_LOGD("Enter function: %s", __func__);
+       char *salt AUTO_FREE;
+       char *label;
+       char *x;
+
+       /* Prefix $1$ causes crypt() to use MD5 function */
+       if (-1 == asprintf(&salt, "$1$%s", app_id)) {
+               C_LOGE("asprintf failed");
+               return NULL;
+       }
+
+       label = crypt(path, salt);
+       if (label == NULL) {
+               C_LOGE("crypt failed");
+               return NULL;
+       }
+
+       /* crypt() output may contain slash character,
+        * which is not legal in Smack labels */
+       for (x = label; *x; ++x) {
+               if (*x == '/')
+                       *x = '%';
+       }
+
+       return label;
+}
+
+/* FIXME: remove this pragma once deprecated API is deleted */
+#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
+API int app_setup_path(const char* app_id, const char* path, app_path_type_t app_path_type, ...)
+{
+       C_LOGD("Enter function: %s", __func__);
+       va_list ap;
+
+       if (!smack_label_is_valid(app_id)) {
+               C_LOGE("Invalid app_id %s", app_id);
+               return PC_ERR_INVALID_PARAM;
+       }
+
+       switch (app_path_type) {
+       case APP_PATH_PRIVATE:
+               va_start(ap, app_path_type);
+               va_end(ap);
+               return app_label_dir(app_id, path);
+
+       case APP_PATH_GROUP_RW: {
+               const char *shared_label;
+
+               va_start(ap, app_path_type);
+               shared_label = va_arg(ap, const char *);
+               va_end(ap);
+
+               if (!smack_label_is_valid(shared_label)) {
+                       C_LOGE("Invalid shared_label %s", shared_label);
+                       return PC_ERR_INVALID_PARAM;
+               }
+
+               if (strcmp(app_id, shared_label) == 0) {
+                       C_LOGE("app_id equals shared_label");
+                       return PC_ERR_INVALID_PARAM;
+               }
+
+               return app_label_shared_dir(app_id, shared_label, path);
+       }
+
+       case APP_PATH_PUBLIC_RO: {
+               char **app_ids AUTO_FREE;
+               int app_ids_cnt = 0;
+               const char *label;
+               int i, ret;
+
+               va_start(ap, app_path_type);
+               va_end(ap);
+
+               C_LOGD("New public RO path %s", path);
+               label = smack_label_for_path(app_id, path);
+               if (label == NULL)
+                       return PC_ERR_INVALID_OPERATION;
+
+               C_LOGD("Generated label '%s' for public RO path %s", label, path);
+               ret = app_label_shared_dir(app_id, label, path);
+               if (ret != PC_OPERATION_SUCCESS)
+                       return ret;
+
+               /* FIXME: This should be in some kind of transaction/lock */
+               ret = db_add_public_dir(label);
+               if (ret != PC_OPERATION_SUCCESS)
+                       return ret;
+
+               ret = get_all_apps_ids(&app_ids, &app_ids_cnt);
+               if (ret != PC_OPERATION_SUCCESS)
+                       return ret;
+
+               for (i = 0; i < app_ids_cnt; ++i) {
+                       C_LOGD("Allowing app %s to access public path %s", app_id, label[i]);
+                       ret = app_add_rule(app_ids[i], label, "rx");
+                       if (ret != PC_OPERATION_SUCCESS) {
+                               C_LOGE("smack_accesses_new failed");
+                               while (i < app_ids_cnt)
+                                       free(app_ids[i++]);
+                               return ret;
+                       }
+                       free(app_ids[i]);
+               }
+
+               return PC_OPERATION_SUCCESS;
+       }
+
+       case APP_PATH_SETTINGS_RW:
+               va_start(ap, app_path_type);
+               va_end(ap);
+               /* TODO */
+               break;
+
+       default:
+               va_start(ap, app_path_type);
+               va_end(ap);
+               return PC_ERR_INVALID_PARAM;
+       }
+
+       return PC_OPERATION_SUCCESS;
+}
+/* FIXME: remove this pragma once deprecated API is deleted */
+#pragma GCC diagnostic warning "-Wdeprecated-declarations"
+
 API int app_add_friend(const char* app_id1, const char* app_id2)
 {
        C_LOGD("Enter function: %s", __func__);
@@ -1390,6 +1549,7 @@ API int app_install(const char* app_id)
        int ret;
        int fd AUTO_CLOSE;
        char* smack_path AUTO_FREE;
+       struct smack_accesses *smack AUTO_SMACK_FREE;
 
        if (!smack_label_is_valid(app_id))
                return PC_ERR_INVALID_PARAM;
@@ -1404,6 +1564,11 @@ API int app_install(const char* app_id)
                return PC_ERR_FILE_OPERATION;
        }
 
+       if (smack_accesses_new(&smack)) {
+               C_LOGE("smack_accesses_new failed");
+               return PC_ERR_MEM_OPERATION;
+       }
+
        ret = add_app_id_to_databse(app_id);
        if (ret != PC_OPERATION_SUCCESS ) {
                C_LOGE("Error while adding app %s to database: %s ", app_id, strerror(errno));
@@ -1416,6 +1581,22 @@ API int app_install(const char* app_id)
                return ret;
        }
 
+       ret = register_app_for_public_dirs(app_id, smack);
+       if (ret != PC_OPERATION_SUCCESS) {
+               C_LOGE("Error while adding rules for access to public dirs for app %s: %s ", app_id, strerror(errno));
+               return ret;
+       }
+
+       if (have_smack() && smack_accesses_apply(smack)) {
+               C_LOGE("smack_accesses_apply failed");
+               return PC_ERR_INVALID_OPERATION;
+       }
+
+       if (smack_accesses_save(smack, fd)) {
+               C_LOGE("smack_accesses_save failed");
+               return PC_ERR_INVALID_OPERATION;
+       }
+
        return PC_OPERATION_SUCCESS;
 }