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 #include #include +#include #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: