New API for native/OSP installer.
authorRafal Krypa <r.krypa@samsung.com>
Tue, 8 Jan 2013 19:27:59 +0000 (20:27 +0100)
committerRafal Krypa <r.krypa@samsung.com>
Thu, 10 Jan 2013 16:52:17 +0000 (17:52 +0100)
[Issue#]       LINUXSWAP-426
[Feature]      New API for simplified SMACK management for native apps.
[Cause]        New API has been requested and designed.
[Solution]     Implement new functions: app_add_permissions, app_revoke_permissions, app_label_dir
[Verification] Only build verification, until the API is used.

Change-Id: I37110e030a71e958dda80650b376036c5dcc7051

include/privilege-control.h
src/privilege-control.c

index 5774575..e7453cf 100644 (file)
@@ -134,6 +134,45 @@ int wrt_set_data_dir(const char* widget_id, const char *path);
  */
 char* wrt_widget_id_from_socket(int sockfd);
 
+/**
+ * Grant SMACK permissions based on permissions list.
+ * It is intended to be called during app installation.
+ * It will construct SMACK rules based on permissions list, grant them
+ * and store it in a file, so they will be automatically granted on
+ * system boot.
+ * It must be called by privileged user.
+ *
+ * @param app_id application identifier
+ * @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);
+
+/**
+ * Revoke SMACK permissions from an application.
+ * This function should be called during app deinstallation.
+ * It will revoke all SMACK rules previously granted by  app_add_permissions().
+ * It will also remove a rules file from disk.
+ * It must be called by privileged user.
+ *
+ * @param app_id application identifier
+ * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
+ */
+int app_revoke_permissions(const char* app_id);
+
+/**
+ * Recursively set SMACK labels for an application directory.
+ * This function should be called once during app installation.
+ * Results will be persistent on the file system.
+ * It must be called by privileged user.
+ *
+ * @param app_id application identifier
+ * @param path directory path
+ * @return PC_OPERATION_SUCCESS on success, PC_ERR_* on error
+ */
+int app_label_dir(const char* app_id, const char* path);
+
+
 #ifdef __cplusplus
 }
 #endif // __cplusplus
index 8b4c844..17ed6fe 100644 (file)
 #include <errno.h>
 #include <math.h>
 #include <ctype.h>
+#include <fcntl.h>
 #include <sys/time.h>
 #include <sys/stat.h>
+#include <sys/file.h>
 #include <sys/smack.h>
 
 #include "privilege-control.h"
@@ -51,6 +53,8 @@
 #define APP_GROUP_PATH TOSTRING(SHAREDIR) "/app_group_list"
 #define DEV_GROUP_PATH TOSTRING(SHAREDIR) "/dev_group_list"
 
+#define SMACK_RULES_DIR  "/etc/smack/accesses.d/"
+
 #define SMACK_APP_LABEL         "~APP~"
 #define SMACK_WRT_LABEL_PREFIX  "wrt_widget_"
 #define SMACK_SRC_FILE_SUFFIX   "_src_file"
@@ -491,7 +495,6 @@ out:
        return ret;
 }
 
-#ifdef WRT_SMACK_ENABLED
 static int dir_set_smack_r(const char *path, const char* label,
                enum smack_label_type type, mode_t type_mask)
 {
@@ -525,7 +528,6 @@ out:
                fts_close(fts);
        return ret;
 }
-#endif // WRT_SMACK_ENABLED
 
 API int wrt_set_src_dir(const char* widget_id, const char *path)
 {
@@ -718,3 +720,142 @@ API char* wrt_widget_id_from_socket(int sockfd)
        free(smack_label);
        return widget_id;
 }
+
+API int app_add_permissions(const char* app_id, const char** perm_list)
+{
+       char* path = NULL;
+       int i, ret;
+       int fd = -1;
+       struct smack_accesses *smack = NULL;
+
+#ifdef SMACK_ENABLED
+       if (asprintf(&path, SMACK_RULES_DIR "/%s", app_id) == -1) {
+               ret = PC_ERR_MEM_OPERATION;
+               goto out;
+       }
+
+       if (smack_accesses_new(&smack)) {
+               ret = PC_ERR_MEM_OPERATION;
+               goto out;
+       }
+
+       fd = open(path, O_CREAT, O_RDWR);
+       if (fd == -1) {
+               ret = PC_ERR_FILE_OPERATION;
+               goto out;
+       }
+
+       if (flock(fd, LOCK_EX)) {
+               ret = PC_ERR_INVALID_OPERATION;
+               goto out;
+       }
+
+       if (smack_accesses_add_from_file(smack, fd)) {
+               ret = PC_ERR_INVALID_OPERATION;
+               goto out;
+       }
+
+       /* Rewind the file */
+       if (lseek(fd, 0, SEEK_SET) == -1) {
+               ret = PC_ERR_FILE_OPERATION;
+               goto out;
+       }
+
+       for (i = 0; perm_list[i] != NULL; ++i) {
+               ret = perm_to_smack(smack, app_id, perm_list[i]);
+               if (ret != PC_OPERATION_SUCCESS)
+                       goto out;
+       }
+
+       if (smack_accesses_apply(smack)) {
+               ret = PC_ERR_INVALID_OPERATION;
+               goto out;
+       }
+
+       if (smack_accesses_save(smack, fd)) {
+               ret = PC_ERR_FILE_OPERATION;
+               goto out;
+       }
+#endif
+
+       ret = PC_OPERATION_SUCCESS;
+out:
+       if (fd != -1)
+               close(fd);
+       if (smack != NULL)
+               smack_accesses_free(smack);
+       free(path);
+
+       return ret;
+}
+
+API int app_revoke_permissions(const char* app_id)
+{
+       char* path = NULL;
+       int ret;
+       int fd = -1;
+       struct smack_accesses *smack = NULL;
+
+#ifdef SMACK_ENABLED
+       if (asprintf(&path, SMACK_RULES_DIR "/%s", app_id) == -1) {
+               ret = PC_ERR_MEM_OPERATION;
+               goto out;
+       }
+
+       if (smack_accesses_new(&smack)) {
+               ret = PC_ERR_MEM_OPERATION;
+               goto out;
+       }
+
+       fd = open(path, O_RDONLY);
+       if (fd == -1) {
+               ret = PC_ERR_FILE_OPERATION;
+               goto out;
+       }
+
+       if (flock(fd, LOCK_EX | LOCK_NB)) {
+               /* Non-blocking lock request on a file failed. */
+               ret = PC_ERR_INVALID_OPERATION;
+               goto out;
+       }
+
+       if (unlink(path)) {
+               ret = PC_ERR_INVALID_OPERATION;
+               goto out;
+       }
+
+       if (smack_accesses_add_from_file(smack, fd)) {
+               ret = PC_ERR_INVALID_OPERATION;
+               goto out;
+       }
+
+       if (smack_accesses_clear(smack)) {
+               ret = PC_ERR_INVALID_OPERATION;
+               goto out;
+       }
+
+       if (smack_revoke_subject(app_id)) {
+               ret = PC_ERR_INVALID_OPERATION;
+               goto out;
+       }
+#endif
+
+       ret = PC_OPERATION_SUCCESS;
+out:
+       if (fd != -1)
+               close(fd);
+       if (smack != NULL)
+               smack_accesses_free(smack);
+       free(path);
+
+       return ret;
+}
+
+API int app_label_dir(const char* app_id, const char* path)
+{
+#ifdef SMACK_ENABLED
+       return dir_set_smack_r(path, app_id, SMACK_LABEL_ACCESS, ~0);
+#else
+       return PC_OPERATION_SUCCESS;
+#endif
+}