2014-07-15 12:56:30

by Dmitry Kasatkin

[permalink] [raw]
Subject: [PATCH v1 0/4] ima: require signed user-space initialization

Currently secure IMA/EVM initialization has to be done from the initramfs,
embedded in the signed kernel image. Many systems do not want to use
initramfs or usage of embedded initramfs makes it difficult to have
multi-target kernels.

This is a very simple patchset which makes it possible to perform secure
initialization by requiring initial user-space to be signed.

It does it by:
- introducing IMA public keys loading hook
- loading IMA trusted public key into .ima trusted keyring
- making default IMA appraisal policy to require everything to be signed

When builtin initramfs is not in use, keys cannot be read from initcalls,
because root filesystem is not yet mounted. In order to read keys before
executing init process, ima_prepare_keys() hook is introduced. Reading
public keys from the kernel is justified because signature verification
key is needed in order to verify anything else which is read from the
file system. Public keys are X509 certificates and itself signed by the
trusted key from the .system keyring. Kernel BIG KEYS support is an example
of reading keys directly by the kernel.

CONFIG_IMA_APPRAISE_SIGNED_INIT kernel option is provided to make the IMA
default appraisal policy to required signature validation. Signed init
process need to initialize EVM key and load appropriate IMA policy which
would not require everything to be signed.

Unless real '/sbin/init' is signed, a simple and practical way is to place
all signed programs, libraries, scripts and configuration files under
dedicated directory, for example '/ima', and run signed init process by
providing a kernel command line parameter 'init=/ima/init'

-Dmitry

Dmitry Kasatkin (4):
ima: provide hook to load IMA keys when rootfs is ready
integrity: provide file reading API
integrity: provide x509 certificate loading from the kernel
ima: require signed user-space initialization

include/linux/ima.h | 9 +++++
init/main.c | 6 ++-
security/integrity/Kconfig | 7 ++++
security/integrity/digsig.c | 78 +++++++++++++++++++++++++++++++++++++
security/integrity/ima/Kconfig | 15 +++++++
security/integrity/ima/ima_init.c | 17 ++++++++
security/integrity/ima/ima_policy.c | 5 +++
security/integrity/integrity.h | 11 +++++-
8 files changed, 146 insertions(+), 2 deletions(-)

--
1.9.1


2014-07-15 12:56:44

by Dmitry Kasatkin

[permalink] [raw]
Subject: [PATCH v1 3/4] integrity: provide x509 certificate loading from the kernel

Provide API to load x509 certificates from the kernel into the
integrity kernel keyrings.

Signed-off-by: Dmitry Kasatkin <[email protected]>
---
security/integrity/Kconfig | 4 ++++
security/integrity/digsig.c | 37 +++++++++++++++++++++++++++++++++++++
security/integrity/integrity.h | 9 +++++++++
3 files changed, 50 insertions(+)

diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index 1f000c4..63766fb 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig
@@ -53,6 +53,10 @@ config INTEGRITY_AUDIT
config INTEGRITY_FILE_READ
def_bool n

+config INTEGRITY_LOAD_X509
+ select INTEGRITY_FILE_READ
+ def_bool n
+
source security/integrity/ima/Kconfig
source security/integrity/evm/Kconfig

diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
index 85d6662..63f66cc 100644
--- a/security/integrity/digsig.c
+++ b/security/integrity/digsig.c
@@ -104,6 +104,43 @@ out:
}
#endif

+#ifdef CONFIG_INTEGRITY_LOAD_X509
+int integrity_load_x509(const unsigned int id, char *path)
+{
+ key_ref_t key;
+ char *data;
+ int rc;
+
+ if (!keyring[id])
+ return -EINVAL;
+
+ rc = integrity_read_file(path, &data);
+ if (rc < 0)
+ return rc;
+
+ key = key_create_or_update(make_key_ref(keyring[id], 1),
+ "asymmetric",
+ NULL,
+ data,
+ rc,
+ ((KEY_POS_ALL & ~KEY_POS_SETATTR) |
+ KEY_USR_VIEW | KEY_USR_READ),
+ KEY_ALLOC_NOT_IN_QUOTA |
+ KEY_ALLOC_TRUSTED);
+ if (IS_ERR(key)) {
+ rc = PTR_ERR(key);
+ pr_err("Problem loading X.509 certificate (%d): %s\n",
+ rc, path);
+ } else {
+ pr_notice("Loaded X.509 cert '%s': %s\n",
+ key_ref_to_ptr(key)->description, path);
+ key_ref_put(key);
+ }
+ kfree(data);
+ return 0;
+}
+#endif
+
int integrity_init_keyring(const unsigned int id)
{
const struct cred *cred = current_cred();
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index f77de68..a4de3e3 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -158,6 +158,15 @@ static inline int asymmetric_verify(struct key *keyring, const char *sig,
}
#endif

+#ifdef CONFIG_INTEGRITY_LOAD_X509
+int integrity_load_x509(const unsigned int id, char *path);
+#else
+static inline int integrity_load_x509(const unsigned int id, char *path)
+{
+ return 0;
+}
+#endif
+
#ifdef CONFIG_INTEGRITY_AUDIT
/* declarations */
void integrity_audit_msg(int audit_msgno, struct inode *inode,
--
1.9.1

2014-07-15 12:56:26

by Dmitry Kasatkin

[permalink] [raw]
Subject: [PATCH v1 4/4] ima: require signed user-space initialization

This patch provides kernel parameter CONFIG_IMA_APPRAISE_SIGNED_INIT
to force initial user-space verification using signatures.
This is useful, when EVM key is not initalized yet and we want securely
initialize integrity or any other functionality. It implements
ima_preapre_keys() hook to load X509 certificate into the .ima trusted
kernel keyring from root filesystem. It forces embedded policy to
check signature. Signed initialization script can initialize EVM key,
update the IMA policy and change requirement of everything to be signed.

Signed-off-by: Dmitry Kasatkin <[email protected]>
---
security/integrity/ima/Kconfig | 15 +++++++++++++++
security/integrity/ima/ima_init.c | 17 +++++++++++++++++
security/integrity/ima/ima_policy.c | 5 +++++
3 files changed, 37 insertions(+)

diff --git a/security/integrity/ima/Kconfig b/security/integrity/ima/Kconfig
index 2477d1e..294ee2f 100644
--- a/security/integrity/ima/Kconfig
+++ b/security/integrity/ima/Kconfig
@@ -132,3 +132,18 @@ config IMA_TRUSTED_KEYRING
help
This option requires that all keys added to the .ima
keyring be signed by a key on the system trusted keyring.
+
+config IMA_APPRAISE_SIGNED_INIT
+ bool "Require signed user-space initialization"
+ depends on IMA_TRUSTED_KEYRING
+ select INTEGRITY_LOAD_X509
+ default n
+ help
+ This option requires user-space init to be signed.
+
+config IMA_X509_PATH
+ string "IMA X509 certificate path"
+ depends on IMA_APPRAISE_SIGNED_INIT
+ default "/init/ima/x509_ima.der"
+ help
+ This option defines IMA X509 certificate path.
diff --git a/security/integrity/ima/ima_init.c b/security/integrity/ima/ima_init.c
index 8cf0f39..120b041 100644
--- a/security/integrity/ima/ima_init.c
+++ b/security/integrity/ima/ima_init.c
@@ -24,6 +24,12 @@
#include <crypto/hash_info.h>
#include "ima.h"

+#ifdef CONFIG_IMA_X509_PATH
+#define IMA_X509_PATH CONFIG_IMA_X509_PATH
+#else
+#define IMA_X509_PATH "/init/ima/x509_ima.der"
+#endif
+
/* name for boot aggregate entry */
static const char *boot_aggregate_name = "boot_aggregate";
int ima_used_chip;
@@ -85,6 +91,17 @@ err_out:
audit_cause, result, 0);
}

+void __init ima_prepare_keys(void)
+{
+ if (ima_initialized) {
+ /* disable IMA to load the key */
+ /* hackish for now */
+ ima_initialized = 0;
+ integrity_load_x509(INTEGRITY_KEYRING_IMA, IMA_X509_PATH);
+ ima_initialized = 1;
+ }
+}
+
int __init ima_init(void)
{
u8 pcr_i[TPM_DIGEST_SIZE];
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index b9716d9..96e885f 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -97,7 +97,12 @@ static struct ima_rule_entry default_appraise_rules[] = {
{.action = DONT_APPRAISE, .fsmagic = SECURITYFS_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_APPRAISE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_APPRAISE, .fsmagic = CGROUP_SUPER_MAGIC, .flags = IMA_FSMAGIC},
+#ifndef CONFIG_IMA_APPRAISE_SIGNED_INIT
{.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .flags = IMA_FOWNER},
+#else
+ /* force signature */
+ {.action = APPRAISE, .fowner = GLOBAL_ROOT_UID, .flags = IMA_FOWNER | IMA_DIGSIG_REQUIRED},
+#endif
};

static LIST_HEAD(ima_default_rules);
--
1.9.1

2014-07-15 12:56:22

by Dmitry Kasatkin

[permalink] [raw]
Subject: [PATCH v1 2/4] integrity: provide file reading API

Signed-off-by: Dmitry Kasatkin <[email protected]>
---
security/integrity/Kconfig | 3 +++
security/integrity/digsig.c | 41 +++++++++++++++++++++++++++++++++++++++++
security/integrity/integrity.h | 2 +-
3 files changed, 45 insertions(+), 1 deletion(-)

diff --git a/security/integrity/Kconfig b/security/integrity/Kconfig
index 463219b..1f000c4 100644
--- a/security/integrity/Kconfig
+++ b/security/integrity/Kconfig
@@ -50,6 +50,9 @@ config INTEGRITY_AUDIT
be enabled by specifying 'integrity_audit=1' on the kernel
command line.

+config INTEGRITY_FILE_READ
+ def_bool n
+
source security/integrity/ima/Kconfig
source security/integrity/evm/Kconfig

diff --git a/security/integrity/digsig.c b/security/integrity/digsig.c
index 8d4fbff..85d6662 100644
--- a/security/integrity/digsig.c
+++ b/security/integrity/digsig.c
@@ -18,6 +18,8 @@
#include <linux/cred.h>
#include <linux/key-type.h>
#include <linux/digsig.h>
+#include <linux/slab.h>
+#include <linux/file.h>

#include "integrity.h"

@@ -63,6 +65,45 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
return -EOPNOTSUPP;
}

+#ifdef CONFIG_INTEGRITY_FILE_READ
+int integrity_read_file(const char *path, char **data)
+{
+ struct file *file;
+ loff_t size;
+ char *buf;
+ int rc = -EINVAL;
+
+ file = filp_open(path, O_RDONLY, 0);
+ if (IS_ERR(file)) {
+ rc = PTR_ERR(file);
+ pr_err("Unable to open file: %s (%d)", path, rc);
+ return rc;
+ }
+
+ size = i_size_read(file_inode(file));
+ if (size <= 0)
+ goto out;
+
+ buf = kmalloc(size, GFP_KERNEL);
+ if (!buf) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ /* should be ima_kernel_read */
+ rc = kernel_read(file, 0, buf, size);
+ if (rc < 0)
+ kfree(buf);
+ else if (rc != size)
+ rc = -EIO;
+ else
+ *data = buf;
+out:
+ fput(file);
+ return rc;
+}
+#endif
+
int integrity_init_keyring(const unsigned int id)
{
const struct cred *cred = current_cred();
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index 7656d47..f77de68 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -130,7 +130,7 @@ struct integrity_iint_cache *integrity_iint_find(struct inode *inode);

int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
const char *digest, int digestlen);
-
+int integrity_read_file(const char *path, char **data);
int integrity_init_keyring(const unsigned int id);
#else

--
1.9.1

2014-07-15 12:58:56

by Dmitry Kasatkin

[permalink] [raw]
Subject: [PATCH v1 1/4] ima: provide hook to load IMA keys when rootfs is ready

Keys can only be loaded when rootfs is mounted. Initcalls
are not suitable for that. Provide a special hook.

Signed-off-by: Dmitry Kasatkin <[email protected]>
---
include/linux/ima.h | 9 +++++++++
init/main.c | 6 +++++-
2 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/include/linux/ima.h b/include/linux/ima.h
index 23a87a4..b617c1a 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -73,4 +73,13 @@ static inline int ima_inode_removexattr(struct dentry *dentry,
return 0;
}
#endif /* CONFIG_IMA_APPRAISE */
+
+#ifdef CONFIG_IMA_APPRAISE_SIGNED_INIT
+extern void __init ima_prepare_keys(void);
+#else
+static inline void ima_prepare_keys(void)
+{
+}
+#endif
+
#endif /* _LINUX_IMA_H */
diff --git a/init/main.c b/init/main.c
index e8ae1fe..b24cfaa 100644
--- a/init/main.c
+++ b/init/main.c
@@ -78,6 +78,7 @@
#include <linux/context_tracking.h>
#include <linux/random.h>
#include <linux/list.h>
+#include <linux/ima.h>

#include <asm/io.h>
#include <asm/bugs.h>
@@ -1028,6 +1029,9 @@ static noinline void __init kernel_init_freeable(void)
* initmem segments and start the user-mode stuff..
*/

- /* rootfs is available now, try loading default modules */
+ /* rootfs is available now */
+ /* try loading public keys */
+ ima_prepare_keys();
+ /* try loading default modules */
load_default_modules();
}
--
1.9.1

2014-07-15 21:33:23

by Andrew Morton

[permalink] [raw]
Subject: Re: [PATCH v1 0/4] ima: require signed user-space initialization

On Tue, 15 Jul 2014 15:54:19 +0300 Dmitry Kasatkin <[email protected]> wrote:

> Currently secure IMA/EVM initialization has to be done from the initramfs,
> embedded in the signed kernel image. Many systems do not want to use
> initramfs or usage of embedded initramfs makes it difficult to have
> multi-target kernels.
>
> This is a very simple patchset which makes it possible to perform secure
> initialization by requiring initial user-space to be signed.
>
> It does it by:
> - introducing IMA public keys loading hook
> - loading IMA trusted public key into .ima trusted keyring
> - making default IMA appraisal policy to require everything to be signed
>
> When builtin initramfs is not in use, keys cannot be read from initcalls,
> because root filesystem is not yet mounted. In order to read keys before
> executing init process, ima_prepare_keys() hook is introduced. Reading
> public keys from the kernel is justified because signature verification
> key is needed in order to verify anything else which is read from the
> file system. Public keys are X509 certificates and itself signed by the
> trusted key from the .system keyring. Kernel BIG KEYS support is an example
> of reading keys directly by the kernel.
>
> CONFIG_IMA_APPRAISE_SIGNED_INIT kernel option is provided to make the IMA
> default appraisal policy to required signature validation. Signed init
> process need to initialize EVM key and load appropriate IMA policy which
> would not require everything to be signed.
>
> Unless real '/sbin/init' is signed, a simple and practical way is to place
> all signed programs, libraries, scripts and configuration files under
> dedicated directory, for example '/ima', and run signed init process by
> providing a kernel command line parameter 'init=/ima/init'

The kernel may already have loaded kernel modules before it gets around
to mounting rootfs and running /sbin/init. How does that fit into the
overall signing scheme? And how did /sbin/modprobe get its signature
checked?


The proposed interface and implementation look reasonable to me.
Opening and reading a file from the root fs is a bit unusual, but we
already do something similar with "/sbin/init" and the reasoning here
is similar.

The only alternative I can immediately think of is to bundle the public
keys into a kernel module and load them into the kernel that way but

- if/when we implement module signing, we have a chicken-and-egg problem

- doing it via a kernel module seems a bit fake - a bit of trickery
to reduce code duplication. Better to do it explicitly.


One thing I'm wondering: integrity_read_file() is a very simple
open-file-and-slurp-it-into-memory. Have you checked whether other
code sites are doing the same thing? Perhaps integrity_read_file()
should be in ./lib/ and other callsites can be converted to share it?

That comment in integrity_read_file() is completely useless :(

2014-07-16 20:26:52

by Dmitry Kasatkin

[permalink] [raw]
Subject: Re: [PATCH v1 0/4] ima: require signed user-space initialization

Hello,


On Wed, Jul 16, 2014 at 12:33 AM, Andrew Morton
<[email protected]> wrote:
> On Tue, 15 Jul 2014 15:54:19 +0300 Dmitry Kasatkin <[email protected]> wrote:
>
>> Currently secure IMA/EVM initialization has to be done from the initramfs,
>> embedded in the signed kernel image. Many systems do not want to use
>> initramfs or usage of embedded initramfs makes it difficult to have
>> multi-target kernels.
>>
>> This is a very simple patchset which makes it possible to perform secure
>> initialization by requiring initial user-space to be signed.
>>
>> It does it by:
>> - introducing IMA public keys loading hook
>> - loading IMA trusted public key into .ima trusted keyring
>> - making default IMA appraisal policy to require everything to be signed
>>
>> When builtin initramfs is not in use, keys cannot be read from initcalls,
>> because root filesystem is not yet mounted. In order to read keys before
>> executing init process, ima_prepare_keys() hook is introduced. Reading
>> public keys from the kernel is justified because signature verification
>> key is needed in order to verify anything else which is read from the
>> file system. Public keys are X509 certificates and itself signed by the
>> trusted key from the .system keyring. Kernel BIG KEYS support is an example
>> of reading keys directly by the kernel.
>>
>> CONFIG_IMA_APPRAISE_SIGNED_INIT kernel option is provided to make the IMA
>> default appraisal policy to required signature validation. Signed init
>> process need to initialize EVM key and load appropriate IMA policy which
>> would not require everything to be signed.
>>
>> Unless real '/sbin/init' is signed, a simple and practical way is to place
>> all signed programs, libraries, scripts and configuration files under
>> dedicated directory, for example '/ima', and run signed init process by
>> providing a kernel command line parameter 'init=/ima/init'
>
> The kernel may already have loaded kernel modules before it gets around
> to mounting rootfs and running /sbin/init. How does that fit into the
> overall signing scheme? And how did /sbin/modprobe get its signature
> checked?
>
>

If kernel embedded initramfs is in use then it is signed together with kernel,
and this functionality is not needed and no need to enable it with
kernel configuration.

As it is IMA extensions and it is entirely based on IMA functionality
it requires
extended attribute support.

If externally loaded initramfs is used, then that one uses cpio based
archive that
does not support extended attributes and thus external initramfs cannot be used
for secure initialization.

This functionality is targeted to be used without initramfs on normal
filesystems
supporting xattrs. In such case, modprobe cannot be loaded before
rootfs is mounted.
Any filesystems and block device drivers obviously need to be embedded
into the kernel.
In the place where ima_prepare_keys() hooks is called, we have

ima_prepare_keys();
load_default_modules();

So we load keys after mounting rootfs and before calling load_default_modules().
So if anything useful kernel loads with load_default_modules, will be
loaded after
IMA key is available and thus modprobe will be verified.


> The proposed interface and implementation look reasonable to me.
> Opening and reading a file from the root fs is a bit unusual, but we
> already do something similar with "/sbin/init" and the reasoning here
> is similar.
>
> The only alternative I can immediately think of is to bundle the public
> keys into a kernel module and load them into the kernel that way but
>
> - if/when we implement module signing, we have a chicken-and-egg problem
>
> - doing it via a kernel module seems a bit fake - a bit of trickery
> to reduce code duplication. Better to do it explicitly.
>

This was the idea. Kernel has embedded certificate signing key on the
.system keyring. Filesystem image/package can come with own signing key
and that one is loaded and verified by existing KEY infrastructure.
Entire signed init code can come as rpm or deb package with its own key.
That is benefit of loading key.

>
> One thing I'm wondering: integrity_read_file() is a very simple
> open-file-and-slurp-it-into-memory. Have you checked whether other
> code sites are doing the same thing? Perhaps integrity_read_file()
> should be in ./lib/ and other callsites can be converted to share it?
>

Yes, indeed, I saw. For code cleanness for posting I thought to have
it all belonging to integrity subsystem. I can make it as additional patch
for the next post to show how to "refactor" common code and if needed to
squash it.

> That comment in integrity_read_file() is completely useless :(
>
>

Ough, you mean /* should be ima_kernel_read */ ??

The thing is that ima_kernel_read which is used to read file for hashing
does not honor security checks.. Indeed, kernel must read it regardless
any obstacles. The same is here with keys...
I worked on this patch in parallel I introduced ima_kernel_read.

So if ima_kernel_read would be used, then we cannot share integrity_read_file
as they other code uses kernel_read and honors security checks.

We had discussion with Mimi on list to move and rename ima_kernel_read
as "kernel_read_nosec" or something like that. It was once suggested
by Eric Biederman.
So then we could have such "helper" function.

Let us think about it.

Thank you for commenting.

-Dmitry

2014-07-23 19:08:58

by Mimi Zohar

[permalink] [raw]
Subject: Re: [PATCH v1 0/4] ima: require signed user-space initialization

On Wed, 2014-07-16 at 23:26 +0300, Dmitry Kasatkin wrote:
> Hello,
>
>
> On Wed, Jul 16, 2014 at 12:33 AM, Andrew Morton
> <[email protected]> wrote:
> > On Tue, 15 Jul 2014 15:54:19 +0300 Dmitry Kasatkin <[email protected]> wrote:
> >
> >> Currently secure IMA/EVM initialization has to be done from the initramfs,
> >> embedded in the signed kernel image. Many systems do not want to use
> >> initramfs or usage of embedded initramfs makes it difficult to have
> >> multi-target kernels.
> >>
> >> This is a very simple patchset which makes it possible to perform secure
> >> initialization by requiring initial user-space to be signed.
> >>
> >> It does it by:
> >> - introducing IMA public keys loading hook
> >> - loading IMA trusted public key into .ima trusted keyring
> >> - making default IMA appraisal policy to require everything to be signed
> >>
> >> When builtin initramfs is not in use, keys cannot be read from initcalls,
> >> because root filesystem is not yet mounted. In order to read keys before
> >> executing init process, ima_prepare_keys() hook is introduced. Reading
> >> public keys from the kernel is justified because signature verification
> >> key is needed in order to verify anything else which is read from the
> >> file system. Public keys are X509 certificates and itself signed by the
> >> trusted key from the .system keyring. Kernel BIG KEYS support is an example
> >> of reading keys directly by the kernel.
> >>
> >> CONFIG_IMA_APPRAISE_SIGNED_INIT kernel option is provided to make the IMA
> >> default appraisal policy to required signature validation. Signed init
> >> process need to initialize EVM key and load appropriate IMA policy which
> >> would not require everything to be signed.
> >>
> >> Unless real '/sbin/init' is signed, a simple and practical way is to place
> >> all signed programs, libraries, scripts and configuration files under
> >> dedicated directory, for example '/ima', and run signed init process by
> >> providing a kernel command line parameter 'init=/ima/init'
> >
> > The kernel may already have loaded kernel modules before it gets around
> > to mounting rootfs and running /sbin/init. How does that fit into the
> > overall signing scheme? And how did /sbin/modprobe get its signature
> > checked?
> >
> >
>
> If kernel embedded initramfs is in use then it is signed together with kernel,
> and this functionality is not needed and no need to enable it with
> kernel configuration.
>
> As it is IMA extensions and it is entirely based on IMA functionality
> it requires extended attribute support.
>
> If externally loaded initramfs is used, then that one uses cpio based
> archive that does not support extended attributes and thus external
> initramfs cannot be used for secure initialization.

Right, but GNU tar version 1.27.1 supports Posix.1 (ustar) format, which
has xattr support. GNU CPIO supports the Posix.1 tar format. The
question is whether CPIO supports the included xattrs.

> This functionality is targeted to be used without initramfs on normal
> filesystems supporting xattrs. In such case, modprobe cannot be loaded before
> rootfs is mounted. Any filesystems and block device drivers obviously
> need to be embedded into the kernel. In the place where
> ima_prepare_keys() hooks is called, we have
>
> ima_prepare_keys();
> load_default_modules();
>
> So we load keys after mounting rootfs and before calling load_default_modules().
> So if anything useful kernel loads with load_default_modules, will be
> loaded after IMA key is available and thus modprobe will be verified.
>
>
> > The proposed interface and implementation look reasonable to me.
> > Opening and reading a file from the root fs is a bit unusual, but we
> > already do something similar with "/sbin/init" and the reasoning here
> > is similar.
> >
> > The only alternative I can immediately think of is to bundle the public
> > keys into a kernel module and load them into the kernel that way but
> >
> > - if/when we implement module signing, we have a chicken-and-egg problem
> >
> > - doing it via a kernel module seems a bit fake - a bit of trickery
> > to reduce code duplication. Better to do it explicitly.
> >
>
> This was the idea. Kernel has embedded certificate signing key on the
> .system keyring. Filesystem image/package can come with own signing key
> and that one is loaded and verified by existing KEY infrastructure.
> Entire signed init code can come as rpm or deb package with its own key.
> That is benefit of loading key.

Ok, this type of solution addresses the concerns of devices, but we also
need a viable solution for systems with an initramfs.

Mimi

2014-07-29 21:37:09

by Dmitry Kasatkin

[permalink] [raw]
Subject: Re: [PATCH v1 0/4] ima: require signed user-space initialization

On Wed, Jul 23, 2014 at 9:08 PM, Mimi Zohar <[email protected]> wrote:
> On Wed, 2014-07-16 at 23:26 +0300, Dmitry Kasatkin wrote:
>> Hello,
>>
>>
>> On Wed, Jul 16, 2014 at 12:33 AM, Andrew Morton
>> <[email protected]> wrote:
>> > On Tue, 15 Jul 2014 15:54:19 +0300 Dmitry Kasatkin <[email protected]> wrote:
>> >
>> >> Currently secure IMA/EVM initialization has to be done from the initramfs,
>> >> embedded in the signed kernel image. Many systems do not want to use
>> >> initramfs or usage of embedded initramfs makes it difficult to have
>> >> multi-target kernels.
>> >>
>> >> This is a very simple patchset which makes it possible to perform secure
>> >> initialization by requiring initial user-space to be signed.
>> >>
>> >> It does it by:
>> >> - introducing IMA public keys loading hook
>> >> - loading IMA trusted public key into .ima trusted keyring
>> >> - making default IMA appraisal policy to require everything to be signed
>> >>
>> >> When builtin initramfs is not in use, keys cannot be read from initcalls,
>> >> because root filesystem is not yet mounted. In order to read keys before
>> >> executing init process, ima_prepare_keys() hook is introduced. Reading
>> >> public keys from the kernel is justified because signature verification
>> >> key is needed in order to verify anything else which is read from the
>> >> file system. Public keys are X509 certificates and itself signed by the
>> >> trusted key from the .system keyring. Kernel BIG KEYS support is an example
>> >> of reading keys directly by the kernel.
>> >>
>> >> CONFIG_IMA_APPRAISE_SIGNED_INIT kernel option is provided to make the IMA
>> >> default appraisal policy to required signature validation. Signed init
>> >> process need to initialize EVM key and load appropriate IMA policy which
>> >> would not require everything to be signed.
>> >>
>> >> Unless real '/sbin/init' is signed, a simple and practical way is to place
>> >> all signed programs, libraries, scripts and configuration files under
>> >> dedicated directory, for example '/ima', and run signed init process by
>> >> providing a kernel command line parameter 'init=/ima/init'
>> >
>> > The kernel may already have loaded kernel modules before it gets around
>> > to mounting rootfs and running /sbin/init. How does that fit into the
>> > overall signing scheme? And how did /sbin/modprobe get its signature
>> > checked?
>> >
>> >
>>
>> If kernel embedded initramfs is in use then it is signed together with kernel,
>> and this functionality is not needed and no need to enable it with
>> kernel configuration.
>>
>> As it is IMA extensions and it is entirely based on IMA functionality
>> it requires extended attribute support.
>>
>> If externally loaded initramfs is used, then that one uses cpio based
>> archive that does not support extended attributes and thus external
>> initramfs cannot be used for secure initialization.
>
> Right, but GNU tar version 1.27.1 supports Posix.1 (ustar) format, which
> has xattr support. GNU CPIO supports the Posix.1 tar format. The
> question is whether CPIO supports the included xattrs.
>
>> This functionality is targeted to be used without initramfs on normal
>> filesystems supporting xattrs. In such case, modprobe cannot be loaded before
>> rootfs is mounted. Any filesystems and block device drivers obviously
>> need to be embedded into the kernel. In the place where
>> ima_prepare_keys() hooks is called, we have
>>
>> ima_prepare_keys();
>> load_default_modules();
>>
>> So we load keys after mounting rootfs and before calling load_default_modules().
>> So if anything useful kernel loads with load_default_modules, will be
>> loaded after IMA key is available and thus modprobe will be verified.
>>
>>
>> > The proposed interface and implementation look reasonable to me.
>> > Opening and reading a file from the root fs is a bit unusual, but we
>> > already do something similar with "/sbin/init" and the reasoning here
>> > is similar.
>> >
>> > The only alternative I can immediately think of is to bundle the public
>> > keys into a kernel module and load them into the kernel that way but
>> >
>> > - if/when we implement module signing, we have a chicken-and-egg problem
>> >
>> > - doing it via a kernel module seems a bit fake - a bit of trickery
>> > to reduce code duplication. Better to do it explicitly.
>> >
>>
>> This was the idea. Kernel has embedded certificate signing key on the
>> .system keyring. Filesystem image/package can come with own signing key
>> and that one is loaded and verified by existing KEY infrastructure.
>> Entire signed init code can come as rpm or deb package with its own key.
>> That is benefit of loading key.
>
> Ok, this type of solution addresses the concerns of devices, but we also
> need a viable solution for systems with an initramfs.
>
> Mimi
>

Sorry for the late reply. I am on holidays at the moment.

Offered solution is simple one to work without initramfs.

When using initramfs, one approach is that it can be be embedded into
the kernel.

When initramfs is separate, offered solution would work as well, but
it would require initramfs container, which is 'cpio' would support
extended attributes. cpio does not support them. 'cpio' maintainer
Sergey Poznyakoff replied in my email to him that it would require
standardization work. He suggested that it is better to use 'tar'
archive which supports xattrs. Using tar for initramfs would require
initramfs tool changes across all distros and kernel. As I said above
offered solution would work as well for initramfs without any changes
if initramfs container would support xattrs... So further extensions
are not related to this patchset.

Thanks,
Dmitry

2014-10-10 14:15:47

by Dmitry Kasatkin

[permalink] [raw]
Subject: Re: [PATCH v1 0/4] ima: require signed user-space initialization

Hello Andrew,

I have just posted updated patchset.
Please check patch description where I discuss your questions and
related changes.

Thanks,
Dmitry

On 30/07/14 00:37, Dmitry Kasatkin wrote:
> On Wed, Jul 23, 2014 at 9:08 PM, Mimi Zohar <[email protected]> wrote:
>> On Wed, 2014-07-16 at 23:26 +0300, Dmitry Kasatkin wrote:
>>> Hello,
>>>
>>>
>>> On Wed, Jul 16, 2014 at 12:33 AM, Andrew Morton
>>> <[email protected]> wrote:
>>>> On Tue, 15 Jul 2014 15:54:19 +0300 Dmitry Kasatkin <[email protected]> wrote:
>>>>
>>>>> Currently secure IMA/EVM initialization has to be done from the initramfs,
>>>>> embedded in the signed kernel image. Many systems do not want to use
>>>>> initramfs or usage of embedded initramfs makes it difficult to have
>>>>> multi-target kernels.
>>>>>
>>>>> This is a very simple patchset which makes it possible to perform secure
>>>>> initialization by requiring initial user-space to be signed.
>>>>>
>>>>> It does it by:
>>>>> - introducing IMA public keys loading hook
>>>>> - loading IMA trusted public key into .ima trusted keyring
>>>>> - making default IMA appraisal policy to require everything to be signed
>>>>>
>>>>> When builtin initramfs is not in use, keys cannot be read from initcalls,
>>>>> because root filesystem is not yet mounted. In order to read keys before
>>>>> executing init process, ima_prepare_keys() hook is introduced. Reading
>>>>> public keys from the kernel is justified because signature verification
>>>>> key is needed in order to verify anything else which is read from the
>>>>> file system. Public keys are X509 certificates and itself signed by the
>>>>> trusted key from the .system keyring. Kernel BIG KEYS support is an example
>>>>> of reading keys directly by the kernel.
>>>>>
>>>>> CONFIG_IMA_APPRAISE_SIGNED_INIT kernel option is provided to make the IMA
>>>>> default appraisal policy to required signature validation. Signed init
>>>>> process need to initialize EVM key and load appropriate IMA policy which
>>>>> would not require everything to be signed.
>>>>>
>>>>> Unless real '/sbin/init' is signed, a simple and practical way is to place
>>>>> all signed programs, libraries, scripts and configuration files under
>>>>> dedicated directory, for example '/ima', and run signed init process by
>>>>> providing a kernel command line parameter 'init=/ima/init'
>>>> The kernel may already have loaded kernel modules before it gets around
>>>> to mounting rootfs and running /sbin/init. How does that fit into the
>>>> overall signing scheme? And how did /sbin/modprobe get its signature
>>>> checked?
>>>>
>>>>
>>> If kernel embedded initramfs is in use then it is signed together with kernel,
>>> and this functionality is not needed and no need to enable it with
>>> kernel configuration.
>>>
>>> As it is IMA extensions and it is entirely based on IMA functionality
>>> it requires extended attribute support.
>>>
>>> If externally loaded initramfs is used, then that one uses cpio based
>>> archive that does not support extended attributes and thus external
>>> initramfs cannot be used for secure initialization.
>> Right, but GNU tar version 1.27.1 supports Posix.1 (ustar) format, which
>> has xattr support. GNU CPIO supports the Posix.1 tar format. The
>> question is whether CPIO supports the included xattrs.
>>
>>> This functionality is targeted to be used without initramfs on normal
>>> filesystems supporting xattrs. In such case, modprobe cannot be loaded before
>>> rootfs is mounted. Any filesystems and block device drivers obviously
>>> need to be embedded into the kernel. In the place where
>>> ima_prepare_keys() hooks is called, we have
>>>
>>> ima_prepare_keys();
>>> load_default_modules();
>>>
>>> So we load keys after mounting rootfs and before calling load_default_modules().
>>> So if anything useful kernel loads with load_default_modules, will be
>>> loaded after IMA key is available and thus modprobe will be verified.
>>>
>>>
>>>> The proposed interface and implementation look reasonable to me.
>>>> Opening and reading a file from the root fs is a bit unusual, but we
>>>> already do something similar with "/sbin/init" and the reasoning here
>>>> is similar.
>>>>
>>>> The only alternative I can immediately think of is to bundle the public
>>>> keys into a kernel module and load them into the kernel that way but
>>>>
>>>> - if/when we implement module signing, we have a chicken-and-egg problem
>>>>
>>>> - doing it via a kernel module seems a bit fake - a bit of trickery
>>>> to reduce code duplication. Better to do it explicitly.
>>>>
>>> This was the idea. Kernel has embedded certificate signing key on the
>>> .system keyring. Filesystem image/package can come with own signing key
>>> and that one is loaded and verified by existing KEY infrastructure.
>>> Entire signed init code can come as rpm or deb package with its own key.
>>> That is benefit of loading key.
>> Ok, this type of solution addresses the concerns of devices, but we also
>> need a viable solution for systems with an initramfs.
>>
>> Mimi
>>
> Sorry for the late reply. I am on holidays at the moment.
>
> Offered solution is simple one to work without initramfs.
>
> When using initramfs, one approach is that it can be be embedded into
> the kernel.
>
> When initramfs is separate, offered solution would work as well, but
> it would require initramfs container, which is 'cpio' would support
> extended attributes. cpio does not support them. 'cpio' maintainer
> Sergey Poznyakoff replied in my email to him that it would require
> standardization work. He suggested that it is better to use 'tar'
> archive which supports xattrs. Using tar for initramfs would require
> initramfs tool changes across all distros and kernel. As I said above
> offered solution would work as well for initramfs without any changes
> if initramfs container would support xattrs... So further extensions
> are not related to this patchset.
>
> Thanks,
> Dmitry
>