mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Shane Wang <shane.wang@intel.com>
To: "linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	Ingo Molnar <mingo@elte.hu>, "H. Peter Anvin" <hpa@zytor.com>,
	"Cihula, Joseph" <joseph.cihula@intel.com>,
	"arjan@linux.intel.com" <arjan@linux.intel.com>,
	Andi Kleen <andi@firstfloor.org>,
	"chrisw@sous-sol.org" <chrisw@sous-sol.org>,
	"jmorris@namei.org" <jmorris@namei.org>,
	"jbeulich@novell.com" <jbeulich@novell.com>,
	"peterm@redhat.com" <peterm@redhat.com>,
	len.brown@intel.com, Pavel Machek <pavel@ucw.cz>,
	"Rafael J. Wysocki" <rjw@sisk.pl>,
	linux-pm@lists.linux-foundation.org, shane.wang@intel.com
Subject: [PATCH] intel_txt: add s3 userspace memory integrity verification
Date: Fri, 04 Dec 2009 17:12:11 +0800	[thread overview]
Message-ID: <4B18D26B.4040500@intel.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 10630 bytes --]

This patch added verification for userspace memory integrity after S3 resume.
Integrity verification for other memory (say kernel itself) has been done by tboot.

Thanks
Shane

---
  arch/x86/kernel/entry_64.S |   20 +++
  arch/x86/kernel/tboot.c    |  226 +++++++++++++++++++++++++++++++++++
  drivers/acpi/sleep.c       |    3
  include/linux/mm.h         |    8 -
  include/linux/tboot.h      |    3
  security/Kconfig           |    2
  6 files changed, 256 insertions(+), 6 deletions(-)

Signed-off-by: Shane Wang <shane.wang@intel.com>
Signed-off-by: Joseph Cihula <joseph.cihula@intel.com>

diff -r c878d454dc8b arch/x86/kernel/entry_64.S
--- a/arch/x86/kernel/entry_64.S	Wed Dec 02 01:06:32 2009 -0800
+++ b/arch/x86/kernel/entry_64.S	Thu Dec 03 07:22:17 2009 -0800
@@ -1275,6 +1275,26 @@ ENTRY(call_softirq)
  	CFI_ENDPROC
  END(call_softirq)

+#ifdef CONFIG_INTEL_TXT
+/* void tboot_switch_stack_call(void (*target_func)(void), u64 new_rsp) */
+ENTRY(tboot_switch_stack_call)
+	CFI_STARTPROC
+	push %rbp
+	CFI_ADJUST_CFA_OFFSET	8
+	CFI_REL_OFFSET	rbp,0
+	mov %rsp, %rbp
+	CFI_DEF_CFA_REGISTER	rbp
+	mov %rsi, %rsp
+	push %rbp
+	call *%rdi
+	leaveq
+	CFI_DEF_CFA_REGISTER	rsp
+	CFI_ADJUST_CFA_OFFSET	-8
+	ret
+	CFI_ENDPROC
+END(tboot_switch_stack_call)
+#endif
+
  #ifdef CONFIG_XEN
  zeroentry xen_hypervisor_callback xen_do_hypervisor_callback

diff -r c878d454dc8b arch/x86/kernel/tboot.c
--- a/arch/x86/kernel/tboot.c	Wed Dec 02 01:06:32 2009 -0800
+++ b/arch/x86/kernel/tboot.c	Thu Dec 03 07:22:17 2009 -0800
@@ -20,6 +20,7 @@
   */

  #include <linux/dma_remapping.h>
+#include <linux/scatterlist.h>
  #include <linux/init_task.h>
  #include <linux/spinlock.h>
  #include <linux/delay.h>
@@ -30,12 +31,17 @@
  #include <linux/pfn.h>
  #include <linux/mm.h>
  #include <linux/tboot.h>
+#include <linux/random.h>
+
+#include <crypto/vmac.h>
+#include <crypto/hash.h>

  #include <asm/trampoline.h>
  #include <asm/processor.h>
  #include <asm/bootparam.h>
  #include <asm/pgtable.h>
  #include <asm/pgalloc.h>
+#include <asm/percpu.h>
  #include <asm/fixmap.h>
  #include <asm/proto.h>
  #include <asm/setup.h>
@@ -168,6 +174,159 @@ static void tboot_create_trampoline(void
  		      map_base, map_size);
  }

+#ifdef CONFIG_X86_64
+static char *new_stack, *new_stack_ptr;
+
+static int tboot_pre_stack_switch(void)
+{
+	BUG_ON((new_stack != NULL) || (new_stack_ptr != NULL));
+
+	/*
+	 * as long as thread info is above 4G, then switch stack,
+	 * since tboot can't access >4G stack for MACing
+	 */
+	if (!((PFN_PHYS(PFN_DOWN(virt_to_phys(current_thread_info())))
+		+ (PFN_UP(THREAD_SIZE) << PAGE_SHIFT))
+		& 0xffffffff00000000UL))
+		return -1;
+
+	new_stack = (char *)__get_free_pages(GFP_DMA32, IRQ_STACK_ORDER);
+
+	BUG_ON(new_stack == NULL);
+	memset(new_stack, 0, IRQ_STACK_SIZE);
+	new_stack_ptr = new_stack + IRQ_STACK_SIZE - 64;
+
+	return 0;
+}
+
+static void tboot_post_stack_switch(void)
+{
+	BUG_ON((new_stack == NULL) || (new_stack_ptr == NULL));
+
+	free_pages((unsigned long)new_stack, IRQ_STACK_ORDER);
+	new_stack = NULL;
+	new_stack_ptr = NULL;
+}
+
+extern void tboot_switch_stack_call(void (*target_func)(void), u64 new_rsp);
+
+#else /* CONFIG_X86_32 */
+
+#define tboot_pre_stack_switch()			(-1)
+#define tboot_post_stack_switch()			do { } while (0)
+#define tboot_switch_stack_call(target_func, new_rsp)	do { } while (0)
+
+#endif
+
+static vmac_t mem_mac;
+static struct crypto_hash *tfm;
+
+static int tboot_gen_mem_integrity(const uint8_t key[], vmac_t *mac)
+{
+	int i, j, ret;
+	pg_data_t *pgdat;
+	struct hash_desc desc;
+	struct scatterlist sg[1];
+	struct page *page;
+	uint64_t paddr, rstart, rend;
+	unsigned long pfn;
+	uint8_t zeroed_key[VMAC_KEY_LEN];
+
+	if (!tfm)
+		tfm = crypto_alloc_hash("vmac(aes)", 0, CRYPTO_ALG_ASYNC);
+
+	if (IS_ERR(tfm)) {
+		tfm = NULL;
+		return -ENOMEM;
+	}
+
+	desc.tfm = tfm;
+	desc.flags = 0;
+
+	sg_init_table(sg, 1);
+
+	ret = crypto_hash_init(&desc);
+	if (ret)
+		return ret;
+	ret = crypto_hash_setkey(desc.tfm, key, VMAC_KEY_LEN);
+	if (ret)
+		return ret;
+
+	for_each_online_pgdat(pgdat) {
+		unsigned long flags;
+
+		pgdat_resize_lock(pgdat, &flags);
+		for (i = 0, pfn = pgdat->node_start_pfn;
+			i < pgdat->node_spanned_pages;
+			i++, pfn = pgdat->node_start_pfn + i) {
+
+			if (!pfn_valid(pfn) || !page_is_ram(pfn))
+				continue;
+
+			page = pfn_to_page(pfn);
+			paddr = page_to_phys(page);
+
+			/* If pg will be MACed by tboot, no need to MAC here */
+			for (j = 0; j < tboot->num_mac_regions; j++) {
+				rstart = tboot->mac_regions[j].start;
+				rend = rstart +	tboot->mac_regions[j].size;
+				if (((paddr + PAGE_SIZE) <= rstart)
+					|| (rend <= paddr))
+					continue;
+				break;
+			}
+
+			if (j == tboot->num_mac_regions) {
+				sg_set_page(sg, page, PAGE_SIZE, 0);
+#ifdef CONFIG_DEBUG_PAGEALLOC
+			/*
+			 * check if the page we are going to MAC is marked as
+			 * present in the kernel page tables.
+			 */
+			if (!kernel_page_present(page)) {
+				kernel_map_pages(page, 1, 1);
+				ret = crypto_hash_update(&desc, sg, PAGE_SIZE);
+				kernel_map_pages(page, 1, 0);
+			} else
+#endif
+				ret = crypto_hash_update(&desc, sg, PAGE_SIZE);
+				if (ret) {
+					pgdat_resize_unlock(pgdat, &flags);
+					return ret;
+				}
+			}
+		}
+		pgdat_resize_unlock(pgdat, &flags);
+	}
+
+#ifdef CONFIG_X86_64
+	/*
+	 * for stack > 4G, we should MAC the stack in the kernel after switch,
+	 * for stack < 4G, the stack is MACed by tboot
+	 */
+	if (new_stack) {
+		for (i = 0, page = virt_to_page((void *)current_thread_info());
+			i < (1 << THREAD_ORDER);
+			i++, page++) {
+			sg_set_page(sg, page, PAGE_SIZE, 0);
+			ret = crypto_hash_update(&desc, sg, PAGE_SIZE);
+			if (ret)
+				return ret;
+		}
+	}
+#endif
+
+	ret = crypto_hash_final(&desc, (uint8_t *)mac);
+	if (ret)
+		return ret;
+
+	/* Clean the key */
+	memset(zeroed_key, 0, sizeof(zeroed_key));
+	crypto_hash_setkey(desc.tfm, zeroed_key, VMAC_KEY_LEN);
+
+	return 0;
+}
+
  #ifdef CONFIG_ACPI_SLEEP

  static void add_mac_region(phys_addr_t start, unsigned long size)
@@ -196,6 +355,27 @@ static int tboot_setup_sleep(void)

  	/* kernel code + data + bss */
  	add_mac_region(virt_to_phys(_text), _end - _text);
+
+	/* stack */
+#ifdef CONFIG_X86_64
+	/*
+	 * if stack > 4G, we should MAC the stack in the kernel after switch,
+	 * if stack < 4G, the stack is MACed by tboot
+	 */
+	if (new_stack)
+		add_mac_region(virt_to_phys(new_stack),
+				IRQ_STACK_SIZE); /* > 4G */
+	else
+#endif
+		add_mac_region(virt_to_phys(current_thread_info()),
+				THREAD_SIZE); /* < 4G */
+
+	/* MAC userspace memory not handled by tboot */
+	get_random_bytes(tboot->s3_key, sizeof(tboot->s3_key));
+	if (tboot_gen_mem_integrity(tboot->s3_key, &mem_mac)) {
+		panic("tboot: vmac generation failed\n");
+		return -1;
+	}

  	tboot->acpi_sinfo.kernel_s3_resume_vector = acpi_wakeup_address;

@@ -292,6 +472,52 @@ void tboot_sleep(u8 sleep_state, u32 pm1
  	}

  	tboot_shutdown(acpi_shutdown_map[sleep_state]);
+}
+
+static void tboot_sx_resume(void)
+{
+	vmac_t mac;
+
+	if (tboot_gen_mem_integrity(tboot->s3_key, &mac))
+		panic("tboot: vmac generation failed\n");
+	else if (mac != mem_mac)
+#ifdef CONFIG_DEBUG_KERNEL
+		pr_debug("tboot: memory integrity %llx -> %llx\n",
+				mem_mac, mac);
+#else
+		panic("tboot: memory integrity was lost on resume\n");
+#endif
+	else
+		pr_info("memory integrity OK\n");
+
+	/* Clean s3_key */
+	memset(tboot->s3_key, 0, sizeof(tboot->s3_key));
+}
+
+extern void do_suspend_lowlevel(void);
+
+static void tboot_do_suspend_lowlevel_call(void)
+{
+	do_suspend_lowlevel();
+	tboot_sx_resume();
+}
+
+void tboot_do_suspend_lowlevel(void)
+{
+	int ret = -1;
+
+	if (!tboot_enabled()) {
+		do_suspend_lowlevel();
+		return;
+	}
+
+	ret = tboot_pre_stack_switch();
+	if (!ret) {
+		tboot_switch_stack_call(tboot_do_suspend_lowlevel_call,
+					(u64)new_stack_ptr);
+		tboot_post_stack_switch();
+	} else
+		tboot_do_suspend_lowlevel_call();
  }

  static atomic_t ap_wfs_count;
diff -r c878d454dc8b drivers/acpi/sleep.c
--- a/drivers/acpi/sleep.c	Wed Dec 02 01:06:32 2009 -0800
+++ b/drivers/acpi/sleep.c	Thu Dec 03 07:22:17 2009 -0800
@@ -16,6 +16,7 @@
  #include <linux/device.h>
  #include <linux/suspend.h>
  #include <linux/reboot.h>
+#include <linux/tboot.h>

  #include <asm/io.h>

@@ -244,7 +245,7 @@ static int acpi_suspend_enter(suspend_st
  		break;

  	case ACPI_STATE_S3:
-		do_suspend_lowlevel();
+		tboot_do_suspend_lowlevel();
  		break;
  	}

diff -r c878d454dc8b include/linux/mm.h
--- a/include/linux/mm.h	Wed Dec 02 01:06:32 2009 -0800
+++ b/include/linux/mm.h	Thu Dec 03 07:22:17 2009 -0800
@@ -1263,18 +1263,18 @@ static inline void enable_debug_pageallo
  {
  	debug_pagealloc_enabled = 1;
  }
-#ifdef CONFIG_HIBERNATION
+#if defined(CONFIG_HIBERNATION) || defined(CONFIG_INTEL_TXT)
  extern bool kernel_page_present(struct page *page);
-#endif /* CONFIG_HIBERNATION */
+#endif /* CONFIG_HIBERNATION || CONFIG_INTEL_TXT */
  #else
  static inline void
  kernel_map_pages(struct page *page, int numpages, int enable) {}
  static inline void enable_debug_pagealloc(void)
  {
  }
-#ifdef CONFIG_HIBERNATION
+#if defined(CONFIG_HIBERNATION) || defined(CONFIG_INTEL_TXT)
  static inline bool kernel_page_present(struct page *page) { return true; }
-#endif /* CONFIG_HIBERNATION */
+#endif /* CONFIG_HIBERNATION || CONFIG_INTEL_TXT */
  #endif

  extern struct vm_area_struct *get_gate_vma(struct task_struct *tsk);
diff -r c878d454dc8b include/linux/tboot.h
--- a/include/linux/tboot.h	Wed Dec 02 01:06:32 2009 -0800
+++ b/include/linux/tboot.h	Thu Dec 03 07:22:17 2009 -0800
@@ -147,7 +147,7 @@ extern struct acpi_table_header *tboot_g
  extern struct acpi_table_header *tboot_get_dmar_table(
  				      struct acpi_table_header *dmar_tbl);
  extern int tboot_force_iommu(void);
-
+extern void tboot_do_suspend_lowlevel(void);
  #else

  #define tboot_probe()			do { } while (0)
@@ -156,6 +156,7 @@ extern int tboot_force_iommu(void);
  					do { } while (0)
  #define tboot_get_dmar_table(dmar_tbl)	(dmar_tbl)
  #define tboot_force_iommu()		0
+#define tboot_do_suspend_lowlevel()	do_suspend_lowlevel()

  #endif /* !CONFIG_INTEL_TXT */

diff -r c878d454dc8b security/Kconfig
--- a/security/Kconfig	Wed Dec 02 01:06:32 2009 -0800
+++ b/security/Kconfig	Thu Dec 03 07:22:17 2009 -0800
@@ -116,6 +116,8 @@ config INTEL_TXT
  config INTEL_TXT
  	bool "Enable Intel(R) Trusted Execution Technology (Intel(R) TXT)"
  	depends on HAVE_INTEL_TXT
+	select CRYPTO_VMAC
+	select CRYPTO_AES
  	help
  	  This option enables support for booting the kernel with the
  	  Trusted Boot (tboot) module. This will utilize

[-- Attachment #2: s3.patch --]
[-- Type: text/plain, Size: 10252 bytes --]

This patch added verification for userspace memory integrity after S3 resume.
Integrity verification for other memory (say kernel itself) has been done by tboot.

Signed-off-by: Shane Wang <shane.wang@intel.com>
Signed-off-by: Joseph Cihula <joseph.cihula@intel.com>

diff -r c878d454dc8b arch/x86/kernel/entry_64.S
--- a/arch/x86/kernel/entry_64.S	Wed Dec 02 01:06:32 2009 -0800
+++ b/arch/x86/kernel/entry_64.S	Thu Dec 03 07:22:17 2009 -0800
@@ -1275,6 +1275,26 @@ ENTRY(call_softirq)
 	CFI_ENDPROC
 END(call_softirq)
 
+#ifdef CONFIG_INTEL_TXT
+/* void tboot_switch_stack_call(void (*target_func)(void), u64 new_rsp) */
+ENTRY(tboot_switch_stack_call)
+	CFI_STARTPROC
+	push %rbp
+	CFI_ADJUST_CFA_OFFSET	8
+	CFI_REL_OFFSET	rbp,0
+	mov %rsp, %rbp
+	CFI_DEF_CFA_REGISTER	rbp
+	mov %rsi, %rsp
+	push %rbp
+	call *%rdi
+	leaveq
+	CFI_DEF_CFA_REGISTER	rsp
+	CFI_ADJUST_CFA_OFFSET	-8
+	ret
+	CFI_ENDPROC
+END(tboot_switch_stack_call)
+#endif
+
 #ifdef CONFIG_XEN
 zeroentry xen_hypervisor_callback xen_do_hypervisor_callback
 
diff -r c878d454dc8b arch/x86/kernel/tboot.c
--- a/arch/x86/kernel/tboot.c	Wed Dec 02 01:06:32 2009 -0800
+++ b/arch/x86/kernel/tboot.c	Thu Dec 03 07:22:17 2009 -0800
@@ -20,6 +20,7 @@
  */
 
 #include <linux/dma_remapping.h>
+#include <linux/scatterlist.h>
 #include <linux/init_task.h>
 #include <linux/spinlock.h>
 #include <linux/delay.h>
@@ -30,12 +31,17 @@
 #include <linux/pfn.h>
 #include <linux/mm.h>
 #include <linux/tboot.h>
+#include <linux/random.h>
+
+#include <crypto/vmac.h>
+#include <crypto/hash.h>
 
 #include <asm/trampoline.h>
 #include <asm/processor.h>
 #include <asm/bootparam.h>
 #include <asm/pgtable.h>
 #include <asm/pgalloc.h>
+#include <asm/percpu.h>
 #include <asm/fixmap.h>
 #include <asm/proto.h>
 #include <asm/setup.h>
@@ -168,6 +174,159 @@ static void tboot_create_trampoline(void
 		      map_base, map_size);
 }
 
+#ifdef CONFIG_X86_64
+static char *new_stack, *new_stack_ptr;
+
+static int tboot_pre_stack_switch(void)
+{
+	BUG_ON((new_stack != NULL) || (new_stack_ptr != NULL));
+
+	/*
+	 * as long as thread info is above 4G, then switch stack,
+	 * since tboot can't access >4G stack for MACing
+	 */
+	if (!((PFN_PHYS(PFN_DOWN(virt_to_phys(current_thread_info())))
+		+ (PFN_UP(THREAD_SIZE) << PAGE_SHIFT))
+		& 0xffffffff00000000UL))
+		return -1;
+
+	new_stack = (char *)__get_free_pages(GFP_DMA32, IRQ_STACK_ORDER);
+
+	BUG_ON(new_stack == NULL);
+	memset(new_stack, 0, IRQ_STACK_SIZE);
+	new_stack_ptr = new_stack + IRQ_STACK_SIZE - 64;
+
+	return 0;
+}
+
+static void tboot_post_stack_switch(void)
+{
+	BUG_ON((new_stack == NULL) || (new_stack_ptr == NULL));
+
+	free_pages((unsigned long)new_stack, IRQ_STACK_ORDER);
+	new_stack = NULL;
+	new_stack_ptr = NULL;
+}
+
+extern void tboot_switch_stack_call(void (*target_func)(void), u64 new_rsp);
+
+#else /* CONFIG_X86_32 */
+
+#define tboot_pre_stack_switch()			(-1)
+#define tboot_post_stack_switch()			do { } while (0)
+#define tboot_switch_stack_call(target_func, new_rsp)	do { } while (0)
+
+#endif
+
+static vmac_t mem_mac;
+static struct crypto_hash *tfm;
+
+static int tboot_gen_mem_integrity(const uint8_t key[], vmac_t *mac)
+{
+	int i, j, ret;
+	pg_data_t *pgdat;
+	struct hash_desc desc;
+	struct scatterlist sg[1];
+	struct page *page;
+	uint64_t paddr, rstart, rend;
+	unsigned long pfn;
+	uint8_t zeroed_key[VMAC_KEY_LEN];
+
+	if (!tfm)
+		tfm = crypto_alloc_hash("vmac(aes)", 0, CRYPTO_ALG_ASYNC);
+
+	if (IS_ERR(tfm)) {
+		tfm = NULL;
+		return -ENOMEM;
+	}
+
+	desc.tfm = tfm;
+	desc.flags = 0;
+
+	sg_init_table(sg, 1);
+
+	ret = crypto_hash_init(&desc);
+	if (ret)
+		return ret;
+	ret = crypto_hash_setkey(desc.tfm, key, VMAC_KEY_LEN);
+	if (ret)
+		return ret;
+
+	for_each_online_pgdat(pgdat) {
+		unsigned long flags;
+
+		pgdat_resize_lock(pgdat, &flags);
+		for (i = 0, pfn = pgdat->node_start_pfn;
+			i < pgdat->node_spanned_pages;
+			i++, pfn = pgdat->node_start_pfn + i) {
+
+			if (!pfn_valid(pfn) || !page_is_ram(pfn))
+				continue;
+
+			page = pfn_to_page(pfn);
+			paddr = page_to_phys(page);
+
+			/* If pg will be MACed by tboot, no need to MAC here */
+			for (j = 0; j < tboot->num_mac_regions; j++) {
+				rstart = tboot->mac_regions[j].start;
+				rend = rstart +	tboot->mac_regions[j].size;
+				if (((paddr + PAGE_SIZE) <= rstart)
+					|| (rend <= paddr))
+					continue;
+				break;
+			}
+
+			if (j == tboot->num_mac_regions) {
+				sg_set_page(sg, page, PAGE_SIZE, 0);
+#ifdef CONFIG_DEBUG_PAGEALLOC
+			/*
+			 * check if the page we are going to MAC is marked as
+			 * present in the kernel page tables.
+			 */
+			if (!kernel_page_present(page)) {
+				kernel_map_pages(page, 1, 1);
+				ret = crypto_hash_update(&desc, sg, PAGE_SIZE);
+				kernel_map_pages(page, 1, 0);
+			} else
+#endif
+				ret = crypto_hash_update(&desc, sg, PAGE_SIZE);
+				if (ret) {
+					pgdat_resize_unlock(pgdat, &flags);
+					return ret;
+				}
+			}
+		}
+		pgdat_resize_unlock(pgdat, &flags);
+	}
+
+#ifdef CONFIG_X86_64
+	/*
+	 * for stack > 4G, we should MAC the stack in the kernel after switch,
+	 * for stack < 4G, the stack is MACed by tboot
+	 */
+	if (new_stack) {
+		for (i = 0, page = virt_to_page((void *)current_thread_info());
+			i < (1 << THREAD_ORDER);
+			i++, page++) {
+			sg_set_page(sg, page, PAGE_SIZE, 0);
+			ret = crypto_hash_update(&desc, sg, PAGE_SIZE);
+			if (ret)
+				return ret;
+		}
+	}
+#endif
+
+	ret = crypto_hash_final(&desc, (uint8_t *)mac);
+	if (ret)
+		return ret;
+
+	/* Clean the key */
+	memset(zeroed_key, 0, sizeof(zeroed_key));
+	crypto_hash_setkey(desc.tfm, zeroed_key, VMAC_KEY_LEN);
+
+	return 0;
+}
+
 #ifdef CONFIG_ACPI_SLEEP
 
 static void add_mac_region(phys_addr_t start, unsigned long size)
@@ -196,6 +355,27 @@ static int tboot_setup_sleep(void)
 
 	/* kernel code + data + bss */
 	add_mac_region(virt_to_phys(_text), _end - _text);
+
+	/* stack */
+#ifdef CONFIG_X86_64
+	/*
+	 * if stack > 4G, we should MAC the stack in the kernel after switch,
+	 * if stack < 4G, the stack is MACed by tboot
+	 */
+	if (new_stack)
+		add_mac_region(virt_to_phys(new_stack),
+				IRQ_STACK_SIZE); /* > 4G */
+	else
+#endif
+		add_mac_region(virt_to_phys(current_thread_info()),
+				THREAD_SIZE); /* < 4G */
+
+	/* MAC userspace memory not handled by tboot */
+	get_random_bytes(tboot->s3_key, sizeof(tboot->s3_key));
+	if (tboot_gen_mem_integrity(tboot->s3_key, &mem_mac)) {
+		panic("tboot: vmac generation failed\n");
+		return -1;
+	}
 
 	tboot->acpi_sinfo.kernel_s3_resume_vector = acpi_wakeup_address;
 
@@ -292,6 +472,52 @@ void tboot_sleep(u8 sleep_state, u32 pm1
 	}
 
 	tboot_shutdown(acpi_shutdown_map[sleep_state]);
+}
+
+static void tboot_sx_resume(void)
+{
+	vmac_t mac;
+
+	if (tboot_gen_mem_integrity(tboot->s3_key, &mac))
+		panic("tboot: vmac generation failed\n");
+	else if (mac != mem_mac)
+#ifdef CONFIG_DEBUG_KERNEL
+		pr_debug("tboot: memory integrity %llx -> %llx\n",
+				mem_mac, mac);
+#else
+		panic("tboot: memory integrity was lost on resume\n");
+#endif
+	else
+		pr_info("memory integrity OK\n");
+
+	/* Clean s3_key */
+	memset(tboot->s3_key, 0, sizeof(tboot->s3_key));
+}
+
+extern void do_suspend_lowlevel(void);
+
+static void tboot_do_suspend_lowlevel_call(void)
+{
+	do_suspend_lowlevel();
+	tboot_sx_resume();
+}
+
+void tboot_do_suspend_lowlevel(void)
+{
+	int ret = -1;
+
+	if (!tboot_enabled()) {
+		do_suspend_lowlevel();
+		return;
+	}
+
+	ret = tboot_pre_stack_switch();
+	if (!ret) {
+		tboot_switch_stack_call(tboot_do_suspend_lowlevel_call,
+					(u64)new_stack_ptr);
+		tboot_post_stack_switch();
+	} else
+		tboot_do_suspend_lowlevel_call();
 }
 
 static atomic_t ap_wfs_count;
diff -r c878d454dc8b drivers/acpi/sleep.c
--- a/drivers/acpi/sleep.c	Wed Dec 02 01:06:32 2009 -0800
+++ b/drivers/acpi/sleep.c	Thu Dec 03 07:22:17 2009 -0800
@@ -16,6 +16,7 @@
 #include <linux/device.h>
 #include <linux/suspend.h>
 #include <linux/reboot.h>
+#include <linux/tboot.h>
 
 #include <asm/io.h>
 
@@ -244,7 +245,7 @@ static int acpi_suspend_enter(suspend_st
 		break;
 
 	case ACPI_STATE_S3:
-		do_suspend_lowlevel();
+		tboot_do_suspend_lowlevel();
 		break;
 	}
 
diff -r c878d454dc8b include/linux/mm.h
--- a/include/linux/mm.h	Wed Dec 02 01:06:32 2009 -0800
+++ b/include/linux/mm.h	Thu Dec 03 07:22:17 2009 -0800
@@ -1263,18 +1263,18 @@ static inline void enable_debug_pageallo
 {
 	debug_pagealloc_enabled = 1;
 }
-#ifdef CONFIG_HIBERNATION
+#if defined(CONFIG_HIBERNATION) || defined(CONFIG_INTEL_TXT)
 extern bool kernel_page_present(struct page *page);
-#endif /* CONFIG_HIBERNATION */
+#endif /* CONFIG_HIBERNATION || CONFIG_INTEL_TXT */
 #else
 static inline void
 kernel_map_pages(struct page *page, int numpages, int enable) {}
 static inline void enable_debug_pagealloc(void)
 {
 }
-#ifdef CONFIG_HIBERNATION
+#if defined(CONFIG_HIBERNATION) || defined(CONFIG_INTEL_TXT)
 static inline bool kernel_page_present(struct page *page) { return true; }
-#endif /* CONFIG_HIBERNATION */
+#endif /* CONFIG_HIBERNATION || CONFIG_INTEL_TXT */
 #endif
 
 extern struct vm_area_struct *get_gate_vma(struct task_struct *tsk);
diff -r c878d454dc8b include/linux/tboot.h
--- a/include/linux/tboot.h	Wed Dec 02 01:06:32 2009 -0800
+++ b/include/linux/tboot.h	Thu Dec 03 07:22:17 2009 -0800
@@ -147,7 +147,7 @@ extern struct acpi_table_header *tboot_g
 extern struct acpi_table_header *tboot_get_dmar_table(
 				      struct acpi_table_header *dmar_tbl);
 extern int tboot_force_iommu(void);
-
+extern void tboot_do_suspend_lowlevel(void);
 #else
 
 #define tboot_probe()			do { } while (0)
@@ -156,6 +156,7 @@ extern int tboot_force_iommu(void);
 					do { } while (0)
 #define tboot_get_dmar_table(dmar_tbl)	(dmar_tbl)
 #define tboot_force_iommu()		0
+#define tboot_do_suspend_lowlevel()	do_suspend_lowlevel()
 
 #endif /* !CONFIG_INTEL_TXT */
 
diff -r c878d454dc8b security/Kconfig
--- a/security/Kconfig	Wed Dec 02 01:06:32 2009 -0800
+++ b/security/Kconfig	Thu Dec 03 07:22:17 2009 -0800
@@ -116,6 +116,8 @@ config INTEL_TXT
 config INTEL_TXT
 	bool "Enable Intel(R) Trusted Execution Technology (Intel(R) TXT)"
 	depends on HAVE_INTEL_TXT
+	select CRYPTO_VMAC
+	select CRYPTO_AES
 	help
 	  This option enables support for booting the kernel with the
 	  Trusted Boot (tboot) module. This will utilize

             reply	other threads:[~2009-12-04  9:12 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-12-04  9:12 Shane Wang [this message]
2009-12-04  8:29 ` Pavel Machek
2009-12-04 16:52   ` Cihula, Joseph
2009-12-04 22:20     ` Pavel Machek
2009-12-04 11:05 ` Andi Kleen
  -- strict thread matches above, loose matches on Subject: below --
2009-09-01  8:52 [PATCH] intel_txt: fix the build errors of intel_txt patch on non-X86 platforms (resend) Shane Wang
2009-09-27  9:07 ` [PATCH] intel_txt: add s3 userspace memory integrity verification Shane Wang
2009-10-04 18:58   ` Pavel Machek
2009-10-04 23:26     ` Andi Kleen
2009-10-15  7:57     ` Wang, Shane
2009-12-04  9:07     ` Wang, Shane
2009-12-04  8:19       ` Pavel Machek
2009-12-04 16:46         ` Cihula, Joseph
2009-12-04 17:13           ` Andi Kleen
2009-12-04 17:41             ` Cihula, Joseph
2009-12-04 20:09               ` Andi Kleen
2009-12-04 20:17                 ` Cihula, Joseph
2009-12-04 20:31                   ` Andi Kleen
2009-12-04 21:27                   ` H. Peter Anvin
2009-12-04 17:53             ` H. Peter Anvin
2009-12-04 20:10               ` Andi Kleen
2009-12-04 22:25               ` Pavel Machek
2009-12-04 22:15           ` Pavel Machek
2009-12-04 22:24             ` H. Peter Anvin
2009-12-04 22:39               ` Pavel Machek
2009-12-04 22:46                 ` H. Peter Anvin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4B18D26B.4040500@intel.com \
    --to=shane.wang@intel.com \
    --cc=andi@firstfloor.org \
    --cc=arjan@linux.intel.com \
    --cc=chrisw@sous-sol.org \
    --cc=hpa@zytor.com \
    --cc=jbeulich@novell.com \
    --cc=jmorris@namei.org \
    --cc=joseph.cihula@intel.com \
    --cc=len.brown@intel.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@lists.linux-foundation.org \
    --cc=mingo@elte.hu \
    --cc=pavel@ucw.cz \
    --cc=peterm@redhat.com \
    --cc=rjw@sisk.pl \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

Powered by JetHome