Currently policy is loaded by writing policy content to '<securityfs>/ima/policy' file.
This patch extends policy loading meachanism with possibility to load signed policy using a path to the policy. Policy signature must be available in the <policy>.sig file. Policy can be loaded like: echo /etc/ima/ima_policy > /sys/kernel/security/ima/policy Signed-off-by: Dmitry Kasatkin <[email protected]> --- security/integrity/ima/Kconfig | 13 +++++++ security/integrity/ima/ima.h | 9 +++++ security/integrity/ima/ima_fs.c | 2 +- security/integrity/ima/ima_policy.c | 74 +++++++++++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+), 1 deletion(-) diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig index 5474c47..465cef4 100644 --- a/security/integrity/ima/Kconfig +++ b/security/integrity/ima/Kconfig @@ -140,3 +140,16 @@ config IMA_LOAD_X509 help This option enables X509 certificate loading from the kernel to the '_ima' trusted keyring. + +config IMA_POLICY_LOADER + bool "Path based policy loading interface" + depends on IMA_TRUSTED_KEYRING + default n + help + This option enables path based signed policy loading interface. + Policy signature must be provided in the <policy>.sig file + along with the policy. When this option is enabled, kernel + tries to load default policy from /etc/ima_policy. + + Loading policy is like: + echo /etc/ima/ima_policy > /sys/kernel/security/ima/policy diff --git a/security/integrity/ima/ima.h b/security/integrity/ima/ima.h index 3b90b60..f2722bb 100644 --- a/security/integrity/ima/ima.h +++ b/security/integrity/ima/ima.h @@ -170,6 +170,15 @@ bool ima_default_policy(void); ssize_t ima_parse_add_rule(char *); void ima_delete_rules(void); +#ifdef CONFIG_IMA_POLICY_LOADER +ssize_t ima_read_policy(char *path); +#else +static inline ssize_t ima_read_policy(char *data) +{ + return ima_parse_add_rule(data); +} +#endif + /* Appraise integrity measurements */ #define IMA_APPRAISE_ENFORCE 0x01 #define IMA_APPRAISE_FIX 0x02 diff --git a/security/integrity/ima/ima_fs.c b/security/integrity/ima/ima_fs.c index 34ae5f2..bde7a0e 100644 --- a/security/integrity/ima/ima_fs.c +++ b/security/integrity/ima/ima_fs.c @@ -273,7 +273,7 @@ static ssize_t ima_write_policy(struct file *file, const char __user *buf, if (copy_from_user(data, buf, datalen)) goto out; - result = ima_parse_add_rule(data); + result = ima_read_policy(data); out: if (result < 0) valid_policy = 0; diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c index b24e7d1..c6da801 100644 --- a/security/integrity/ima/ima_policy.c +++ b/security/integrity/ima/ima_policy.c @@ -17,6 +17,9 @@ #include <linux/parser.h> #include <linux/slab.h> #include <linux/genhd.h> +#ifdef CONFIG_IMA_POLICY_LOADER +#include <linux/file.h> +#endif #include "ima.h" @@ -747,3 +750,74 @@ void ima_delete_rules(void) } mutex_unlock(&ima_rules_mutex); } + +#ifdef CONFIG_IMA_POLICY_LOADER + +ssize_t ima_read_policy(char *path) +{ + char *data, *datap, *sig; + int rc, psize, pathlen = strlen(path); + char *p, *sigpath; + struct { + struct ima_digest_data hdr; + char digest[IMA_MAX_DIGEST_SIZE]; + } hash; + + if (path[0] != '/') + return ima_parse_add_rule(path); + + /* remove \n */ + datap = path; + strsep(&datap, "\n"); + + /* we always want signature? */ + sigpath = __getname(); + if (!sigpath) + return -ENOMEM; + + rc = integrity_read_file(path, &data); + if (rc < 0) + goto free_path; + + psize = rc; + datap = data; + + sprintf(sigpath, "%s.sig", path); + /* we always want signature? */ + rc = integrity_read_file(sigpath, &sig); + if (rc < 0) + goto free_data; + + hash.hdr.algo = ima_hash_algo; + ima_get_hash_algo((void *)sig, rc, &hash.hdr); + ima_calc_buffer_hash(data, psize, &hash.hdr); + rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA, + (const char *)sig, rc, + hash.hdr.digest, hash.hdr.length); + if (rc) { + pr_err("integrity_digsig_verify() = %d\n", rc); + goto free_sig; + } + + while (psize > 0 && (p = strsep(&datap, "\n"))) { + pr_debug("rule: %s\n", p); + rc = ima_parse_add_rule(p); + if (rc < 0) + break; + psize -= rc; + } +free_sig: + kfree(sig); +free_data: + kfree(data); +free_path: + __putname(sigpath); + if (rc < 0) + return rc; + else if (psize) + return -EINVAL; + else + return pathlen; +} + +#endif -- 1.8.3.2 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/

