RFC: Public key encryption of dmesg by the kernel
Subsystems (6)
cover RFC: Public key encryption of dmesg by the kernel
From: Dan Aloni <[email protected]>
Hi All,
There has been a lot of progress in recent times regarding the removal of sensitive information from dmesg (pointers, etc.), so I figured - why not encrypt it all? However, I have not found any existing discussions or references regarding this technical direction.
I am not sure that desktop and power users would like to have their kernel message encrypted, but there are scenarios such as in mobile devices, where only the developers, makers of devices, may actually benefit from access to kernel prints messages, and the users may be more protected from exploits.
In its present form, it is an RFC, so that before investing more time developing it further, I would receive comments regarding its viability and suggestions for design.
Dan Aloni (5):
crypto: fix memory leak in rsa-kcs1pad encryption
certs: allow in-kernel access of trusted keys kernel/printk: allow kmsg to be encrypted using public key encryption
tools: add dmesg decryption program
docs: add dmesg encryption doc
Documentation/admin-guide/dmesg-encryption.rst | 77 +++++ certs/system_keyring.c | 56 +++- crypto/rsa-pkcs1pad.c | 9 - include/keys/system_keyring.h | 3 + include/uapi/linux/kmsg.h | 18 ++ init/Kconfig | 10 + kernel/printk/printk.c | 422 +++++++++++++++++++++++++ tools/Makefile | 5 +- tools/kmsg/.gitignore | 1 + tools/kmsg/Makefile | 14 + tools/kmsg/dmesg-decipher.c | 316 ++++++++++++++++++ 11 files changed, 920 insertions(+), 11 deletions(-) create mode 100644 Documentation/admin-guide/dmesg-encryption.rst create mode 100644 include/uapi/linux/kmsg.h create mode 100644 tools/kmsg/.gitignore create mode 100644 tools/kmsg/Makefile create mode 100644 tools/kmsg/dmesg-decipher.c
Signature · 1 line
2.13.6
PATCH 1/5 crypto: fix memory leak in rsa-kcs1pad encryption
From: Dan Aloni <[email protected]>
The encryption mode of pkcs1pad never uses out_sg and out_buf, so there's no need to allocate the buffer, which presently is not even being freed.
--- crypto/rsa-pkcs1pad.c | 9 --------- 1 file changed, 9 deletions(-)
crypto/rsa-pkcs1pad.c +0 -9
@@ -261,15 +261,6 @@ static int pkcs1pad_encrypt(struct akcipher_request *req)pkcs1pad_sg_set_buf (req_ctx->in_sg, req_ctx->in_buf, ctx->key_size -1 - req->src_len, req->src); - req_ctx->out_buf =kmalloc (ctx->key_size,GFP_KERNEL ); -if (!req_ctx->out_buf) { -kfree (req_ctx->in_buf); -return -ENOMEM ; - } - -pkcs1pad_sg_set_buf (req_ctx->out_sg, req_ctx->out_buf, - ctx->key_size,NULL ); -akcipher_request_set_tfm (&req_ctx->child_req, ctx->child);akcipher_request_set_callback (&req_ctx->child_req, req->base.flags, pkcs1pad_encrypt_sign_complete_cb, req);
Signature · 1 line
2.13.6
PATCH 2/5 certs: allow in-kernel access of trusted keys
In reply to Dan AloniFrom: Dan Aloni <[email protected]>
--- certs/system_keyring.c | 56 ++++++++++++++++++++++++++++++++++++++++++- include/keys/system_keyring.h | 3 +++ 2 files changed, 58 insertions(+), 1 deletion(-)
certs/system_keyring.c +55 -1
@@ -131,6 +131,8 @@ static __init int system_trusted_keyring_init(void)*/ device_initcall (system_trusted_keyring_init); +static char *first_asymmetric_key_description; +/* * Load the compiled-in list of X.509 certificates. */
@@ -172,8 +174,11 @@ static __init int load_system_certificate_list(void)pr_err ("Problem loading in-kernel X.509 certificate (%ld)\n" ,PTR_ERR (key)); }else { + first_asymmetric_key_description = +kstrdup (key_ref_to_ptr (key)->description, +GFP_KERNEL );pr_notice ("Loaded X.509 cert '%s'\n" , -key_ref_to_ptr (key)->description); + first_asymmetric_key_description);key_ref_put (key); } p += plen;
@@ -265,3 +270,52 @@ int verify_pkcs7_signature(const void *data, size_t len,EXPORT_SYMBOL_GPL (verify_pkcs7_signature);#endif /* CONFIG_SYSTEM_DATA_VERIFICATION */ + +/** +* get_first_asymmetric_key - Find a key by ID. +* @keyring: The keys to search. +* +* Return the first assymmetric key in a keyring. +*/ +static struct key *get_first_asymmetric_key (struct key *keyring) +{ +key_ref_t ref; + + ref =keyring_search (make_key_ref (keyring,1 ), + &key_type_asymmetric, + first_asymmetric_key_description); +if (IS_ERR (ref)) { +switch (PTR_ERR (ref)) { +case -EACCES : +case -ENOTDIR : +case -EAGAIN : +return ERR_PTR (-ENOKEY ); +default : +return ERR_CAST (ref); + } + } + +return key_ref_to_ptr (ref); +} + +/** +* find_asymmetric_key - Find a key by ID in the builtin trusted keys +* keyring, or return the first key in that keyring. +* +* @id_0: The first ID to look for or NULL. +* @id_1: The second ID to look for or NULL. +* +* The preferred identifier is the id_0 and the fallback identifier is +* the id_1. If both are given, the lookup is by the former, but the +* latter must also match. If none are given, the first key is returned. +*/ +struct key *find_trusted_asymmetric_key (const struct asymmetric_key_id *id_0, +const struct asymmetric_key_id *id_1) +{ +struct key *keyring = builtin_trusted_keys; +if (!id_0 && !id_1) { +return get_first_asymmetric_key (keyring); + } + +return find_asymmetric_key (keyring, id_0, id_1, false); +}
include/keys/system_keyring.h +3 -0
@@ -13,6 +13,7 @@#define _KEYS_SYSTEM_KEYRING_H#include <linux/key.h> +#include <keys/asymmetric-type.h> #ifdef CONFIG_SYSTEM_TRUSTED_KEYRING
@@ -61,5 +62,7 @@ static inline struct key *get_ima_blacklist_keyring(void) }#endif /* CONFIG_IMA_BLACKLIST_KEYRING */ +struct key *find_trusted_asymmetric_key (const struct asymmetric_key_id *id_0, +const struct asymmetric_key_id *id_1);#endif /* _KEYS_SYSTEM_KEYRING_H */
Signature · 1 line
2.13.6
Randy Dunlap
reviewerRe: [PATCH 2/5] certs: allow in-kernel access of trusted keys
Quoted 35 lines · Dan Aloni
From: Dan Aloni <[email protected]>
Signed-off-by Dan Aloni <[email protected]>--- certs/system_keyring.c | 56 ++++++++++++++++++++++++++++++++++++++++++- include/keys/system_keyring.h | 3 +++ 2 files changed, 58 insertions(+), 1 deletion(-)certs/system_keyring.c +6
-1@@ -131,6 +131,8 @@ static __init int system_trusted_keyring_init(void)*/ device_initcall (system_trusted_keyring_init); +static char *first_asymmetric_key_description; +/* * Load the compiled-in list of X.509 certificates. */ @@ -172,8 +174,11 @@ static __init int load_system_certificate_list(void)pr_err ("Problem loading in-kernel X.509 certificate (%ld)\n" ,PTR_ERR (key)); }else { + first_asymmetric_key_description = +kstrdup (key_ref_to_ptr (key)->description, +GFP_KERNEL );pr_notice ("Loaded X.509 cert '%s'\n" , -key_ref_to_ptr (key)->description); + first_asymmetric_key_description);key_ref_put (key); } p += plen;
certs/system_keyring.c int verify_pkcs7_signature(const void *data, size_t len, · line 278
Quoted 9 lines
certs/system_keyring.c +6
-0@@ -265,3 +270,52 @@ int verify_pkcs7_signature(const void *data, size_t len,EXPORT_SYMBOL_GPL (verify_pkcs7_signature);#endif /* CONFIG_SYSTEM_DATA_VERIFICATION */ + +/** +* get_first_asymmetric_key - Find a key by ID. +* @keyring: The keys to search. +* +* Return the first assymmetric key in a keyring.
spello
Quoted 14 lines
certs/system_keyring.c +14
-0+*/ +static struct key *get_first_asymmetric_key (struct key *keyring) +{ +key_ref_t ref; + + ref =keyring_search (make_key_ref (keyring,1 ), + &key_type_asymmetric, + first_asymmetric_key_description); +if (IS_ERR (ref)) { +switch (PTR_ERR (ref)) { +case -EACCES : +case -ENOTDIR : +case -EAGAIN : +return ERR_PTR (-ENOKEY );
certs/system_keyring.c int verify_pkcs7_signature(const void *data, size_t len, · line 302
Quoted 10 lines
certs/system_keyring.c +10
-0+default : +return ERR_CAST (ref); + } + } + +return key_ref_to_ptr (ref); +} + +/** +* find_asymmetric_key - Find a key by ID in the builtin trusted keys
^Function name should match the name of the function below.
Quoted 19 lines
certs/system_keyring.c +19
-0+* keyring, or return the first key in that keyring. +* +* @id_0: The first ID to look for or NULL. +* @id_1: The second ID to look for or NULL. +* +* The preferred identifier is the id_0 and the fallback identifier is +* the id_1. If both are given, the lookup is by the former, but the +* latter must also match. If none are given, the first key is returned. +*/ +struct key *find_trusted_asymmetric_key (const struct asymmetric_key_id *id_0, +const struct asymmetric_key_id *id_1) +{ +struct key *keyring = builtin_trusted_keys; +if (!id_0 && !id_1) { +return get_first_asymmetric_key (keyring); + } + +return find_asymmetric_key (keyring, id_0, id_1, false); +}
Signature · 1 line
~Randy
PATCH 3/5 kernel/printk: allow kmsg to be encrypted using public key encryption
In reply to Dan AloniFrom: Dan Aloni <[email protected]>
This commit enables the kernel to encrypt the free-form text that is generated by printk() before it is brought up to dmesg in userspace.
The encryption is made using one of the trusted public keys which are kept built-in inside the kernel. These keys are presently also used for verifying kernel modules and userspace-supplied firmwares.
--- include/uapi/linux/kmsg.h | 18 ++ init/Kconfig | 10 ++ kernel/printk/printk.c | 422 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 450 insertions(+) create mode 100644 include/uapi/linux/kmsg.h
include/uapi/linux/kmsg.h new file +18 -0
@@ -0,0 +1,18 @@ +#ifndef _LINUX_UAPI_KMSG_H +#define _LINUX_UAPI_KMSG_H + +#include <linux/ioctl.h> +#include <linux/types.h> + +struct kmsg_ioctl_get_encrypted_key { +void __user *output_buffer; +__u64 buffer_size; +__u64 key_size; +}; + +#define KMSG_IOCTL_BASE 0x42 + +#define KMSG_IOCTL__GET_ENCRYPTED_KEY _IOWR(KMSG_IOCTL_BASE, 0xe1, \ + struct kmsg_ioctl_get_encrypted_key) + +#endif /* _LINUX_DN_H */
init/Kconfig +10 -0
@@ -1757,6 +1757,16 @@ config MODULE_SIG debuginfo strip done by some packagers (such as rpmbuild) and inclusion into an initramfs that wants the module size reduced. +config KMSG_ENCRYPTION + bool "Encrypt /dev/kmsg (viewing dmesg will require decryption!)" + depends on SYSTEM_TRUSTED_KEYRING + help + This enables strong encryption of messages generated by the kernel, + to defend against most kinds of information leaks. + + Note that this option adds the OpenSSL development packages as a + kernel build dependency so that certificates can be generated. + config MODULE_SIG_FORCE bool "Require modules to be validly signed" depends on MODULE_SIG
kernel/printk/printk.c +422 -0
528 lines not on this page · raw message
Signature · 1 line
2.13.6
Randy Dunlap
reviewerRe: [PATCH 3/5] kernel/printk: allow kmsg to be encrypted using public key encryption
Quoted 32 lines · Dan Aloni
From: Dan Aloni <[email protected]>
This commit enables the kernel to encrypt the free-form text that is generated by
printk()before it is brought up todmesgin userspace.The encryption is made using one of the trusted public keys which are kept built-in inside the kernel. These keys are presently also used for verifying kernel modules and userspace-supplied firmwares.
Signed-off-by Dan Aloni <[email protected]>--- include/uapi/linux/kmsg.h | 18 ++ init/Kconfig | 10 ++ kernel/printk/printk.c | 422 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 450 insertions(+) create mode 100644 include/uapi/linux/kmsg.hinclude/uapi/linux/kmsg.h new file +7
-0@@ -0,0 +1,18 @@ +#ifndef _LINUX_UAPI_KMSG_H +#define _LINUX_UAPI_KMSG_H + +#include <linux/ioctl.h> +#include <linux/types.h> + +struct kmsg_ioctl_get_encrypted_key {
include/uapi/linux/kmsg.h line 17
Quoted 10 lines
include/uapi/linux/kmsg.h new file +10
-0+void __user *output_buffer; +__u64 buffer_size; +__u64 key_size; +}; + +#define KMSG_IOCTL_BASE 0x42 + +#define KMSG_IOCTL__GET_ENCRYPTED_KEY _IOWR(KMSG_IOCTL_BASE, 0xe1, \ + struct kmsg_ioctl_get_encrypted_key) +
The ioctl info needs to be added to Documentation/ioctl/ioctl-number.txt. BTW, 0x42 == 'B', with number 0xe1, conflicts with advanced bbus, whatever that is. But at least it should be added to the doc file.
Quoted 9 lines
include/uapi/linux/kmsg.h new file +1
-0+#endif /* _LINUX_DN_H */ kernel/printk/printk.c +0
-0@@ -744,12 +755,33 @@ static ssize_t msg_print_ext_body(char *buf, size_t size,return p - buf;
kernel/printk/printk.c static ssize_t msg_print_ext_body(char *buf, size_t size, · line 765
Quoted 10 lines
kernel/printk/printk.c +8
-0} +#ifdef CONFIG_KMSG_ENCRYPTION +static int __ro_after_init kmsg_encrypt =1 ; +static int __init control_kmsg_encrypt (char *str) +{ +get_option (&str, &kmsg_encrypt); +return 0 ; +} +__setup ("kmsg.encrypt=" , control_kmsg_encrypt);
See comment in the documentation patch: please change the parameter name (no dot).
Signature · 1 line
~Randy
PATCH 4/5 tools: add dmesg decryption program
In reply to Dan AloniFrom: Dan Aloni <[email protected]>
Example execution:
dmesg | dmesg-decipher <private-key.pem>
--- tools/Makefile | 5 +- tools/kmsg/.gitignore | 1 + tools/kmsg/Makefile | 14 ++ tools/kmsg/dmesg-decipher.c | 316 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 335 insertions(+), 1 deletion(-) create mode 100644 tools/kmsg/.gitignore create mode 100644 tools/kmsg/Makefile create mode 100644 tools/kmsg/dmesg-decipher.c
tools/Makefile +4 -1
@@ -167,6 +167,9 @@ tmon_clean: freefall_clean: $(call descend,laptop/freefall,clean) +kmsg: + $(call descend,kmsg,clean) + build_clean: $(call descend,build,clean)
@@ -174,6 +177,6 @@ clean: acpi_clean cgroup_clean cpupower_clean hv_clean firewire_clean \ perf_clean selftests_clean turbostat_clean spi_clean usb_clean virtio_clean \ vm_clean bpf_clean iio_clean x86_energy_perf_policy_clean tmon_clean \ freefall_clean build_clean libbpf_clean libsubcmd_clean liblockdep_clean \ - gpio_clean objtool_clean leds_clean wmi_clean + gpio_clean objtool_clean leds_clean wmi_clean kmsg .PHONY: FORCE
tools/kmsg/.gitignore new file +1 -0
@@ -0,0 +1 @@ +dmesg-decipher
tools/kmsg/Makefile new file +14 -0
@@ -0,0 +1,14 @@ +# SPDX-License-Identifier: GPL-2.0 +CC := $(CROSS_COMPILE)gcc + +CFLAGS := -O2 -Wall $$(pkg-config --libs openssl) + +PROGS := dmesg-decipher + +%: %.c + $(CC) $(CFLAGS) -o $@ $^ + +all: $(PROGS) + +clean: + rm -fr $(PROGS)
tools/kmsg/dmesg-decipher.c new file +316 -0
316 lines not on this page · raw message
Signature · 1 line
2.13.6
Randy Dunlap
reviewerRe: [PATCH 4/5] tools: add dmesg decryption program
Quoted 17 lines · Dan Aloni
From: Dan Aloni <[email protected]>
Example execution:
dmesg | dmesg-decipher <private-key.pem>
Signed-off-by Dan Aloni <[email protected]>---
tools/kmsg/dmesg-decipher.c new file +1
-0@@ -0,0 +1,316 @@ +// SPDX-License-Identifier: GPL-2.0
tools/kmsg/dmesg-decipher.c line 11
Quoted 10 lines
tools/kmsg/dmesg-decipher.c new file +10
-0+/* +* dmesg-decipher.c +* +* A sample utility to decrypt an encrypted dmesg output, for +* developement with kernels having kmsg encryption enabled. +* +* Copyright (c) Dan Aloni, 2017 +* +* Compile with +* gcc -I/usr/src/linux/include getdelays.c -o getdelays
copy-paste error ^^^
Quoted 10 lines
tools/kmsg/dmesg-decipher.c new file +10
-0+*/ + +#include <openssl/pem.h> +#include <openssl/pkcs7.h> +#include <openssl/err.h> + +#include <stdbool.h> +#include <stdint.h> +#include <string.h> +#include <regex.h>
[snip]
Quoted 18 lines
tools/kmsg/dmesg-decipher.c new file +18
-0+int main (int argc,char **argv) +{ +BIO *tbio =NULL ; +RSA *rsa; +int ret =1 ; +char line[0x1000 ]; +uint8_t enc_sess_key[0x200 ]; +uint8_t sess_key[0x200 ] = {0 , }; +bool got_key = false; + +OpenSSL_add_all_algorithms (); +ERR_load_crypto_strings (); + +regex_t session_key_regex; +regex_t message_regex; + + ret =regcomp (&session_key_regex, session_key_pattern,REG_EXTENDED ); +if (ret) {
tools/kmsg/dmesg-decipher.c line 256
Quoted 10 lines
tools/kmsg/dmesg-decipher.c new file +10
-0+ goto err; + } + + ret =regcomp (&message_regex, message_pattern,REG_EXTENDED ); +if (ret) { + goto err; + } + +if (argc <2 ) { +fprintf (stderr,"not enough paramters\n" );
parameters
Quoted 2 lines
tools/kmsg/dmesg-decipher.c new file +2
-0+return -1 ; + }
Signature · 1 line
~Randy
PATCH 5/5 docs: add dmesg encryption doc
In reply to Dan AloniFrom: Dan Aloni <[email protected]>
--- Documentation/admin-guide/dmesg-encryption.rst | 77 ++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 Documentation/admin-guide/dmesg-encryption.rst
Documentation/admin-guide/dmesg-encryption.rst new file +77 -0
@@ -0,0 +1,77 @@ +Kernel message encryption +------------------------- + +.. CONTENTS +.. +.. - Overview +.. - Reason for encrypting dmesg +.. - Compile time and run time switches +.. - Limitations +.. - Decrypting dmesg + + +======== +Overview +======== + +Similaly the module signing facility, it is also possible to have the kernel perform public key encryption of the kernel messages that are being generated by printk calls. + +The encryption can be performed for one of the trusted public keys in the kernel keyring, and by default will be performed against the kernel's moduel signing key. + +To prevent a run-time dependency inside printk itself, the encryption takes places upon trying to read ``/dev/kmsg`` which is the mechanism currenly used by ``systemd`` to read kernel messages, and is also used by ``dmesg`` invocations. + +The first line being read by a ``dmesg`` opener will be an artificial line containing an encrypted symmetric encryption session key, in RSA PKCS#1 format. The other lines are messages encrypted under an AES-128-GCM scheme. All binary ciphertext is hex-encoded, so that the ciphertext solely comprises of printable characters. + +=========== +Limitations +=========== + +There are various limitations one need to consider when enabling dmesg encryption: + + * The metadata of kernel messages is not part of the encryption (timestamp, log facility, log severity). + * The seldom accompanying dictionary is also not part of the encryption. + * Any output to any system console, happening when printk() itself is executing, is also not encrypted. A potential attacker can load up ``netconsole`` and have kernel messages being sent as plaintext to other machines. Hopefully, on embedded devices, all system consoles are under strict control of the developers. + * The syslog system call is barred from reading kmsg. Its present users are few, as the system call's interface is mostly a fallback to an inaccessible ``/dev/kmsg``. This is only an implementation limitation and that may be addressed. + * kmsg buffers will still be saved as plaintext inside kdumps. The assumption is that having an access to read a kdump is equivalent to full kernel access anyway. + +=========================== +Reason for encryption dmesg +=========================== + +For years, dmesg has contained data which could be utilized by vulnerability exploiters, allowing for privilege escalations. Developers may leave key data such as pointers, indication of driver bugs, and more. + +The feature is mostly aimed for device manufacturers who are not keen on revealing the full details of kernel execution, bugs, and crashes to their users, but only to their developers, so that local programs running on the devices cannot use the data for 'rooting' and executing exploits. + +================================== +Compile time and run time switches +================================== + +In build time, this feature is controlled via the ``CONFIG_KMSG_ENCRYPTION`` configuration variable. + +In run time, it can be turned off by providing `kmsg.encrypt=0` as a boot time parameter. + +================ +Decrypting dmesg +================ + +A supplied program in the kernel tree named ``dmesg-decipher``, uses the OpenSSL library along with the paired private key of the encryption, in order to decipher an encrypted dmesg. + +An innocuous dmesg invocation will appear as such (with the ciphertexts shortened here for the brevity of this document):: + + [ 0.000000] K:7c7da3617b6f...f4098e2425af00 + [ 0.000000] M:36ae318532e...61686821b3ab,16,12 + [ 0.000000] M:7fca10...154e035,16,12 + .... + +The artificial ``K:`` message is generated per opening of ``/dev/kmsg``. It contains the encrypted session key. The encrypted dmesg lines follows it (prefix ``M:``). + +Provided with the private key, deciphering a dmesg output should be a straight-forward process. + +For example, one can save an encrypted dmesg to ``dmesg.enc`` in one machine, then transfer it to another machine which contains access to the PEM with the decrypting private key, and use the the following command:: + + cat dmesg.enc | ./tools/kmsg/dmesg-decipher certs/signing_key.pem + + [ 0.000000] Linux version 4.15.0-rc5+ (dan@jupiter) (gcc version 7.2.1 20170915 (Red Hat 7.2.1-2) (GCC)) #109 SMP Sat Dec 30 18:32:25 IST 2017 + [ 0.000000] Command line: BOOT_IMAGE=/vmlinuz-4.15.0-rc5-dan+ root=UUID=f48b37ec-fcb8-4689-b12e-58703db3cb21 ro rhgb quiet LANG=en_US.UTF-8 + [ 0.000000] x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point registers' + ...
Signature · 1 line
2.13.6
Re: [kernel-hardening] [PATCH 5/5] docs: add dmesg encryption doc
Quoted 23 lines · Dan Aloni
From: Dan Aloni <[email protected]>
Signed-off-by Dan Aloni <[email protected]>--- Documentation/admin-guide/dmesg-encryption.rst | 77 ++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 Documentation/admin-guide/dmesg-encryption.rstDocumentation/admin-guide/dmesg-encryption.rst new file +9
-0@@ -0,0 +1,77 @@ +Kernel message encryption +------------------------- + +.. CONTENTS +.. +.. - Overview +.. - Reason for encrypting dmesg +.. - Compile time and run time switches +.. - Limitations
Documentation/admin-guide/dmesg-encryption.rst line 19
Quoted 10 lines
Documentation/admin-guide/dmesg-encryption.rst new file +10
-0+.. - Decrypting dmesg + + +======== +Overview +======== + +Similaly the module signing facility, it is also possible to have the kernel perform public key encryption of the kernel messages that are being generated by printk calls. + +The encryption can be performed for one of the trusted public keys in the kernel keyring, and by default will be performed against the kernel's moduel signing key.
Typo - s/moduel/module/
Documentation/admin-guide/dmesg-encryption.rst line 21
Quoted 2 lines
Documentation/admin-guide/dmesg-encryption.rst new file +2
-0+ +To prevent a run-time dependency inside printk itself, the encryption takes places upon trying to read ``/dev/kmsg`` which is the mechanism currenly used by ``systemd`` to read kernel messages, and is also used by ``dmesg`` invocations.
Typo - s/currenly/currently/
Quoted 57 lines
Documentation/admin-guide/dmesg-encryption.rst new file +56
-1+ +The first line being read by a ``dmesg`` opener will be an artificial line containing an encrypted symmetric encryption session key, in RSA PKCS#1 format. The other lines are messages encrypted under an AES-128-GCM scheme. All binary ciphertext is hex-encoded, so that the ciphertext solely comprises of printable characters. + +=========== +Limitations +=========== + +There are various limitations one need to consider when enabling dmesg encryption: + + * The metadata of kernel messages is not part of the encryption (timestamp, log facility, log severity). + * The seldom accompanying dictionary is also not part of the encryption. + * Any output to any system console, happening when printk() itself is executing, is also not encrypted. A potential attacker can load up ``netconsole`` and have kernel messages being sent as plaintext to other machines. Hopefully, on embedded devices, all system consoles are under strict control of the developers. + * The syslog system call is barred from reading kmsg. Its present users are few, as the system call's interface is mostly a fallback to an inaccessible ``/dev/kmsg``. This is only an implementation limitation and that may be addressed. + * kmsg buffers will still be saved as plaintext inside kdumps. The assumption is that having an access to read a kdump is equivalent to full kernel access anyway. + +=========================== +Reason for encryption dmesg +=========================== + +For years, dmesg has contained data which could be utilized by vulnerability exploiters, allowing for privilege escalations. Developers may leave key data such as pointers, indication of driver bugs, and more. + +The feature is mostly aimed for device manufacturers who are not keen on revealing the full details of kernel execution, bugs, and crashes to their users, but only to their developers, so that local programs running on the devices cannot use the data for 'rooting' and executing exploits. + +================================== +Compile time and run time switches +================================== + +In build time, this feature is controlled via the ``CONFIG_KMSG_ENCRYPTION`` configuration variable. + +In run time, it can be turned off by providing `kmsg.encrypt=0` as a boot time parameter. + +================ +Decrypting dmesg +================ + +A supplied program in the kernel tree named ``dmesg-decipher``, uses the OpenSSL library along with the paired private key of the encryption, in order to decipher an encrypted dmesg. + +An innocuous dmesg invocation will appear as such (with the ciphertexts shortened here for the brevity of this document):: + + [ 0.000000] K:7c7da3617b6f...f4098e2425af00 + [ 0.000000] M:36ae318532e...61686821b3ab,16,12 + [ 0.000000] M:7fca10...154e035,16,12 + .... + +The artificial ``K:`` message is generated per opening of ``/dev/kmsg``. It contains the encrypted session key. The encrypted dmesg lines follows it (prefix ``M:``). + +Provided with the private key, deciphering a dmesg output should be a straight-forward process. + +For example, one can save an encrypted dmesg to ``dmesg.enc`` in one machine, then transfer it to another machine which contains access to the PEM with the decrypting private key, and use the the following command:: + + cat dmesg.enc | ./tools/kmsg/dmesg-decipher certs/signing_key.pem + + [ 0.000000] Linux version 4.15.0-rc5+ (dan@jupiter) (gcc version 7.2.1 20170915 (Red Hat 7.2.1-2) (GCC)) #109 SMP Sat Dec 30 18:32:25 IST 2017 + [ 0.000000] Command line: BOOT_IMAGE=/vmlinuz-4.15.0-rc5-dan+ root=UUID=f48b37ec-fcb8-4689-b12e-58703db3cb21 ro rhgb quiet LANG=en_US.UTF-8 + [ 0.000000] x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point registers' + ... --
Quoted 2 lines
2.13.6
The proposed use case for embedded developers and other constrained systems makes me wonder how useful a GPL-only facility is in those situations. AFAIK the Linux crypto subsystem is pretty restrictive for non-GPL modules (Tom Caputi of Datto had to port over a ton of Illumos crypto code for ZFS), and third-party components which can't be released under GPL also shouldn't be linking against GPL-only functions. I'm woefully unfamiliar with the history and context around decisions to mark things GPL-only, so please pardon my ignorance on the matter, but in practice this might be a barrier to legal real-world use.
Another use case for this, by the way, is for private clouds where instance owners may be untrusted and the hypervisor or cloud fabric have access to the decryption keys as well as out-of-band dmesg outputs since they hook ttySX in the VM and spool to a buffer outside the instance. Bugs in virtual devices mapping physical memory would produce usable output for the cloud provider to track and tackle, while increasing the barriers toward mapping host resources from inside the instance. Obviously an attacker with root access can bypass this facility with a reboot or kernel replacement, but it does raise the barrier and forces them to leave footprints like an elephant. Clouds running containers as the isolation mechanism and sharing a kernel benefit all the more by reducing cross-container leakage, and without the kernel concern (if they're escaping the container to alter that, we're long past this problem domain). Lastly, private instances in public clouds should also benefit from this as the same semantic around dumping dmesg to an externally facing serial tty is standard fare, and the provider can currently see tons of (ideally) privileged data.
Signature · 3 lines
Boris Lukashev Systems Architect Semper Victus
Randy Dunlap
reviewerRe: [PATCH 5/5] docs: add dmesg encryption doc
In reply to Dan AloniQuoted 20 lines · Dan Aloni
From: Dan Aloni <[email protected]>
Signed-off-by Dan Aloni <[email protected]>--- Documentation/admin-guide/dmesg-encryption.rst | 77 ++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 Documentation/admin-guide/dmesg-encryption.rstDocumentation/admin-guide/dmesg-encryption.rst new file +6
-0@@ -0,0 +1,77 @@ +Kernel message encryption +------------------------- + +.. CONTENTS +.. +.. - Overview
Documentation/admin-guide/dmesg-encryption.rst line 16
Quoted 10 lines
Documentation/admin-guide/dmesg-encryption.rst new file +10
-0+.. - Reason for encrypting dmesg +.. - Compile time and run time switches +.. - Limitations +.. - Decrypting dmesg + + +======== +Overview +======== +
Please hard wrap long lines so that they are readable in 80 columns. Some people still read .rst files like they are text files.
Documentation/admin-guide/dmesg-encryption.rst line 17
Quoted 1 line
Documentation/admin-guide/dmesg-encryption.rst new file +1
-0+Similaly the module signing facility, it is also possible to have the kernel perform public key encryption of the kernel messages that are being generated by printk calls.
Similar to the module signing facility,
Documentation/admin-guide/dmesg-encryption.rst line 19
Quoted 2 lines
Documentation/admin-guide/dmesg-encryption.rst new file +2
-0+ +The encryption can be performed for one of the trusted public keys in the kernel keyring, and by default will be performed against the kernel's moduel signing key.
s/moduel/module/
Documentation/admin-guide/dmesg-encryption.rst line 21
Quoted 2 lines
Documentation/admin-guide/dmesg-encryption.rst new file +2
-0+ +To prevent a run-time dependency inside printk itself, the encryption takes places upon trying to read ``/dev/kmsg`` which is the mechanism currenly used by ``systemd`` to read kernel messages, and is also used by ``dmesg`` invocations.
s/takes places/takes place/
s/currenly/currently/
Documentation/admin-guide/dmesg-encryption.rst line 29
Quoted 8 lines
Documentation/admin-guide/dmesg-encryption.rst new file +8
-0+ +The first line being read by a ``dmesg`` opener will be an artificial line containing an encrypted symmetric encryption session key, in RSA PKCS#1 format. The other lines are messages encrypted under an AES-128-GCM scheme. All binary ciphertext is hex-encoded, so that the ciphertext solely comprises of printable characters. + +=========== +Limitations +=========== + +There are various limitations one need to consider when enabling dmesg encryption:
needs
Quoted 12 lines
Documentation/admin-guide/dmesg-encryption.rst new file +12
-0+ + * The metadata of kernel messages is not part of the encryption (timestamp, log facility, log severity). + * The seldom accompanying dictionary is also not part of the encryption. + * Any output to any system console, happening when printk() itself is executing, is also not encrypted. A potential attacker can load up ``netconsole`` and have kernel messages being sent as plaintext to other machines. Hopefully, on embedded devices, all system consoles are under strict control of the developers. + * The syslog system call is barred from reading kmsg. Its present users are few, as the system call's interface is mostly a fallback to an inaccessible ``/dev/kmsg``. This is only an implementation limitation and that may be addressed. + * kmsg buffers will still be saved as plaintext inside kdumps. The assumption is that having an access to read a kdump is equivalent to full kernel access anyway. + +=========================== +Reason for encryption dmesg +=========================== + +For years, dmesg has contained data which could be utilized by vulnerability exploiters, allowing for privilege escalations. Developers may leave key data such as pointers, indication of driver bugs, and more.
Documentation/admin-guide/dmesg-encryption.rst line 51
Quoted 10 lines
Documentation/admin-guide/dmesg-encryption.rst new file +10
-0+ +The feature is mostly aimed for device manufacturers who are not keen on revealing the full details of kernel execution, bugs, and crashes to their users, but only to their developers, so that local programs running on the devices cannot use the data for 'rooting' and executing exploits. + +================================== +Compile time and run time switches +================================== + +In build time, this feature is controlled via the ``CONFIG_KMSG_ENCRYPTION`` configuration variable. + +In run time, it can be turned off by providing `kmsg.encrypt=0` as a boot time parameter.
A dot ('.') in a kernel parameter name usually means <module_name>.<module_parameter_name>. This probably does work as it is here, but it's unusual. It would be better to change it to an underscore: kmsg_encrypt=0
or since it is printk.c, it could be: printk.kmsg_encrypt=0
depending on how it is implemented (__setup vs. module_param_* or core_param).
Documentation/admin-guide/dmesg-encryption.rst
Quoted 6 lines
Documentation/admin-guide/dmesg-encryption.rst new file +6
-0+ +================ +Decrypting dmesg +================ + +A supplied program in the kernel tree named ``dmesg-decipher``, uses the OpenSSL library
no comma after ``dmesg-decipher``
along with the paired private key of the encryption, in order to decipher an encrypted dmesg.
no comma after "encryption"
Documentation/admin-guide/dmesg-encryption.rst line 68
Quoted 11 lines
Documentation/admin-guide/dmesg-encryption.rst new file +11
-0+ +An innocuous dmesg invocation will appear as such (with the ciphertexts shortened here for the brevity of this document):: + + [ 0.000000] K:7c7da3617b6f...f4098e2425af00 + [ 0.000000] M:36ae318532e...61686821b3ab,16,12 + [ 0.000000] M:7fca10...154e035,16,12 + .... + +The artificial ``K:`` message is generated per opening of ``/dev/kmsg``. It contains the encrypted session key. The encrypted dmesg lines follows it (prefix ``M:``). + +Provided with the private key, deciphering a dmesg output should be a straight-forward process.
"straightforward"
Quoted 10 lines
Documentation/admin-guide/dmesg-encryption.rst new file +9
-0+ +For example, one can save an encrypted dmesg to ``dmesg.enc`` in one machine, then transfer it to another machine which contains access to the PEM with the decrypting private key, and use the the following command:: + + cat dmesg.enc | ./tools/kmsg/dmesg-decipher certs/signing_key.pem + + [ 0.000000] Linux version 4.15.0-rc5+ (dan@jupiter) (gcc version 7.2.1 20170915 (Red Hat 7.2.1-2) (GCC)) #109 SMP Sat Dec 30 18:32:25 IST 2017 + [ 0.000000] Command line: BOOT_IMAGE=/vmlinuz-4.15.0-rc5-dan+ root=UUID=f48b37ec-fcb8-4689-b12e-58703db3cb21 ro rhgb quiet LANG=en_US.UTF-8 + [ 0.000000] x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point registers' + ...
Signature · 1 line
~Randy
Re: [PATCH 5/5] docs: add dmesg encryption doc
Quoted 15 lines · Randy Dunlap
Documentation/admin-guide/dmesg-encryption.rst line 16
Quoted 11 lines · Dan Aloni
From: Dan Aloni <[email protected]>
Signed-off-by Dan Aloni <[email protected]>--- Documentation/admin-guide/dmesg-encryption.rst | 77 ++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 Documentation/admin-guide/dmesg-encryption.rst+========
Documentation/admin-guide/dmesg-encryption.rst new file +3
-0+Overview +======== +Please hard wrap long lines so that they are readable in 80 columns. Some people still read .rst files like they are text files.
Thanks very much for all the reviews in this reply and others, your suggestions are incorporated in the next version. A reviewed-by is in order?
Signature · 1 line
Dan Aloni
Re: [PATCH 5/5] docs: add dmesg encryption doc
Quoted 17 lines · Dan Aloni
Quoted 15 lines · Randy Dunlap
Documentation/admin-guide/dmesg-encryption.rst line 16
Quoted 11 lines · Dan Aloni
From: Dan Aloni <[email protected]>
Signed-off-by Dan Aloni <[email protected]>--- Documentation/admin-guide/dmesg-encryption.rst | 77 ++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 Documentation/admin-guide/dmesg-encryption.rst+========
Documentation/admin-guide/dmesg-encryption.rst new file +3
-0+Overview +======== +Please hard wrap long lines so that they are readable in 80 columns. Some people still read .rst files like they are text files.
Quoted 4 lines
Thanks very much for all the reviews in this reply and others, your suggestions are incorporated in the next version. A reviewed-by is in order?
only for patch 5/5: docs:
Signature · 1 line
~Randy
Quoted 9 lines · Dan Aloni
From: Dan Aloni <[email protected]>
Hi All,
There has been a lot of progress in recent times regarding the removal of sensitive information from dmesg (pointers, etc.), so I figured - why not encrypt it all? However, I have not found any existing discussions or references regarding this technical direction.
Quoted 5 lines
I am not sure that desktop and power users would like to have their kernel message encrypted, but there are scenarios such as in mobile devices, where only the developers, makers of devices, may actually benefit from access to kernel prints messages, and the users may be more protected from exploits.
What is the benefit of your approach compared to setting dmesg_restrict=1 or something like that and letting userland decide who should get access to raw dmesg output and in what form?
Quoted 16 lines · Jann Horn
Quoted 9 lines · Dan Aloni
From: Dan Aloni <[email protected]>
Hi All,
There has been a lot of progress in recent times regarding the removal of sensitive information from dmesg (pointers, etc.), so I figured - why not encrypt it all? However, I have not found any existing discussions or references regarding this technical direction.
Quoted 5 lines
I am not sure that desktop and power users would like to have their kernel message encrypted, but there are scenarios such as in mobile devices, where only the developers, makers of devices, may actually benefit from access to kernel prints messages, and the users may be more protected from exploits.
Quoted 3 lines
What is the benefit of your approach compared to setting dmesg_restrict=1 or something like that and letting userland decide who should get access to raw dmesg output and in what form?
Inter-process vulnerabilities (via sockets, shared memory, etc.) can still allow one process with lesser dmesg privileges to exploit another with higher privileges. Once the higher process is exploited, without this approach, a plaintext dmesg is exposed for kernel exploitation through it.
There can be systems designed in such a way that the most privileged userland process would still be barred from accessing the raw hardware directly, and in those systems we still want to guard the kernel from exploits, in order to keep the hardware protected, but still allow developers to debug the kernel.
Signature · 1 line
Dan Aloni
Quoted 9 lines · Dan Aloni
From: Dan Aloni <[email protected]>
Hi All,
There has been a lot of progress in recent times regarding the removal of sensitive information from dmesg (pointers, etc.), so I figured - why not encrypt it all? However, I have not found any existing discussions or references regarding this technical direction.
Quoted 5 lines
I am not sure that desktop and power users would like to have their kernel message encrypted, but there are scenarios such as in mobile devices, where only the developers, makers of devices, may actually benefit from access to kernel prints messages, and the users may be more protected from exploits.
Yes, we have "TiVo" problem in mobile space, but please no, don't make it worse.
We should not make it easy for device makers to lock devices down from their owners.
Pavel
Signature · 2 lines
(english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html