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>
Cc: 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@firstfloor.org" <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>
Subject: [PATCH] intel_txt: add s3 userspace memory integrity verification
Date: Sun, 27 Sep 2009 17:07:28 +0800	[thread overview]
Message-ID: <4ABF2B50.6070106@intel.com> (raw)
In-Reply-To: <4A9CE0B2.5060608@intel.com>

[-- Attachment #1: Type: text/plain, Size: 7677 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 for your comments.
Shane

---
  arch/x86/kernel/tboot.c |  170 ++++++++++++++++++++++++++++++++++++++
  drivers/acpi/sleep.c    |    4
  include/linux/tboot.h   |    7 +
  security/Kconfig        |    2
  4 files changed, 182 insertions(+), 1 deletion(-)


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

diff -r 42870e183bd5 arch/x86/kernel/tboot.c
--- a/arch/x86/kernel/tboot.c	Fri Sep 25 06:06:39 2009 -0400
+++ b/arch/x86/kernel/tboot.c	Fri Sep 25 11:03:04 2009 -0400
@@ -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,80 @@ static void tboot_create_trampoline(void
  		      map_base, map_size);
  }

+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) {
+		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);
+				ret = crypto_hash_update(&desc, sg, PAGE_SIZE);
+				if (ret)
+					return ret;
+			}
+		}
+	}
+	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)
@@ -197,6 +277,16 @@ static int tboot_setup_sleep(void)
  	/* kernel code + data + bss */
  	add_mac_region(virt_to_phys(_text), _end - _text);

+	/* stack */
+	add_mac_region(virt_to_phys(current_thread_info()), THREAD_SIZE);
+
+	/* 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;

  	return 0;
@@ -212,6 +302,68 @@ static int tboot_setup_sleep(void)
  }

  #endif
+
+static struct thread_info *low_ti, *current_ti;
+
+static void tboot_do_stack_switch(struct thread_info *new_ti,
+				struct thread_info *old_ti)
+{
+	memcpy(new_ti, old_ti, THREAD_SIZE);
+#ifdef CONFIG_X86_32
+	asm volatile (
+		" and %0, %%esp;        "
+		" add %1, %%esp;        "
+		: : "i" (THREAD_SIZE - 1), "r" (new_ti));
+#else
+	asm volatile (
+		" and %0, %%rsp;        "
+		" add %1, %%rsp;        "
+		: : "i" (THREAD_SIZE - 1), "r" (new_ti));
+	percpu_write(kernel_stack, (unsigned long)new_ti -
+				KERNEL_STACK_OFFSET + THREAD_SIZE);
+#endif
+	current->stack = new_ti;
+}
+
+void tboot_switch_stack(void)
+{
+	if (!tboot_enabled())
+		return;
+
+	current_ti = current_thread_info();
+
+	/* If thread info is above 4G, then switch stack */
+	if (!((PFN_PHYS(PFN_DOWN(virt_to_phys(current_ti)))
+		+ (PFN_UP(THREAD_SIZE) << PAGE_SHIFT))
+		& 0xffffffff00000000ULL))
+		return;
+
+	if (low_ti == NULL)
+		low_ti = (struct thread_info *)
+				__get_free_pages(GFP_DMA32, THREAD_ORDER);
+
+	tboot_do_stack_switch(low_ti, current_ti);
+}
+
+void tboot_restore_stack(void)
+{
+	if (!tboot_enabled())
+		return;
+
+	if (current_ti == NULL)
+		BUG();
+
+	/* If thread info is above 4G, then restore stack */
+	if (!((PFN_PHYS(PFN_DOWN(virt_to_phys(current_ti)))
+		+ (PFN_UP(THREAD_SIZE) << PAGE_SHIFT))
+		& 0xffffffff00000000ULL))
+		return;
+
+	if (low_ti == NULL)
+		BUG();
+
+	tboot_do_stack_switch(current_ti, low_ti);
+}

  void tboot_shutdown(u32 shutdown_type)
  {
@@ -292,6 +444,24 @@ void tboot_sleep(u8 sleep_state, u32 pm1
  	}

  	tboot_shutdown(acpi_shutdown_map[sleep_state]);
+}
+
+void tboot_sx_resume(void)
+{
+	vmac_t mac;
+
+	if (!tboot_enabled())
+		return;
+
+	if (tboot_gen_mem_integrity(tboot->s3_key, &mac))
+		panic("tboot: vmac generation failed\n");
+	else if (mac != mem_mac)
+		panic("tboot: memory integrity was lost on resume\n");
+	else
+		pr_info("memory integrity OK\n");
+
+	/* Clean s3_key */
+	memset(tboot->s3_key, 0, sizeof(tboot->s3_key));
  }

  static atomic_t ap_wfs_count;
diff -r 42870e183bd5 drivers/acpi/sleep.c
--- a/drivers/acpi/sleep.c	Fri Sep 25 06:06:39 2009 -0400
+++ b/drivers/acpi/sleep.c	Fri Sep 25 11:03:04 2009 -0400
@@ -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,10 @@ static int acpi_suspend_enter(suspend_st
  		break;

  	case ACPI_STATE_S3:
+		tboot_switch_stack();
  		do_suspend_lowlevel();
+		tboot_sx_resume();
+		tboot_restore_stack();
  		break;
  	}

diff -r 42870e183bd5 include/linux/tboot.h
--- a/include/linux/tboot.h	Fri Sep 25 06:06:39 2009 -0400
+++ b/include/linux/tboot.h	Fri Sep 25 11:03:04 2009 -0400
@@ -147,7 +147,9 @@ 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_sx_resume(void);
+extern void tboot_switch_stack(void);
+extern void tboot_restore_stack(void);
  #else

  #define tboot_probe()			do { } while (0)
@@ -156,6 +158,9 @@ 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_sx_resume()		do { } while (0)
+#define tboot_switch_stack()		do { } while (0)
+#define tboot_restore_stack()		do { } while (0)

  #endif /* !CONFIG_INTEL_TXT */

diff -r 42870e183bd5 security/Kconfig
--- a/security/Kconfig	Fri Sep 25 06:06:39 2009 -0400
+++ b/security/Kconfig	Fri Sep 25 11:03:04 2009 -0400
@@ -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_integrity.patch --]
[-- Type: text/plain, Size: 7374 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 42870e183bd5 arch/x86/kernel/tboot.c
--- a/arch/x86/kernel/tboot.c	Fri Sep 25 06:06:39 2009 -0400
+++ b/arch/x86/kernel/tboot.c	Fri Sep 25 11:03:04 2009 -0400
@@ -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,80 @@ static void tboot_create_trampoline(void
 		      map_base, map_size);
 }
 
+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) {
+		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);
+				ret = crypto_hash_update(&desc, sg, PAGE_SIZE);
+				if (ret)
+					return ret;
+			}
+		}
+	}
+	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)
@@ -197,6 +277,16 @@ static int tboot_setup_sleep(void)
 	/* kernel code + data + bss */
 	add_mac_region(virt_to_phys(_text), _end - _text);
 
+	/* stack */
+	add_mac_region(virt_to_phys(current_thread_info()), THREAD_SIZE);
+
+	/* 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;
 
 	return 0;
@@ -212,6 +302,68 @@ static int tboot_setup_sleep(void)
 }
 
 #endif
+
+static struct thread_info *low_ti, *current_ti;
+
+static void tboot_do_stack_switch(struct thread_info *new_ti,
+				struct thread_info *old_ti)
+{
+	memcpy(new_ti, old_ti, THREAD_SIZE);
+#ifdef CONFIG_X86_32
+	asm volatile (
+		" and %0, %%esp;        "
+		" add %1, %%esp;        "
+		: : "i" (THREAD_SIZE - 1), "r" (new_ti));
+#else
+	asm volatile (
+		" and %0, %%rsp;        "
+		" add %1, %%rsp;        "
+		: : "i" (THREAD_SIZE - 1), "r" (new_ti));
+	percpu_write(kernel_stack, (unsigned long)new_ti -
+				KERNEL_STACK_OFFSET + THREAD_SIZE);
+#endif
+	current->stack = new_ti;
+}
+
+void tboot_switch_stack(void)
+{
+	if (!tboot_enabled())
+		return;
+
+	current_ti = current_thread_info();
+
+	/* If thread info is above 4G, then switch stack */
+	if (!((PFN_PHYS(PFN_DOWN(virt_to_phys(current_ti)))
+		+ (PFN_UP(THREAD_SIZE) << PAGE_SHIFT))
+		& 0xffffffff00000000ULL))
+		return;
+
+	if (low_ti == NULL)
+		low_ti = (struct thread_info *)
+				__get_free_pages(GFP_DMA32, THREAD_ORDER);
+
+	tboot_do_stack_switch(low_ti, current_ti);
+}
+
+void tboot_restore_stack(void)
+{
+	if (!tboot_enabled())
+		return;
+
+	if (current_ti == NULL)
+		BUG();
+
+	/* If thread info is above 4G, then restore stack */
+	if (!((PFN_PHYS(PFN_DOWN(virt_to_phys(current_ti)))
+		+ (PFN_UP(THREAD_SIZE) << PAGE_SHIFT))
+		& 0xffffffff00000000ULL))
+		return;
+
+	if (low_ti == NULL)
+		BUG();
+
+	tboot_do_stack_switch(current_ti, low_ti);
+}
 
 void tboot_shutdown(u32 shutdown_type)
 {
@@ -292,6 +444,24 @@ void tboot_sleep(u8 sleep_state, u32 pm1
 	}
 
 	tboot_shutdown(acpi_shutdown_map[sleep_state]);
+}
+
+void tboot_sx_resume(void)
+{
+	vmac_t mac;
+
+	if (!tboot_enabled())
+		return;
+
+	if (tboot_gen_mem_integrity(tboot->s3_key, &mac))
+		panic("tboot: vmac generation failed\n");
+	else if (mac != mem_mac)
+		panic("tboot: memory integrity was lost on resume\n");
+	else
+		pr_info("memory integrity OK\n");
+
+	/* Clean s3_key */
+	memset(tboot->s3_key, 0, sizeof(tboot->s3_key));
 }
 
 static atomic_t ap_wfs_count;
diff -r 42870e183bd5 drivers/acpi/sleep.c
--- a/drivers/acpi/sleep.c	Fri Sep 25 06:06:39 2009 -0400
+++ b/drivers/acpi/sleep.c	Fri Sep 25 11:03:04 2009 -0400
@@ -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,10 @@ static int acpi_suspend_enter(suspend_st
 		break;
 
 	case ACPI_STATE_S3:
+		tboot_switch_stack();
 		do_suspend_lowlevel();
+		tboot_sx_resume();
+		tboot_restore_stack();
 		break;
 	}
 
diff -r 42870e183bd5 include/linux/tboot.h
--- a/include/linux/tboot.h	Fri Sep 25 06:06:39 2009 -0400
+++ b/include/linux/tboot.h	Fri Sep 25 11:03:04 2009 -0400
@@ -147,7 +147,9 @@ 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_sx_resume(void);
+extern void tboot_switch_stack(void);
+extern void tboot_restore_stack(void);
 #else
 
 #define tboot_probe()			do { } while (0)
@@ -156,6 +158,9 @@ 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_sx_resume()		do { } while (0)
+#define tboot_switch_stack()		do { } while (0)
+#define tboot_restore_stack()		do { } while (0)
 
 #endif /* !CONFIG_INTEL_TXT */
 
diff -r 42870e183bd5 security/Kconfig
--- a/security/Kconfig	Fri Sep 25 06:06:39 2009 -0400
+++ b/security/Kconfig	Fri Sep 25 11:03:04 2009 -0400
@@ -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-09-27  9:07 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 ` Shane Wang [this message]
2009-09-29  2:27   ` [PATCH] intel_txt: fix the buggy timeout warning logic in tboot Shane Wang
2009-10-04 18:58   ` [PATCH] intel_txt: add s3 userspace memory integrity verification 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
2010-03-09  8:52     ` [PATCH v2] intel_txt: add support for S3 memory integrity protection within Intel(R) TXT launched kernel Wang, Shane
2010-03-09  9:06       ` Pavel Machek
2010-03-10  6:36       ` [PATCH v3] " Shane Wang
2010-03-10 20:31         ` Rafael J. Wysocki
2010-03-19 21:18         ` [tip:x86/txt] x86, tboot: Add support for S3 memory integrity protection tip-bot for Shane Wang
2009-12-04  9:12 [PATCH] intel_txt: add s3 userspace memory integrity verification Shane Wang
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

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=4ABF2B50.6070106@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=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=peterm@redhat.com \
    /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