Re: [PATCH 15/20] ima: path based policy loading interface

From: Mimi Zohar
Date: Thu Apr 24 2014 - 17:05:10 EST


On Wed, 2014-04-23 at 16:30 +0300, Dmitry Kasatkin wrote:
> 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.

Assuming (big assumption) you're permitted to open the policy file from
the kernel, why are you verifying the signature inline based on a .sig?
Shouldn't this be a new integrity/security hook?

thanks,

Mimi

>
> Policy can be loaded like:
> echo /etc/ima/ima_policy > /sys/kernel/security/ima/policy
>
> Signed-off-by: Dmitry Kasatkin <d.kasatkin@xxxxxxxxxxx>
> ---
> 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


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/