lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Date:	Sun, 15 Sep 2013 08:56:57 +0800
From:	"Lee, Chun-Yi" <joeyli.kernel@...il.com>
To:	linux-kernel@...r.kernel.org
Cc:	linux-security-module@...r.kernel.org, linux-efi@...r.kernel.org,
	linux-pm@...r.kernel.org, linux-crypto@...r.kernel.org,
	opensuse-kernel@...nsuse.org, David Howells <dhowells@...hat.com>,
	"Rafael J. Wysocki" <rjw@...k.pl>,
	Matthew Garrett <mjg59@...f.ucam.org>,
	Len Brown <len.brown@...el.com>, Pavel Machek <pavel@....cz>,
	Josh Boyer <jwboyer@...hat.com>,
	Vojtech Pavlik <vojtech@...e.cz>,
	Matt Fleming <matt.fleming@...el.com>,
	James Bottomley <james.bottomley@...senpartnership.com>,
	Greg KH <gregkh@...uxfoundation.org>, JKosina@...e.com,
	Rusty Russell <rusty@...tcorp.com.au>,
	Herbert Xu <herbert@...dor.apana.org.au>,
	"David S. Miller" <davem@...emloft.net>,
	"H. Peter Anvin" <hpa@...or.com>, Michal Marek <mmarek@...e.cz>,
	Gary Lin <GLin@...e.com>, Vivek Goyal <vgoyal@...hat.com>,
	"Lee, Chun-Yi" <jlee@...e.com>
Subject: [PATCH V4 11/15] Hibernate: taint kernel when signature check fail

We will not direct fail the hibernate snapshot restore when the
signature check fail, instead kernel will complain by warning
message and taint kernel.

This patch also introduced a sig_enforce flag to indicate if we want
direct fail the snapshot restore when signature check fail. User can
enable it through snapshot_sig_enforce parameter or
EFI_SECURE_BOOT_SNAPSHOT_SIG_ENFORCE.

Signed-off-by: Lee, Chun-Yi <jlee@...e.com>
---
 Documentation/kernel-parameters.txt |    7 +++++++
 arch/x86/Kconfig                    |   11 +++++++++++
 include/linux/kernel.h              |    1 +
 include/linux/suspend.h             |    7 +++++++
 kernel/panic.c                      |    2 ++
 kernel/power/hibernate_keys.c       |   35 +++++++++++++++++++++++++++++++++++
 kernel/power/power.h                |    1 +
 kernel/power/snapshot.c             |    6 +++++-
 8 files changed, 69 insertions(+), 1 deletions(-)

diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 7f9d4f5..4c686c0 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -2730,6 +2730,13 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
 			Useful for devices that are detected asynchronously
 			(e.g. USB and MMC devices).
 
+	snapshot_sig_enforce
+			[HIBERNATE] When CONFIG_SNAPSHOT_VERIFICATION is set,
+			this means the snapshot image without (valid) signatures
+			will fail to recover. This parameter provides user to
+			force launch the snapshot signature check even the UEFI
+			secure boot didn't enable.
+
 	hibernate=	[HIBERNATION]
 		noresume	Don't check if there's a hibernation image
 				present during boot.
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index ea73d2f..b43217a 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1591,6 +1591,17 @@ config EFI_SECURE_BOOT_SIG_ENFORCE
 	  Say Y here to automatically enable module signature enforcement
 	  when a system boots with UEFI Secure Boot enabled.
 
+config EFI_SECURE_BOOT_SNAPSHOT_SIG_ENFORCE
+	def_bool n
+	prompt "Force snapshot signing when UEFI Secure Boot is enabled"
+	---help---
+	  UEFI Secure Boot provides a mechanism for ensuring that the
+	  firmware will only load signed bootloaders and kernels. Certain
+	  use cases may also require that the snapshot image of hibernate
+	  also be signed.
+	  Say Y here to automatically enable snapshot iage signature
+	  enforcement when a system boots with UEFI Secure Boot enabled.
+
 config SECCOMP
 	def_bool y
 	prompt "Enable seccomp to safely compute untrusted bytecode"
diff --git a/include/linux/kernel.h b/include/linux/kernel.h
index 482ad2d..95df772 100644
--- a/include/linux/kernel.h
+++ b/include/linux/kernel.h
@@ -427,6 +427,7 @@ extern enum system_states {
 #define TAINT_CRAP			10
 #define TAINT_FIRMWARE_WORKAROUND	11
 #define TAINT_OOT_MODULE		12
+#define TAINT_UNSAFE_HIBERNATE		13
 
 extern const char hex_asc[];
 #define hex_asc_lo(x)	hex_asc[((x) & 0x0f)]
diff --git a/include/linux/suspend.h b/include/linux/suspend.h
index f73cabf..6b46726 100644
--- a/include/linux/suspend.h
+++ b/include/linux/suspend.h
@@ -320,6 +320,13 @@ extern unsigned long get_safe_page(gfp_t gfp_mask);
 extern void hibernation_set_ops(const struct platform_hibernation_ops *ops);
 extern int hibernate(void);
 extern bool system_entering_hibernation(void);
+
+#ifdef CONFIG_SNAPSHOT_VERIFICATION
+extern void enforce_signed_snapshot(void);
+#else
+static inline void enforce_signed_snapshot(void) {};
+#endif
+
 #else /* CONFIG_HIBERNATION */
 static inline void register_nosave_region(unsigned long b, unsigned long e) {}
 static inline void register_nosave_region_late(unsigned long b, unsigned long e) {}
diff --git a/kernel/panic.c b/kernel/panic.c
index 8018646..c59b1f6 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -206,6 +206,7 @@ static const struct tnt tnts[] = {
 	{ TAINT_CRAP,			'C', ' ' },
 	{ TAINT_FIRMWARE_WORKAROUND,	'I', ' ' },
 	{ TAINT_OOT_MODULE,		'O', ' ' },
+	{ TAINT_UNSAFE_HIBERNATE,	'H', ' ' },
 };
 
 /**
@@ -224,6 +225,7 @@ static const struct tnt tnts[] = {
  *  'C' - modules from drivers/staging are loaded.
  *  'I' - Working around severe firmware bug.
  *  'O' - Out-of-tree module has been loaded.
+ *  'H' - System restored from unsafe hibernate snapshot image.
  *
  *	The string is overwritten by the next call to print_tainted().
  */
diff --git a/kernel/power/hibernate_keys.c b/kernel/power/hibernate_keys.c
index 0bce9ab..daf08e0 100644
--- a/kernel/power/hibernate_keys.c
+++ b/kernel/power/hibernate_keys.c
@@ -17,6 +17,7 @@ struct forward_info {
 static void *skey_data;
 static void *forward_info_buf;
 static unsigned long skey_dsize;
+static bool sig_enforce = false;
 
 bool swsusp_page_is_sign_key(struct page *page)
 {
@@ -52,6 +53,7 @@ void fill_sig_forward_info(void *page, int sig_check_ret_in)
 	memset(page, 0, PAGE_SIZE);
 	info = (struct forward_info *)page;
 
+	info->head.sig_enforce = sig_enforce;
 	info->head.sig_check_ret = sig_check_ret_in;
 	if (skey_data && !IS_ERR(skey_data) &&
 		skey_dsize <= SKEY_DBUF_MAX_SIZE) {
@@ -74,6 +76,11 @@ void restore_sig_forward_info(void)
 	}
 	info = (struct forward_info *)forward_info_buf;
 
+	/* eanble sig_enforce either boot kernel or resume target kernel set it */
+	sig_enforce = sig_enforce || info->head.sig_enforce;
+	if (sig_enforce)
+		pr_info("PM: Enforce S4 snapshot signature check\n");
+
 	sig_check_ret = info->head.sig_check_ret;
 	if (sig_check_ret)
 		pr_info("PM: Signature check fail: %d\n", sig_check_ret);
@@ -89,6 +96,14 @@ void restore_sig_forward_info(void)
 
 	/* reset skey page buffer */
 	memset(forward_info_buf, 0, PAGE_SIZE);
+
+	/* taint kernel */
+	if (!sig_enforce && sig_check_ret) {
+		pr_warning("PM: Hibernate signature check fail, system "
+			   "restored from unsafe snapshot: tainting kernel\n");
+		add_taint(TAINT_UNSAFE_HIBERNATE, LOCKDEP_STILL_OK);
+		pr_info("%s\n", print_tainted());
+	}
 }
 
 bool skey_data_available(void)
@@ -275,6 +290,17 @@ size_t get_key_length(const struct key *key)
 	return len;
 }
 
+void enforce_signed_snapshot(void)
+{
+	sig_enforce = true;
+	pr_info("PM: Enforce signature verification of hibernate snapshot\n");
+}
+
+bool sig_enforced(void)
+{
+	return sig_enforce;
+}
+
 static int __init init_sign_key_data(void)
 {
 	skey_data = (void *)get_zeroed_page(GFP_KERNEL);
@@ -290,3 +316,12 @@ static int __init init_sign_key_data(void)
 }
 
 late_initcall(init_sign_key_data);
+
+static int __init sig_enforce_setup(char *str)
+{
+	sig_enforce = true;
+	pr_info("PM: Enforce signature verification of hibernate snapshot\n");
+	return 1;
+}
+
+__setup("snapshot_sig_enforce", sig_enforce_setup);
diff --git a/kernel/power/power.h b/kernel/power/power.h
index d2da75b..4f411ac 100644
--- a/kernel/power/power.h
+++ b/kernel/power/power.h
@@ -187,6 +187,7 @@ extern void restore_sig_forward_info(void);
 extern bool swsusp_page_is_sign_key(struct page *page);
 extern unsigned long get_sig_forward_info_pfn(void);
 extern void fill_sig_forward_info(void *page_addr, int sig_check_ret);
+extern bool sig_enforced(void);
 #else
 static inline bool skey_data_available(void)
 {
diff --git a/kernel/power/snapshot.c b/kernel/power/snapshot.c
index d3e14aa..8a166e1 100644
--- a/kernel/power/snapshot.c
+++ b/kernel/power/snapshot.c
@@ -2581,7 +2581,11 @@ int snapshot_image_verify(void)
 		pr_info("PM: snapshot signature check SUCCESS!\n");
 
 forward_ret:
-	snapshot_fill_sig_forward_info(ret);
+	/* forward check result when pass or not enforce verify success */
+	if (!ret || !sig_enforced()) {
+		snapshot_fill_sig_forward_info(ret);
+		ret = 0;
+	}
 error_shash:
 	kfree(handle_buffers);
 	kfree(digest);
-- 
1.6.0.2

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

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ