ima: require signed user-space initialization
Subsystems (3)
cover 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(-)
Signature · 1 line
1.9.1
PATCH 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.
--- include/linux/ima.h | 9 +++++++++ init/main.c | 6 +++++- 2 files changed, 14 insertions(+), 1 deletion(-)
include/linux/ima.h +9 -0
@@ -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 */
init/main.c +5 -1
@@ -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 (); }
Signature · 1 line
1.9.1
PATCH 2/4 integrity: provide file reading API
In reply to Dmitry Kasatkin--- security/integrity/Kconfig | 3 +++ security/integrity/digsig.c | 41 +++++++++++++++++++++++++++++++++++++++++ security/integrity/integrity.h | 2 +- 3 files changed, 45 insertions(+), 1 deletion(-)
security/integrity/Kconfig +3 -0
@@ -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
security/integrity/digsig.c +41 -0
53 lines not on this page · raw message
security/integrity/integrity.h +1 -1
@@ -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
Signature · 1 line
1.9.1
PATCH 3/4 integrity: provide x509 certificate loading from the kernel
In reply to Dmitry KasatkinProvide API to load x509 certificates from the kernel into the integrity kernel keyrings.
--- security/integrity/Kconfig | 4 ++++ security/integrity/digsig.c | 37 +++++++++++++++++++++++++++++++++++++ security/integrity/integrity.h | 9 +++++++++ 3 files changed, 50 insertions(+)
security/integrity/Kconfig +4 -0
@@ -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
security/integrity/digsig.c +37 -0
@@ -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 ();
security/integrity/integrity.h +9 -0
@@ -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,
Signature · 1 line
1.9.1
PATCH 4/4 ima: require signed user-space initialization
In reply to Dmitry KasatkinThis 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.
--- security/integrity/ima/Kconfig | 15 +++++++++++++++ security/integrity/ima/ima_init.c | 17 +++++++++++++++++ security/integrity/ima/ima_policy.c | 5 +++++ 3 files changed, 37 insertions(+)
security/integrity/ima/Kconfig +15 -0
@@ -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.
security/integrity/ima/ima_init.c +17 -0
@@ -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 ];
security/integrity/ima/ima_policy.c +5 -0
@@ -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);
Signature · 1 line
1.9.1
Quoted 27 lines · On Tue, 15 Jul 2014 15:54:19 +0300 Dmitry Kasatkin <[email protected]>…
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 signedWhen 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_INITkernel 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.
Quoted 4 lines
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 :(
Dmitry Kasatkin
maintainerHello,
Quoted 34 lines · Andrew Morton
Quoted 27 lines · On Tue, 15 Jul 2014 15:54:19 +0300 Dmitry Kasatkin <[email protected]>…
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 signedWhen 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_INITkernel 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.Quoted 4 lines
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'
Quoted 6 lines
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/modprobeget 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.
Quoted 5 lines
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.
Quoted 8 lines
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.
Quoted 6 lines
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? Perhapsintegrity_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.
Quoted 3 lines
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
Quoted 50 lines · Dmitry Kasatkin
Hello,
Quoted 34 lines · Andrew Morton
Quoted 27 lines · On Tue, 15 Jul 2014 15:54:19 +0300 Dmitry Kasatkin <[email protected]>…
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 signedWhen 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_INITkernel 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.Quoted 4 lines
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'Quoted 6 lines
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/modprobeget 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.
Quoted 6 lines
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.
Quoted 28 lines
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 haveima_prepare_keys(); load_default_modules();So we load keys after mounting rootfs and before calling
load_default_modules(). So if anything useful kernel loads withload_default_modules, will be loaded after IMA key is available and thus modprobe will be verified.Quoted 5 lines
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.Quoted 8 lines
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.
Quoted 5 lines
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
Dmitry Kasatkin
maintainerQuoted 96 lines · Mimi Zohar
Quoted 50 lines · Dmitry Kasatkin
Hello,
Quoted 34 lines · Andrew Morton
Quoted 27 lines · On Tue, 15 Jul 2014 15:54:19 +0300 Dmitry Kasatkin <[email protected]>…
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 signedWhen 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_INITkernel 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.Quoted 4 lines
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'Quoted 6 lines
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/modprobeget 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.
Quoted 6 lines
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.
Quoted 28 lines
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 haveima_prepare_keys(); load_default_modules();So we load keys after mounting rootfs and before calling
load_default_modules(). So if anything useful kernel loads withload_default_modules, will be loaded after IMA key is available and thus modprobe will be verified.Quoted 5 lines
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.Quoted 8 lines
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.
Quoted 5 lines
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.
Quoted 5 lines
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
Hello Andrew,
I have just posted updated patchset.
Please check patch description where I discuss your questions and related changes.
Thanks,
Dmitry
Quoted 118 lines · Dmitry Kasatkin
Quoted 91 lines · Mimi Zohar
Quoted 48 lines · Dmitry Kasatkin
Hello,
Quoted 29 lines · Andrew Morton
Quoted 27 lines · On Tue, 15 Jul 2014 15:54:19 +0300 Dmitry Kasatkin <[email protected]>…
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 signedWhen 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_INITkernel 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.Quoted 10 lines
Quoted 4 lines
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/modprobeget 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.
Quoted 6 lines
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.
Quoted 24 lines
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 haveima_prepare_keys(); load_default_modules();So we load keys after mounting rootfs and before calling
load_default_modules(). So if anything useful kernel loads withload_default_modules, will be loaded after IMA key is available and thus modprobe will be verified.Quoted 10 lines
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
Quoted 8 lines
Quoted 3 lines
- 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.
Quoted 5 lines
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