summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/linux/fs.h1
-rw-r--r--security/integrity/ima/ima_fs.c45
2 files changed, 44 insertions, 2 deletions
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 52567252288e..e514f76db04f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -2581,6 +2581,7 @@ enum kernel_read_file_id {
READING_MODULE,
READING_KEXEC_IMAGE,
READING_KEXEC_INITRAMFS,
+ READING_POLICY,
READING_MAX_ID
};
diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c
index f355231997b4..a6c61b351f36 100644
--- a/security/integrity/ima/ima_fs.c
+++ b/security/integrity/ima/ima_fs.c
@@ -22,6 +22,7 @@
#include <linux/rculist.h>
#include <linux/rcupdate.h>
#include <linux/parser.h>
+#include <linux/vmalloc.h>
#include "ima.h"
@@ -258,6 +259,43 @@ static const struct file_operations ima_ascii_measurements_ops = {
.release = seq_release,
};
+static ssize_t ima_read_policy(char *path)
+{
+ void *data;
+ char *datap;
+ loff_t size;
+ int rc, pathlen = strlen(path);
+
+ char *p;
+
+ /* remove \n */
+ datap = path;
+ strsep(&datap, "\n");
+
+ rc = kernel_read_file_from_path(path, &data, &size, 0, READING_POLICY);
+ if (rc < 0) {
+ pr_err("Unable to open file: %s (%d)", path, rc);
+ return rc;
+ }
+
+ datap = data;
+ while (size > 0 && (p = strsep(&datap, "\n"))) {
+ pr_debug("rule: %s\n", p);
+ rc = ima_parse_add_rule(p);
+ if (rc < 0)
+ break;
+ size -= rc;
+ }
+
+ vfree(data);
+ if (rc < 0)
+ return rc;
+ else if (size)
+ return -EINVAL;
+ else
+ return pathlen;
+}
+
static ssize_t ima_write_policy(struct file *file, const char __user *buf,
size_t datalen, loff_t *ppos)
{
@@ -286,9 +324,12 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf,
result = mutex_lock_interruptible(&ima_write_mutex);
if (result < 0)
goto out_free;
- result = ima_parse_add_rule(data);
- mutex_unlock(&ima_write_mutex);
+ if (data[0] == '/')
+ result = ima_read_policy(data);
+ else
+ result = ima_parse_add_rule(data);
+ mutex_unlock(&ima_write_mutex);
out_free:
kfree(data);
out: