summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJanusz Kozerski <j.kozerski@samsung.com>2014-05-20 17:28:26 +0200
committerJanusz Kozerski <j.kozerski@samsung.com>2014-10-09 16:30:06 +0200
commitc65ec844a0a87db716bc07689122706e45b4d088 (patch)
treeef11c5c44888286aabcc6c9fa81027c68d0a293c
parent0a7a657aa83eb21b7bd0b6b96643752a7dfe9ed7 (diff)
downloadima-evm-utils-c65ec844a0a87db716bc07689122706e45b4d088.tar.gz
ima-evm-utils-c65ec844a0a87db716bc07689122706e45b4d088.tar.bz2
ima-evm-utils-c65ec844a0a87db716bc07689122706e45b4d088.zip
Add ima_set_policy function.
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>
-rw-r--r--src/imaevm.h1
-rw-r--r--src/libimaevm.c161
2 files changed, 161 insertions, 1 deletions
diff --git a/src/imaevm.h b/src/imaevm.h
index b6e380e..3e60d76 100644
--- a/src/imaevm.h
+++ b/src/imaevm.h
@@ -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
diff --git a/src/libimaevm.c b/src/libimaevm.c
index 5c0d69f..8ada490 100644
--- a/src/libimaevm.c
+++ b/src/libimaevm.c
@@ -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;
+}