Add ima_set_policy function. 50/28550/1
authorJanusz Kozerski <j.kozerski@samsung.com>
Tue, 20 May 2014 15:28:26 +0000 (17:28 +0200)
committerJanusz Kozerski <j.kozerski@samsung.com>
Thu, 9 Oct 2014 14:30:06 +0000 (16:30 +0200)
Function takes two parameters:
 char **policy - which is NULL terminated list of strings.
 char *signature - signature of the policy.

Change-Id: I8ecdf91ce4e8d122c69d2f86b18fc7202da5a053
Signed-off-by: Janusz Kozerski <j.kozerski@samsung.com>
src/imaevm.h
src/libimaevm.c

index b6e380e..3e60d76 100644 (file)
@@ -233,5 +233,6 @@ int evm_get_xattr(const char *path, char **hash);
 
 int ima_get_policy(char*** policy);
 int ima_free_policy(char **policy);
+int ima_set_policy(const char **policy, const char *policy_sig);
 
 #endif
index 5c0d69f..8ada490 100644 (file)
@@ -802,7 +802,10 @@ int sign_hash(const char *hashalgo, const unsigned char *hash, int size, const c
 #define EVM_STATE_PATH  "/sys/kernel/security/evm/evm_state"
 #define EVM_XATTR   "security.evm"
 
-#define IMA_POLICY_INTERFACE  "/sys/kernel/security/ima/policy"
+#define IMA_POLICY_INTERFACE             "/sys/kernel/security/ima/policy"
+#define IMA_POLICY_TMP_DIR               "/tmp/"
+#define IMA_POLICY_TMP_FILE_PREFIX       "ima_"
+#define IMA_POLICY_SIGNATRURE_EXTENSION  ".sig"
 
 int ima_get_state(int *state)
 {
@@ -1192,3 +1195,159 @@ int ima_free_policy(char **policy)
 
        return LIB_SUCCESS;
 }
+
+static int _ima_write_rule(int fd, const char *rule)
+{
+       int counter = 0;
+       int ret;
+
+       if (fd < 0)
+               return LIB_ERROR_SYSCALL;
+       if (!rule)
+               return LIB_SUCCESS;
+
+       int len = strlen(rule);
+
+       /* writing rule */
+       while (counter < len) {
+               ret = write(fd, &(rule[counter]), len-counter);
+               if (ret < 0) { /* Write error. Return with error code */
+                       return LIB_ERROR_SYSCALL;
+               }
+               counter += ret;
+       }
+
+       /* writing new line sign */
+       do {
+               ret = write(fd, "\n", sizeof("\n"));
+               if (ret < 0)
+                       return LIB_ERROR_SYSCALL;
+       } while (!ret);
+       if (ret != sizeof("\n"))
+               return LIB_ERROR_SYSCALL;
+
+       return LIB_SUCCESS;
+}
+
+
+int ima_set_policy(const char **policy, const char *policy_sig)
+{
+       int ret_code = LIB_SUCCESS;
+       char *policy_file_name = NULL;
+       char *sig_file_name = NULL;
+       int fd_policy = -1;
+       int fd_sig = -1;
+       int fd = -1;
+       int i, counter, len;
+       int ret;
+
+       if (!policy || !policy_sig) {
+               log_err("Error input param\n");
+               return LIB_ERROR_INPUT_PARAM;
+       }
+
+       /* Generate random filename */
+       policy_file_name = tempnam(IMA_POLICY_TMP_DIR, IMA_POLICY_TMP_FILE_PREFIX);
+       if (!policy_file_name) {
+               log_err("Cannot generate unique file name\n");
+               return LIB_ERROR_SYSCALL;
+       }
+
+       /* write policy to temporary file */
+       /* We need to be sure that we create a new file. */
+       /* No one should have any right to this file - except write for us */
+       fd_policy = open(policy_file_name, O_WRONLY | O_CREAT | O_EXCL, S_IWUSR);
+       if (fd_policy < 0) {
+               log_err("Cannot open policy temporary file\n");
+               ret_code = LIB_ERROR_SYSCALL;
+               goto out;
+       }
+
+       i = 0;
+       while (policy[i]) {
+               ret = _ima_write_rule(fd_policy, policy[i]);
+               if (ret != LIB_SUCCESS) {
+                       log_err("Error while writing policy rule to temporary file\n");
+                       ret_code = ret;
+                       goto out;
+               }
+               ++i;
+       }
+       /* We keep this file locked */
+
+       /* generate signature file name */
+       sig_file_name = malloc(sizeof(char) * (strlen(policy_file_name) + sizeof(IMA_POLICY_SIGNATRURE_EXTENSION) + 1));
+       if (!sig_file_name) {
+               ret_code = LIB_ERROR_MEMORY;
+               goto out;
+       }
+       len = strlen(policy_file_name);
+       memcpy(sig_file_name, policy_file_name, len);
+       memcpy(&(sig_file_name[len]),
+                       IMA_POLICY_SIGNATRURE_EXTENSION,
+                       sizeof(IMA_POLICY_SIGNATRURE_EXTENSION));
+       sig_file_name[len + sizeof(IMA_POLICY_SIGNATRURE_EXTENSION)] = '\0';
+
+       /* write signature to temporary file - the same conditions as for the policy file */
+       fd_sig = open(sig_file_name, O_WRONLY | O_CREAT | O_EXCL, S_IWUSR);
+       if (fd_sig < 0) {
+               log_err("Cannot open signature temporary file\n");
+               ret_code = LIB_ERROR_SYSCALL;
+               goto out;
+       }
+
+       counter = 0;
+       len = strlen(policy_sig);
+       while (counter < len) {
+               ret = write(fd_sig, &(policy_sig[counter]), len-counter);
+               if (ret < 0) {
+                       log_err("Error while writing signature to temporary file\n");
+                       ret_code = LIB_ERROR_SYSCALL;
+                       goto out;
+               }
+               counter += ret;
+       }
+
+       /* unlocked policy and signature file */
+       if (fd_policy > -1)
+               close(fd_policy);
+       if (fd_sig > -1)
+               close(fd_sig);
+
+       /* open and write to kernel interface */
+       fd = open(IMA_POLICY_INTERFACE, O_WRONLY);
+       if (fd < 0) {
+               log_err("Cannot open kernel interface\n");
+               ret_code = LIB_ERROR_SYSCALL;
+               goto out;
+       }
+
+       counter = 0;
+       len = strlen(policy_file_name);
+       while (counter < len) {
+               ret = write(fd, &(policy_file_name[counter]), len-counter);
+               if (ret < 0) {
+                       log_err("Error while writing to the kernel interface\n");
+                       ret_code = LIB_ERROR_SYSCALL;
+                       goto out;
+               }
+               counter += ret;
+       }
+
+out:
+       if (fd_policy > -1)
+               close(fd_policy);
+       if (fd_sig > -1)
+               close(fd_sig);
+       if (fd > -1)
+               close(fd);
+       if (policy_file_name) {
+               unlink(policy_file_name);
+               free(policy_file_name);
+       }
+       if (sig_file_name) {
+               unlink(sig_file_name);
+               free(sig_file_name);
+       }
+       return ret_code;
+}