All of lore.kernel.org
 help / color / mirror / Atom feed
From: Tycho Andersen <tycho@docker.com>
To: linux-kernel@vger.kernel.org
Cc: linux-mm@kvack.org, kernel-hardening@lists.openwall.com,
	Marco Benatto <marco.antonio.780@gmail.com>,
	Juerg Haefliger <juerg.haefliger@canonical.com>,
	Tycho Andersen <tycho@docker.com>
Subject: [kernel-hardening] [PATCH v6 11/11] lkdtm: Add test for XPFO
Date: Thu,  7 Sep 2017 11:36:09 -0600	[thread overview]
Message-ID: <20170907173609.22696-12-tycho@docker.com> (raw)
In-Reply-To: <20170907173609.22696-1-tycho@docker.com>

From: Juerg Haefliger <juerg.haefliger@canonical.com>

This test simply reads from userspace memory via the kernel's linear
map.

v6: * drop an #ifdef, just let the test fail if XPFO is not supported
    * add XPFO_SMP test to try and test the case when one CPU does an xpfo
      unmap of an address, that it can't be used accidentally by other
      CPUs.

Signed-off-by: Juerg Haefliger <juerg.haefliger@canonical.com>
Signed-off-by: Tycho Andersen <tycho@docker.com>
Tested-by: Marco Benatto <marco.antonio.780@gmail.com>
---
 drivers/misc/Makefile     |   1 +
 drivers/misc/lkdtm.h      |   5 ++
 drivers/misc/lkdtm_core.c |   3 +
 drivers/misc/lkdtm_xpfo.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 203 insertions(+)

diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index b0b766416306..8447b42a447d 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -62,6 +62,7 @@ lkdtm-$(CONFIG_LKDTM)		+= lkdtm_heap.o
 lkdtm-$(CONFIG_LKDTM)		+= lkdtm_perms.o
 lkdtm-$(CONFIG_LKDTM)		+= lkdtm_rodata_objcopy.o
 lkdtm-$(CONFIG_LKDTM)		+= lkdtm_usercopy.o
+lkdtm-$(CONFIG_LKDTM)		+= lkdtm_xpfo.o
 
 KCOV_INSTRUMENT_lkdtm_rodata.o	:= n
 
diff --git a/drivers/misc/lkdtm.h b/drivers/misc/lkdtm.h
index 3b4976396ec4..34a6ee37f216 100644
--- a/drivers/misc/lkdtm.h
+++ b/drivers/misc/lkdtm.h
@@ -64,4 +64,9 @@ void lkdtm_USERCOPY_STACK_FRAME_FROM(void);
 void lkdtm_USERCOPY_STACK_BEYOND(void);
 void lkdtm_USERCOPY_KERNEL(void);
 
+/* lkdtm_xpfo.c */
+void lkdtm_XPFO_READ_USER(void);
+void lkdtm_XPFO_READ_USER_HUGE(void);
+void lkdtm_XPFO_SMP(void);
+
 #endif
diff --git a/drivers/misc/lkdtm_core.c b/drivers/misc/lkdtm_core.c
index 42d2b8e31e6b..9544e329de4b 100644
--- a/drivers/misc/lkdtm_core.c
+++ b/drivers/misc/lkdtm_core.c
@@ -235,6 +235,9 @@ struct crashtype crashtypes[] = {
 	CRASHTYPE(USERCOPY_STACK_FRAME_FROM),
 	CRASHTYPE(USERCOPY_STACK_BEYOND),
 	CRASHTYPE(USERCOPY_KERNEL),
+	CRASHTYPE(XPFO_READ_USER),
+	CRASHTYPE(XPFO_READ_USER_HUGE),
+	CRASHTYPE(XPFO_SMP),
 };
 
 
diff --git a/drivers/misc/lkdtm_xpfo.c b/drivers/misc/lkdtm_xpfo.c
new file mode 100644
index 000000000000..d903063bdd0b
--- /dev/null
+++ b/drivers/misc/lkdtm_xpfo.c
@@ -0,0 +1,194 @@
+/*
+ * This is for all the tests related to XPFO (eXclusive Page Frame Ownership).
+ */
+
+#include "lkdtm.h"
+
+#include <linux/cpumask.h>
+#include <linux/mman.h>
+#include <linux/uaccess.h>
+#include <linux/xpfo.h>
+#include <linux/kthread.h>
+
+#include <linux/delay.h>
+#include <linux/sched/task.h>
+
+#define XPFO_DATA 0xdeadbeef
+
+static unsigned long do_map(unsigned long flags)
+{
+	unsigned long user_addr, user_data = XPFO_DATA;
+
+	user_addr = vm_mmap(NULL, 0, PAGE_SIZE,
+			    PROT_READ | PROT_WRITE | PROT_EXEC,
+			    flags, 0);
+	if (user_addr >= TASK_SIZE) {
+		pr_warn("Failed to allocate user memory\n");
+		return 0;
+	}
+
+	if (copy_to_user((void __user *)user_addr, &user_data,
+			 sizeof(user_data))) {
+		pr_warn("copy_to_user failed\n");
+		goto free_user;
+	}
+
+	return user_addr;
+
+free_user:
+	vm_munmap(user_addr, PAGE_SIZE);
+	return 0;
+}
+
+static unsigned long *user_to_kernel(unsigned long user_addr)
+{
+	phys_addr_t phys_addr;
+	void *virt_addr;
+
+	phys_addr = user_virt_to_phys(user_addr);
+	if (!phys_addr) {
+		pr_warn("Failed to get physical address of user memory\n");
+		return NULL;
+	}
+
+	virt_addr = phys_to_virt(phys_addr);
+	if (phys_addr != virt_to_phys(virt_addr)) {
+		pr_warn("Physical address of user memory seems incorrect\n");
+		return NULL;
+	}
+
+	return virt_addr;
+}
+
+static void read_map(unsigned long *virt_addr)
+{
+	pr_info("Attempting bad read from kernel address %p\n", virt_addr);
+	if (*(unsigned long *)virt_addr == XPFO_DATA)
+		pr_err("FAIL: Bad read succeeded?!\n");
+	else
+		pr_err("FAIL: Bad read didn't fail but data is incorrect?!\n");
+}
+
+static void read_user_with_flags(unsigned long flags)
+{
+	unsigned long user_addr, *kernel;
+
+	user_addr = do_map(flags);
+	if (!user_addr) {
+		pr_err("FAIL: map failed\n");
+		return;
+	}
+
+	kernel = user_to_kernel(user_addr);
+	if (!kernel) {
+		pr_err("FAIL: user to kernel conversion failed\n");
+		goto free_user;
+	}
+
+	read_map(kernel);
+
+free_user:
+	vm_munmap(user_addr, PAGE_SIZE);
+}
+
+/* Read from userspace via the kernel's linear map. */
+void lkdtm_XPFO_READ_USER(void)
+{
+	read_user_with_flags(MAP_PRIVATE | MAP_ANONYMOUS);
+}
+
+void lkdtm_XPFO_READ_USER_HUGE(void)
+{
+	read_user_with_flags(MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB);
+}
+
+struct smp_arg {
+	unsigned long *virt_addr;
+	unsigned int cpu;
+};
+
+static int smp_reader(void *parg)
+{
+	struct smp_arg *arg = parg;
+	unsigned long *virt_addr;
+
+	if (arg->cpu != smp_processor_id()) {
+		pr_err("FAIL: scheduled on wrong CPU?\n");
+		return 0;
+	}
+
+	virt_addr = smp_cond_load_acquire(&arg->virt_addr, VAL != NULL);
+	read_map(virt_addr);
+
+	return 0;
+}
+
+#ifdef CONFIG_X86
+#define XPFO_SMP_KILLED SIGKILL
+#elif CONFIG_ARM64
+#define XPFO_SMP_KILLED SIGSEGV
+#else
+#error unsupported arch
+#endif
+
+/* The idea here is to read from the kernel's map on a different thread than
+ * did the mapping (and thus the TLB flushing), to make sure that the page
+ * faults on other cores too.
+ */
+void lkdtm_XPFO_SMP(void)
+{
+	unsigned long user_addr, *virt_addr;
+	struct task_struct *thread;
+	int ret;
+	struct smp_arg arg;
+
+	if (num_online_cpus() < 2) {
+		pr_err("not enough to do a multi cpu test\n");
+		return;
+	}
+
+	arg.virt_addr = NULL;
+	arg.cpu = (smp_processor_id() + 1) % num_online_cpus();
+	thread = kthread_create(smp_reader, &arg, "lkdtm_xpfo_test");
+	if (IS_ERR(thread)) {
+		pr_err("couldn't create kthread? %ld\n", PTR_ERR(thread));
+		return;
+	}
+
+	kthread_bind(thread, arg.cpu);
+	get_task_struct(thread);
+	wake_up_process(thread);
+
+	user_addr = do_map(MAP_PRIVATE | MAP_ANONYMOUS);
+	if (!user_addr)
+		goto kill_thread;
+
+	virt_addr = user_to_kernel(user_addr);
+	if (!virt_addr) {
+		/*
+		 * let's store something that will fail, so we can unblock the
+		 * thread
+		 */
+		smp_store_release(&arg.virt_addr, &arg);
+		goto free_user;
+	}
+
+	smp_store_release(&arg.virt_addr, virt_addr);
+
+	/* there must be a better way to do this. */
+	while (1) {
+		if (thread->exit_state)
+			break;
+		msleep_interruptible(100);
+	}
+
+free_user:
+	if (user_addr)
+		vm_munmap(user_addr, PAGE_SIZE);
+
+kill_thread:
+	ret = kthread_stop(thread);
+	if (ret != XPFO_SMP_KILLED)
+		pr_err("FAIL: thread wasn't killed: %d\n", ret);
+	put_task_struct(thread);
+}
-- 
2.11.0

WARNING: multiple messages have this Message-ID (diff)
From: Tycho Andersen <tycho@docker.com>
To: linux-kernel@vger.kernel.org
Cc: linux-mm@kvack.org, kernel-hardening@lists.openwall.com,
	Marco Benatto <marco.antonio.780@gmail.com>,
	Juerg Haefliger <juerg.haefliger@canonical.com>,
	Tycho Andersen <tycho@docker.com>
Subject: [PATCH v6 11/11] lkdtm: Add test for XPFO
Date: Thu,  7 Sep 2017 11:36:09 -0600	[thread overview]
Message-ID: <20170907173609.22696-12-tycho@docker.com> (raw)
In-Reply-To: <20170907173609.22696-1-tycho@docker.com>

From: Juerg Haefliger <juerg.haefliger@canonical.com>

This test simply reads from userspace memory via the kernel's linear
map.

v6: * drop an #ifdef, just let the test fail if XPFO is not supported
    * add XPFO_SMP test to try and test the case when one CPU does an xpfo
      unmap of an address, that it can't be used accidentally by other
      CPUs.

Signed-off-by: Juerg Haefliger <juerg.haefliger@canonical.com>
Signed-off-by: Tycho Andersen <tycho@docker.com>
Tested-by: Marco Benatto <marco.antonio.780@gmail.com>
---
 drivers/misc/Makefile     |   1 +
 drivers/misc/lkdtm.h      |   5 ++
 drivers/misc/lkdtm_core.c |   3 +
 drivers/misc/lkdtm_xpfo.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 203 insertions(+)

diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index b0b766416306..8447b42a447d 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -62,6 +62,7 @@ lkdtm-$(CONFIG_LKDTM)		+= lkdtm_heap.o
 lkdtm-$(CONFIG_LKDTM)		+= lkdtm_perms.o
 lkdtm-$(CONFIG_LKDTM)		+= lkdtm_rodata_objcopy.o
 lkdtm-$(CONFIG_LKDTM)		+= lkdtm_usercopy.o
+lkdtm-$(CONFIG_LKDTM)		+= lkdtm_xpfo.o
 
 KCOV_INSTRUMENT_lkdtm_rodata.o	:= n
 
diff --git a/drivers/misc/lkdtm.h b/drivers/misc/lkdtm.h
index 3b4976396ec4..34a6ee37f216 100644
--- a/drivers/misc/lkdtm.h
+++ b/drivers/misc/lkdtm.h
@@ -64,4 +64,9 @@ void lkdtm_USERCOPY_STACK_FRAME_FROM(void);
 void lkdtm_USERCOPY_STACK_BEYOND(void);
 void lkdtm_USERCOPY_KERNEL(void);
 
+/* lkdtm_xpfo.c */
+void lkdtm_XPFO_READ_USER(void);
+void lkdtm_XPFO_READ_USER_HUGE(void);
+void lkdtm_XPFO_SMP(void);
+
 #endif
diff --git a/drivers/misc/lkdtm_core.c b/drivers/misc/lkdtm_core.c
index 42d2b8e31e6b..9544e329de4b 100644
--- a/drivers/misc/lkdtm_core.c
+++ b/drivers/misc/lkdtm_core.c
@@ -235,6 +235,9 @@ struct crashtype crashtypes[] = {
 	CRASHTYPE(USERCOPY_STACK_FRAME_FROM),
 	CRASHTYPE(USERCOPY_STACK_BEYOND),
 	CRASHTYPE(USERCOPY_KERNEL),
+	CRASHTYPE(XPFO_READ_USER),
+	CRASHTYPE(XPFO_READ_USER_HUGE),
+	CRASHTYPE(XPFO_SMP),
 };
 
 
diff --git a/drivers/misc/lkdtm_xpfo.c b/drivers/misc/lkdtm_xpfo.c
new file mode 100644
index 000000000000..d903063bdd0b
--- /dev/null
+++ b/drivers/misc/lkdtm_xpfo.c
@@ -0,0 +1,194 @@
+/*
+ * This is for all the tests related to XPFO (eXclusive Page Frame Ownership).
+ */
+
+#include "lkdtm.h"
+
+#include <linux/cpumask.h>
+#include <linux/mman.h>
+#include <linux/uaccess.h>
+#include <linux/xpfo.h>
+#include <linux/kthread.h>
+
+#include <linux/delay.h>
+#include <linux/sched/task.h>
+
+#define XPFO_DATA 0xdeadbeef
+
+static unsigned long do_map(unsigned long flags)
+{
+	unsigned long user_addr, user_data = XPFO_DATA;
+
+	user_addr = vm_mmap(NULL, 0, PAGE_SIZE,
+			    PROT_READ | PROT_WRITE | PROT_EXEC,
+			    flags, 0);
+	if (user_addr >= TASK_SIZE) {
+		pr_warn("Failed to allocate user memory\n");
+		return 0;
+	}
+
+	if (copy_to_user((void __user *)user_addr, &user_data,
+			 sizeof(user_data))) {
+		pr_warn("copy_to_user failed\n");
+		goto free_user;
+	}
+
+	return user_addr;
+
+free_user:
+	vm_munmap(user_addr, PAGE_SIZE);
+	return 0;
+}
+
+static unsigned long *user_to_kernel(unsigned long user_addr)
+{
+	phys_addr_t phys_addr;
+	void *virt_addr;
+
+	phys_addr = user_virt_to_phys(user_addr);
+	if (!phys_addr) {
+		pr_warn("Failed to get physical address of user memory\n");
+		return NULL;
+	}
+
+	virt_addr = phys_to_virt(phys_addr);
+	if (phys_addr != virt_to_phys(virt_addr)) {
+		pr_warn("Physical address of user memory seems incorrect\n");
+		return NULL;
+	}
+
+	return virt_addr;
+}
+
+static void read_map(unsigned long *virt_addr)
+{
+	pr_info("Attempting bad read from kernel address %p\n", virt_addr);
+	if (*(unsigned long *)virt_addr == XPFO_DATA)
+		pr_err("FAIL: Bad read succeeded?!\n");
+	else
+		pr_err("FAIL: Bad read didn't fail but data is incorrect?!\n");
+}
+
+static void read_user_with_flags(unsigned long flags)
+{
+	unsigned long user_addr, *kernel;
+
+	user_addr = do_map(flags);
+	if (!user_addr) {
+		pr_err("FAIL: map failed\n");
+		return;
+	}
+
+	kernel = user_to_kernel(user_addr);
+	if (!kernel) {
+		pr_err("FAIL: user to kernel conversion failed\n");
+		goto free_user;
+	}
+
+	read_map(kernel);
+
+free_user:
+	vm_munmap(user_addr, PAGE_SIZE);
+}
+
+/* Read from userspace via the kernel's linear map. */
+void lkdtm_XPFO_READ_USER(void)
+{
+	read_user_with_flags(MAP_PRIVATE | MAP_ANONYMOUS);
+}
+
+void lkdtm_XPFO_READ_USER_HUGE(void)
+{
+	read_user_with_flags(MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB);
+}
+
+struct smp_arg {
+	unsigned long *virt_addr;
+	unsigned int cpu;
+};
+
+static int smp_reader(void *parg)
+{
+	struct smp_arg *arg = parg;
+	unsigned long *virt_addr;
+
+	if (arg->cpu != smp_processor_id()) {
+		pr_err("FAIL: scheduled on wrong CPU?\n");
+		return 0;
+	}
+
+	virt_addr = smp_cond_load_acquire(&arg->virt_addr, VAL != NULL);
+	read_map(virt_addr);
+
+	return 0;
+}
+
+#ifdef CONFIG_X86
+#define XPFO_SMP_KILLED SIGKILL
+#elif CONFIG_ARM64
+#define XPFO_SMP_KILLED SIGSEGV
+#else
+#error unsupported arch
+#endif
+
+/* The idea here is to read from the kernel's map on a different thread than
+ * did the mapping (and thus the TLB flushing), to make sure that the page
+ * faults on other cores too.
+ */
+void lkdtm_XPFO_SMP(void)
+{
+	unsigned long user_addr, *virt_addr;
+	struct task_struct *thread;
+	int ret;
+	struct smp_arg arg;
+
+	if (num_online_cpus() < 2) {
+		pr_err("not enough to do a multi cpu test\n");
+		return;
+	}
+
+	arg.virt_addr = NULL;
+	arg.cpu = (smp_processor_id() + 1) % num_online_cpus();
+	thread = kthread_create(smp_reader, &arg, "lkdtm_xpfo_test");
+	if (IS_ERR(thread)) {
+		pr_err("couldn't create kthread? %ld\n", PTR_ERR(thread));
+		return;
+	}
+
+	kthread_bind(thread, arg.cpu);
+	get_task_struct(thread);
+	wake_up_process(thread);
+
+	user_addr = do_map(MAP_PRIVATE | MAP_ANONYMOUS);
+	if (!user_addr)
+		goto kill_thread;
+
+	virt_addr = user_to_kernel(user_addr);
+	if (!virt_addr) {
+		/*
+		 * let's store something that will fail, so we can unblock the
+		 * thread
+		 */
+		smp_store_release(&arg.virt_addr, &arg);
+		goto free_user;
+	}
+
+	smp_store_release(&arg.virt_addr, virt_addr);
+
+	/* there must be a better way to do this. */
+	while (1) {
+		if (thread->exit_state)
+			break;
+		msleep_interruptible(100);
+	}
+
+free_user:
+	if (user_addr)
+		vm_munmap(user_addr, PAGE_SIZE);
+
+kill_thread:
+	ret = kthread_stop(thread);
+	if (ret != XPFO_SMP_KILLED)
+		pr_err("FAIL: thread wasn't killed: %d\n", ret);
+	put_task_struct(thread);
+}
-- 
2.11.0

--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org.  For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>

WARNING: multiple messages have this Message-ID (diff)
From: Tycho Andersen <tycho@docker.com>
To: linux-kernel@vger.kernel.org
Cc: linux-mm@kvack.org, kernel-hardening@lists.openwall.com,
	Marco Benatto <marco.antonio.780@gmail.com>,
	Juerg Haefliger <juerg.haefliger@canonical.com>,
	Tycho Andersen <tycho@docker.com>
Subject: [PATCH v6 11/11] lkdtm: Add test for XPFO
Date: Thu,  7 Sep 2017 11:36:09 -0600	[thread overview]
Message-ID: <20170907173609.22696-12-tycho@docker.com> (raw)
In-Reply-To: <20170907173609.22696-1-tycho@docker.com>

From: Juerg Haefliger <juerg.haefliger@canonical.com>

This test simply reads from userspace memory via the kernel's linear
map.

v6: * drop an #ifdef, just let the test fail if XPFO is not supported
    * add XPFO_SMP test to try and test the case when one CPU does an xpfo
      unmap of an address, that it can't be used accidentally by other
      CPUs.

Signed-off-by: Juerg Haefliger <juerg.haefliger@canonical.com>
Signed-off-by: Tycho Andersen <tycho@docker.com>
Tested-by: Marco Benatto <marco.antonio.780@gmail.com>
---
 drivers/misc/Makefile     |   1 +
 drivers/misc/lkdtm.h      |   5 ++
 drivers/misc/lkdtm_core.c |   3 +
 drivers/misc/lkdtm_xpfo.c | 194 ++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 203 insertions(+)

diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index b0b766416306..8447b42a447d 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -62,6 +62,7 @@ lkdtm-$(CONFIG_LKDTM)		+= lkdtm_heap.o
 lkdtm-$(CONFIG_LKDTM)		+= lkdtm_perms.o
 lkdtm-$(CONFIG_LKDTM)		+= lkdtm_rodata_objcopy.o
 lkdtm-$(CONFIG_LKDTM)		+= lkdtm_usercopy.o
+lkdtm-$(CONFIG_LKDTM)		+= lkdtm_xpfo.o
 
 KCOV_INSTRUMENT_lkdtm_rodata.o	:= n
 
diff --git a/drivers/misc/lkdtm.h b/drivers/misc/lkdtm.h
index 3b4976396ec4..34a6ee37f216 100644
--- a/drivers/misc/lkdtm.h
+++ b/drivers/misc/lkdtm.h
@@ -64,4 +64,9 @@ void lkdtm_USERCOPY_STACK_FRAME_FROM(void);
 void lkdtm_USERCOPY_STACK_BEYOND(void);
 void lkdtm_USERCOPY_KERNEL(void);
 
+/* lkdtm_xpfo.c */
+void lkdtm_XPFO_READ_USER(void);
+void lkdtm_XPFO_READ_USER_HUGE(void);
+void lkdtm_XPFO_SMP(void);
+
 #endif
diff --git a/drivers/misc/lkdtm_core.c b/drivers/misc/lkdtm_core.c
index 42d2b8e31e6b..9544e329de4b 100644
--- a/drivers/misc/lkdtm_core.c
+++ b/drivers/misc/lkdtm_core.c
@@ -235,6 +235,9 @@ struct crashtype crashtypes[] = {
 	CRASHTYPE(USERCOPY_STACK_FRAME_FROM),
 	CRASHTYPE(USERCOPY_STACK_BEYOND),
 	CRASHTYPE(USERCOPY_KERNEL),
+	CRASHTYPE(XPFO_READ_USER),
+	CRASHTYPE(XPFO_READ_USER_HUGE),
+	CRASHTYPE(XPFO_SMP),
 };
 
 
diff --git a/drivers/misc/lkdtm_xpfo.c b/drivers/misc/lkdtm_xpfo.c
new file mode 100644
index 000000000000..d903063bdd0b
--- /dev/null
+++ b/drivers/misc/lkdtm_xpfo.c
@@ -0,0 +1,194 @@
+/*
+ * This is for all the tests related to XPFO (eXclusive Page Frame Ownership).
+ */
+
+#include "lkdtm.h"
+
+#include <linux/cpumask.h>
+#include <linux/mman.h>
+#include <linux/uaccess.h>
+#include <linux/xpfo.h>
+#include <linux/kthread.h>
+
+#include <linux/delay.h>
+#include <linux/sched/task.h>
+
+#define XPFO_DATA 0xdeadbeef
+
+static unsigned long do_map(unsigned long flags)
+{
+	unsigned long user_addr, user_data = XPFO_DATA;
+
+	user_addr = vm_mmap(NULL, 0, PAGE_SIZE,
+			    PROT_READ | PROT_WRITE | PROT_EXEC,
+			    flags, 0);
+	if (user_addr >= TASK_SIZE) {
+		pr_warn("Failed to allocate user memory\n");
+		return 0;
+	}
+
+	if (copy_to_user((void __user *)user_addr, &user_data,
+			 sizeof(user_data))) {
+		pr_warn("copy_to_user failed\n");
+		goto free_user;
+	}
+
+	return user_addr;
+
+free_user:
+	vm_munmap(user_addr, PAGE_SIZE);
+	return 0;
+}
+
+static unsigned long *user_to_kernel(unsigned long user_addr)
+{
+	phys_addr_t phys_addr;
+	void *virt_addr;
+
+	phys_addr = user_virt_to_phys(user_addr);
+	if (!phys_addr) {
+		pr_warn("Failed to get physical address of user memory\n");
+		return NULL;
+	}
+
+	virt_addr = phys_to_virt(phys_addr);
+	if (phys_addr != virt_to_phys(virt_addr)) {
+		pr_warn("Physical address of user memory seems incorrect\n");
+		return NULL;
+	}
+
+	return virt_addr;
+}
+
+static void read_map(unsigned long *virt_addr)
+{
+	pr_info("Attempting bad read from kernel address %p\n", virt_addr);
+	if (*(unsigned long *)virt_addr == XPFO_DATA)
+		pr_err("FAIL: Bad read succeeded?!\n");
+	else
+		pr_err("FAIL: Bad read didn't fail but data is incorrect?!\n");
+}
+
+static void read_user_with_flags(unsigned long flags)
+{
+	unsigned long user_addr, *kernel;
+
+	user_addr = do_map(flags);
+	if (!user_addr) {
+		pr_err("FAIL: map failed\n");
+		return;
+	}
+
+	kernel = user_to_kernel(user_addr);
+	if (!kernel) {
+		pr_err("FAIL: user to kernel conversion failed\n");
+		goto free_user;
+	}
+
+	read_map(kernel);
+
+free_user:
+	vm_munmap(user_addr, PAGE_SIZE);
+}
+
+/* Read from userspace via the kernel's linear map. */
+void lkdtm_XPFO_READ_USER(void)
+{
+	read_user_with_flags(MAP_PRIVATE | MAP_ANONYMOUS);
+}
+
+void lkdtm_XPFO_READ_USER_HUGE(void)
+{
+	read_user_with_flags(MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB);
+}
+
+struct smp_arg {
+	unsigned long *virt_addr;
+	unsigned int cpu;
+};
+
+static int smp_reader(void *parg)
+{
+	struct smp_arg *arg = parg;
+	unsigned long *virt_addr;
+
+	if (arg->cpu != smp_processor_id()) {
+		pr_err("FAIL: scheduled on wrong CPU?\n");
+		return 0;
+	}
+
+	virt_addr = smp_cond_load_acquire(&arg->virt_addr, VAL != NULL);
+	read_map(virt_addr);
+
+	return 0;
+}
+
+#ifdef CONFIG_X86
+#define XPFO_SMP_KILLED SIGKILL
+#elif CONFIG_ARM64
+#define XPFO_SMP_KILLED SIGSEGV
+#else
+#error unsupported arch
+#endif
+
+/* The idea here is to read from the kernel's map on a different thread than
+ * did the mapping (and thus the TLB flushing), to make sure that the page
+ * faults on other cores too.
+ */
+void lkdtm_XPFO_SMP(void)
+{
+	unsigned long user_addr, *virt_addr;
+	struct task_struct *thread;
+	int ret;
+	struct smp_arg arg;
+
+	if (num_online_cpus() < 2) {
+		pr_err("not enough to do a multi cpu test\n");
+		return;
+	}
+
+	arg.virt_addr = NULL;
+	arg.cpu = (smp_processor_id() + 1) % num_online_cpus();
+	thread = kthread_create(smp_reader, &arg, "lkdtm_xpfo_test");
+	if (IS_ERR(thread)) {
+		pr_err("couldn't create kthread? %ld\n", PTR_ERR(thread));
+		return;
+	}
+
+	kthread_bind(thread, arg.cpu);
+	get_task_struct(thread);
+	wake_up_process(thread);
+
+	user_addr = do_map(MAP_PRIVATE | MAP_ANONYMOUS);
+	if (!user_addr)
+		goto kill_thread;
+
+	virt_addr = user_to_kernel(user_addr);
+	if (!virt_addr) {
+		/*
+		 * let's store something that will fail, so we can unblock the
+		 * thread
+		 */
+		smp_store_release(&arg.virt_addr, &arg);
+		goto free_user;
+	}
+
+	smp_store_release(&arg.virt_addr, virt_addr);
+
+	/* there must be a better way to do this. */
+	while (1) {
+		if (thread->exit_state)
+			break;
+		msleep_interruptible(100);
+	}
+
+free_user:
+	if (user_addr)
+		vm_munmap(user_addr, PAGE_SIZE);
+
+kill_thread:
+	ret = kthread_stop(thread);
+	if (ret != XPFO_SMP_KILLED)
+		pr_err("FAIL: thread wasn't killed: %d\n", ret);
+	put_task_struct(thread);
+}
-- 
2.11.0

  parent reply	other threads:[~2017-09-07 17:36 UTC|newest]

Thread overview: 241+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-09-07 17:35 [kernel-hardening] [PATCH v6 00/11] Add support for eXclusive Page Frame Ownership Tycho Andersen
2017-09-07 17:35 ` Tycho Andersen
2017-09-07 17:35 ` Tycho Andersen
2017-09-07 17:35 ` [kernel-hardening] [PATCH v6 01/11] mm: add MAP_HUGETLB support to vm_mmap Tycho Andersen
2017-09-07 17:35   ` Tycho Andersen
2017-09-07 17:35   ` Tycho Andersen
2017-09-08  7:42   ` [kernel-hardening] " Christoph Hellwig
2017-09-08  7:42     ` Christoph Hellwig
2017-09-08  7:42     ` Christoph Hellwig
2017-09-07 17:36 ` [kernel-hardening] [PATCH v6 02/11] x86: always set IF before oopsing from page fault Tycho Andersen
2017-09-07 17:36   ` Tycho Andersen
2017-09-07 17:36   ` Tycho Andersen
2017-09-07 17:36 ` [kernel-hardening] [PATCH v6 03/11] mm, x86: Add support for eXclusive Page Frame Ownership (XPFO) Tycho Andersen
2017-09-07 17:36   ` Tycho Andersen
2017-09-07 17:36   ` Tycho Andersen
2017-09-07 18:33   ` [kernel-hardening] " Ralph Campbell
2017-09-07 18:33     ` Ralph Campbell
2017-09-07 18:33     ` Ralph Campbell
2017-09-07 18:50     ` [kernel-hardening] " Tycho Andersen
2017-09-07 18:50       ` Tycho Andersen
2017-09-07 18:50       ` Tycho Andersen
2017-09-08  7:51   ` [kernel-hardening] " Christoph Hellwig
2017-09-08  7:51     ` Christoph Hellwig
2017-09-08  7:51     ` Christoph Hellwig
2017-09-08 14:58     ` [kernel-hardening] " Tycho Andersen
2017-09-08 14:58       ` Tycho Andersen
2017-09-08 14:58       ` Tycho Andersen
2017-09-09 15:35   ` [kernel-hardening] " Laura Abbott
2017-09-09 15:35     ` Laura Abbott
2017-09-09 15:35     ` Laura Abbott
2017-09-11 15:03     ` [kernel-hardening] " Tycho Andersen
2017-09-11 15:03       ` Tycho Andersen
2017-09-11 15:03       ` Tycho Andersen
2017-09-11  7:24   ` [kernel-hardening] " Yisheng Xie
2017-09-11  7:24     ` Yisheng Xie
2017-09-11  7:24     ` Yisheng Xie
2017-09-11 14:50     ` [kernel-hardening] " Tycho Andersen
2017-09-11 14:50       ` Tycho Andersen
2017-09-11 14:50       ` Tycho Andersen
2017-09-11 16:03       ` [kernel-hardening] " Juerg Haefliger
2017-09-11 16:03         ` Juerg Haefliger
2017-09-11 16:03         ` Juerg Haefliger
2017-09-11 16:59         ` [kernel-hardening] " Tycho Andersen
2017-09-11 16:59           ` Tycho Andersen
2017-09-11 16:59           ` Tycho Andersen
2017-09-12  8:05         ` [kernel-hardening] " Yisheng Xie
2017-09-12  8:05           ` Yisheng Xie
2017-09-12  8:05           ` Yisheng Xie
2017-09-12 14:36           ` [kernel-hardening] " Tycho Andersen
2017-09-12 14:36             ` Tycho Andersen
2017-09-12 14:36             ` Tycho Andersen
2017-09-12 18:13             ` [kernel-hardening] " Tycho Andersen
2017-09-12 18:13               ` Tycho Andersen
2017-09-12 18:13               ` Tycho Andersen
2017-09-14  6:15               ` [kernel-hardening] " Yisheng Xie
2017-09-14  6:15                 ` Yisheng Xie
2017-09-14  6:15                 ` Yisheng Xie
2017-09-20 23:46               ` [kernel-hardening] " Dave Hansen
2017-09-20 23:46                 ` Dave Hansen
2017-09-20 23:46                 ` Dave Hansen
2017-09-21  0:02                 ` [kernel-hardening] " Tycho Andersen
2017-09-21  0:02                   ` Tycho Andersen
2017-09-21  0:02                   ` Tycho Andersen
2017-09-21  0:04                   ` [kernel-hardening] " Dave Hansen
2017-09-21  0:04                     ` Dave Hansen
2017-09-21  0:04                     ` Dave Hansen
2017-09-11 18:32   ` [kernel-hardening] " Tycho Andersen
2017-09-11 18:32     ` Tycho Andersen
2017-09-11 18:32     ` Tycho Andersen
2017-09-11 21:54     ` [kernel-hardening] " Marco Benatto
2017-09-11 21:54       ` Marco Benatto
2017-09-11 21:54       ` Marco Benatto
2017-09-20 15:48   ` [kernel-hardening] " Dave Hansen
2017-09-20 15:48     ` Dave Hansen
2017-09-20 15:48     ` Dave Hansen
2017-09-20 22:34     ` [kernel-hardening] " Tycho Andersen
2017-09-20 22:34       ` Tycho Andersen
2017-09-20 22:34       ` Tycho Andersen
2017-09-20 23:21       ` [kernel-hardening] " Dave Hansen
2017-09-20 23:21         ` Dave Hansen
2017-09-20 23:21         ` Dave Hansen
2017-09-21  0:09         ` [kernel-hardening] " Tycho Andersen
2017-09-21  0:09           ` Tycho Andersen
2017-09-21  0:09           ` Tycho Andersen
2017-09-21  0:27           ` [kernel-hardening] " Dave Hansen
2017-09-21  0:27             ` Dave Hansen
2017-09-21  0:27             ` Dave Hansen
2017-09-21  1:37             ` [kernel-hardening] " Tycho Andersen
2017-09-21  1:37               ` Tycho Andersen
2017-09-21  1:37               ` Tycho Andersen
2017-11-10  1:09             ` [kernel-hardening] " Tycho Andersen
2017-11-10  1:09               ` Tycho Andersen
2017-11-10  1:09               ` Tycho Andersen
2017-11-13 22:20               ` [kernel-hardening] " Dave Hansen
2017-11-13 22:20                 ` Dave Hansen
2017-11-13 22:20                 ` Dave Hansen
2017-11-13 22:46                 ` [kernel-hardening] " Dave Hansen
2017-11-13 22:46                   ` Dave Hansen
2017-11-13 22:46                   ` Dave Hansen
2017-11-15  0:33                   ` [kernel-hardening] " Tycho Andersen
2017-11-15  0:33                     ` Tycho Andersen
2017-11-15  0:37                     ` Dave Hansen
2017-11-15  0:37                       ` Dave Hansen
2017-11-15  0:42                       ` Tycho Andersen
2017-11-15  0:42                         ` Tycho Andersen
2017-11-15  3:44                   ` Matthew Wilcox
2017-11-15  3:44                     ` Matthew Wilcox
2017-11-15  3:44                     ` Matthew Wilcox
2017-11-15  7:00                     ` [kernel-hardening] " Dave Hansen
2017-11-15  7:00                       ` Dave Hansen
2017-11-15  7:00                       ` Dave Hansen
2017-11-15 14:58                       ` [kernel-hardening] " Matthew Wilcox
2017-11-15 14:58                         ` Matthew Wilcox
2017-11-15 14:58                         ` Matthew Wilcox
2017-11-15 16:20                         ` [kernel-hardening] " Tycho Andersen
2017-11-15 16:20                           ` Tycho Andersen
2017-11-15 21:34                           ` Matthew Wilcox
2017-11-15 21:34                             ` Matthew Wilcox
2017-09-21  0:03   ` Dave Hansen
2017-09-21  0:03     ` Dave Hansen
2017-09-21  0:03     ` Dave Hansen
2017-09-21  0:28   ` [kernel-hardening] " Dave Hansen
2017-09-21  0:28     ` Dave Hansen
2017-09-21  0:28     ` Dave Hansen
2017-09-21  1:04     ` [kernel-hardening] " Tycho Andersen
2017-09-21  1:04       ` Tycho Andersen
2017-09-21  1:04       ` Tycho Andersen
2017-09-07 17:36 ` [kernel-hardening] [PATCH v6 04/11] swiotlb: Map the buffer if it was unmapped by XPFO Tycho Andersen
2017-09-07 17:36   ` Tycho Andersen
2017-09-07 17:36   ` Tycho Andersen
2017-09-07 18:10   ` [kernel-hardening] " Christoph Hellwig
2017-09-07 18:10     ` Christoph Hellwig
2017-09-07 18:10     ` Christoph Hellwig
2017-09-07 18:44     ` [kernel-hardening] " Tycho Andersen
2017-09-07 18:44       ` Tycho Andersen
2017-09-07 18:44       ` Tycho Andersen
2017-09-08  7:13       ` [kernel-hardening] " Christoph Hellwig
2017-09-08  7:13         ` Christoph Hellwig
2017-09-08  7:13         ` Christoph Hellwig
2017-09-07 17:36 ` [kernel-hardening] [PATCH v6 05/11] arm64/mm: Add support for XPFO Tycho Andersen
2017-09-07 17:36   ` Tycho Andersen
2017-09-07 17:36   ` Tycho Andersen
2017-09-07 17:36   ` Tycho Andersen
2017-09-08  7:53   ` [kernel-hardening] " Christoph Hellwig
2017-09-08  7:53     ` Christoph Hellwig
2017-09-08  7:53     ` Christoph Hellwig
2017-09-08  7:53     ` Christoph Hellwig
2017-09-08 17:24     ` [kernel-hardening] " Tycho Andersen
2017-09-08 17:24       ` Tycho Andersen
2017-09-08 17:24       ` Tycho Andersen
2017-09-08 17:24       ` Tycho Andersen
2017-09-14 10:41       ` [kernel-hardening] " Julien Grall
2017-09-14 10:41         ` Julien Grall
2017-09-14 10:41         ` Julien Grall
2017-09-14 10:41         ` Julien Grall
2017-09-14 11:29         ` Juergen Gross
2017-09-14 11:29         ` [kernel-hardening] " Juergen Gross
2017-09-14 11:29           ` Juergen Gross
2017-09-14 11:29           ` Juergen Gross
2017-09-14 11:29           ` Juergen Gross
2017-09-14 10:41       ` Julien Grall
2017-09-08 17:24     ` Tycho Andersen
2017-09-14 18:22   ` [kernel-hardening] " Mark Rutland
2017-09-14 18:22     ` Mark Rutland
2017-09-14 18:22     ` Mark Rutland
2017-09-18 21:27     ` Tycho Andersen
2017-09-18 21:27       ` Tycho Andersen
2017-09-18 21:27       ` Tycho Andersen
2017-09-07 17:36 ` [kernel-hardening] [PATCH v6 06/11] xpfo: add primitives for mapping underlying memory Tycho Andersen
2017-09-07 17:36   ` Tycho Andersen
2017-09-07 17:36   ` Tycho Andersen
2017-09-07 17:36 ` [kernel-hardening] [PATCH v6 07/11] arm64/mm, xpfo: temporarily map dcache regions Tycho Andersen
2017-09-07 17:36   ` Tycho Andersen
2017-09-07 17:36   ` Tycho Andersen
2017-09-07 17:36   ` Tycho Andersen
2017-09-14 18:25   ` [kernel-hardening] " Mark Rutland
2017-09-14 18:25     ` Mark Rutland
2017-09-14 18:25     ` Mark Rutland
2017-09-14 18:25     ` Mark Rutland
2017-09-18 21:29     ` [kernel-hardening] " Tycho Andersen
2017-09-18 21:29       ` Tycho Andersen
2017-09-18 21:29       ` Tycho Andersen
2017-09-18 21:29       ` Tycho Andersen
2017-09-07 17:36 ` [kernel-hardening] [PATCH v6 08/11] arm64/mm: Add support for XPFO to swiotlb Tycho Andersen
2017-09-07 17:36   ` Tycho Andersen
2017-09-07 17:36   ` Tycho Andersen
2017-09-07 17:36   ` Tycho Andersen
2017-09-07 17:36 ` [kernel-hardening] [PATCH v6 09/11] arm64/mm: disable section/contiguous mappings if XPFO is enabled Tycho Andersen
2017-09-07 17:36   ` Tycho Andersen
2017-09-07 17:36   ` Tycho Andersen
2017-09-07 17:36   ` Tycho Andersen
2017-09-09 15:38   ` [kernel-hardening] " Laura Abbott
2017-09-09 15:38     ` Laura Abbott
2017-09-09 15:38     ` Laura Abbott
2017-09-09 15:38     ` Laura Abbott
2017-09-07 17:36 ` [kernel-hardening] [PATCH v6 10/11] mm: add a user_virt_to_phys symbol Tycho Andersen
2017-09-07 17:36   ` Tycho Andersen
2017-09-07 17:36   ` Tycho Andersen
2017-09-07 17:36   ` Tycho Andersen
2017-09-08  7:55   ` [kernel-hardening] " Christoph Hellwig
2017-09-08  7:55     ` Christoph Hellwig
2017-09-08  7:55     ` Christoph Hellwig
2017-09-08  7:55     ` Christoph Hellwig
2017-09-08 15:44     ` [kernel-hardening] " Kees Cook
2017-09-08 15:44       ` Kees Cook
2017-09-08 15:44       ` Kees Cook
2017-09-08 15:44       ` Kees Cook
2017-09-11  7:36       ` [kernel-hardening] " Christoph Hellwig
2017-09-11  7:36         ` Christoph Hellwig
2017-09-11  7:36         ` Christoph Hellwig
2017-09-11  7:36         ` Christoph Hellwig
2017-09-14 18:34   ` [kernel-hardening] " Mark Rutland
2017-09-14 18:34     ` Mark Rutland
2017-09-14 18:34     ` Mark Rutland
2017-09-18 20:56     ` Tycho Andersen
2017-09-18 20:56       ` Tycho Andersen
2017-09-18 20:56       ` Tycho Andersen
2017-09-07 17:36 ` Tycho Andersen [this message]
2017-09-07 17:36   ` [PATCH v6 11/11] lkdtm: Add test for XPFO Tycho Andersen
2017-09-07 17:36   ` Tycho Andersen
2017-09-07 19:08   ` [kernel-hardening] " Kees Cook
2017-09-07 19:08     ` Kees Cook
2017-09-07 19:08     ` Kees Cook
2017-09-10  0:57   ` [kernel-hardening] " kbuild test robot
2017-09-10  0:57     ` kbuild test robot
2017-09-10  0:57     ` kbuild test robot
2017-09-11 10:34 ` [kernel-hardening] Re: [PATCH v6 00/11] Add support for eXclusive Page Frame Ownership Yisheng Xie
2017-09-11 10:34   ` Yisheng Xie
2017-09-11 10:34   ` Yisheng Xie
2017-09-11 15:02   ` [kernel-hardening] " Tycho Andersen
2017-09-11 15:02     ` Tycho Andersen
2017-09-11 15:02     ` Tycho Andersen
2017-09-12  7:07     ` [kernel-hardening] " Yisheng Xie
2017-09-12  7:07       ` Yisheng Xie
2017-09-12  7:07       ` Yisheng Xie
2017-09-12  7:40       ` [kernel-hardening] " Juerg Haefliger
2017-09-12  7:40         ` Juerg Haefliger
2017-09-12  7:40         ` Juerg Haefliger
2017-09-12  8:11         ` [kernel-hardening] " Yisheng Xie
2017-09-12  8:11           ` Yisheng Xie
2017-09-12  8:11           ` Yisheng Xie

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=20170907173609.22696-12-tycho@docker.com \
    --to=tycho@docker.com \
    --cc=juerg.haefliger@canonical.com \
    --cc=kernel-hardening@lists.openwall.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=marco.antonio.780@gmail.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.