linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC PATCH 1/3] mm: Introduce VM_IBT for CET legacy code bitmap
@ 2019-06-28 19:41 Yu-cheng Yu
  2019-06-28 19:41 ` [RFC PATCH 2/3] Introduce arch_prctl(ARCH_X86_CET_MARK_LEGACY_CODE) Yu-cheng Yu
                   ` (2 more replies)
  0 siblings, 3 replies; 7+ messages in thread
From: Yu-cheng Yu @ 2019-06-28 19:41 UTC (permalink / raw)
  To: x86, H. Peter Anvin, Thomas Gleixner, Ingo Molnar, linux-kernel,
	linux-doc, linux-mm, linux-arch, linux-api, Arnd Bergmann,
	Andy Lutomirski, Balbir Singh, Borislav Petkov, Cyrill Gorcunov,
	Dave Hansen, Eugene Syromiatnikov, Florian Weimer, H.J. Lu,
	Jann Horn, Jonathan Corbet, Kees Cook, Mike Kravetz, Nadav Amit,
	Oleg Nesterov, Pavel Machek, Peter Zijlstra, Randy Dunlap,
	Ravi V. Shankar, Vedvyas Shanbhogue, Dave Martin
  Cc: Yu-cheng Yu

The previous discussion of the IBT legacy code bitmap is here:

    https://lkml.org/lkml/2019/6/6/1032

When CET Indirect Branch Tracking (IBT) is enabled, the processor expects
every branch target is an ENDBR instruction, or the target's address is
marked as legacy in the legacy code bitmap.  The bitmap covers the whole
user-mode address space (TASK_SIZE_MAX for 64-bit, TASK_SIZE for IA32),
and each bit represents one page of linear address range.

This patch introduces VM_IBT for the bitmap.

Signed-off-by: Yu-cheng Yu <yu-cheng.yu@intel.com>
---
 fs/proc/task_mmu.c | 3 +++
 include/linux/mm.h | 8 ++++++++
 2 files changed, 11 insertions(+)

diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 66725e262a77..d707390285d3 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -663,6 +663,9 @@ static void show_smap_vma_flags(struct seq_file *m, struct vm_area_struct *vma)
 #endif /* CONFIG_ARCH_HAS_PKEYS */
 #ifdef CONFIG_X86_INTEL_SHADOW_STACK_USER
 		[ilog2(VM_SHSTK)]	= "ss",
+#endif
+#ifdef CONFIG_X86_INTEL_BRANCH_TRACKING_USER
+		[ilog2(VM_IBT)]		= "bt",
 #endif
 	};
 	size_t i;
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 921bae5fa7ab..a8da5bdfd7c9 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -299,12 +299,14 @@ extern unsigned int kobjsize(const void *objp);
 #define VM_HIGH_ARCH_BIT_3	35	/* bit only usable on 64-bit architectures */
 #define VM_HIGH_ARCH_BIT_4	36	/* bit only usable on 64-bit architectures */
 #define VM_HIGH_ARCH_BIT_5	37	/* bit only usable on 64-bit architectures */
+#define VM_HIGH_ARCH_BIT_6	38	/* bit only usable on 64-bit architectures */
 #define VM_HIGH_ARCH_0	BIT(VM_HIGH_ARCH_BIT_0)
 #define VM_HIGH_ARCH_1	BIT(VM_HIGH_ARCH_BIT_1)
 #define VM_HIGH_ARCH_2	BIT(VM_HIGH_ARCH_BIT_2)
 #define VM_HIGH_ARCH_3	BIT(VM_HIGH_ARCH_BIT_3)
 #define VM_HIGH_ARCH_4	BIT(VM_HIGH_ARCH_BIT_4)
 #define VM_HIGH_ARCH_5	BIT(VM_HIGH_ARCH_BIT_5)
+#define VM_HIGH_ARCH_6	BIT(VM_HIGH_ARCH_BIT_6)
 #endif /* CONFIG_ARCH_USES_HIGH_VMA_FLAGS */
 
 #ifdef CONFIG_ARCH_HAS_PKEYS
@@ -348,6 +350,12 @@ extern unsigned int kobjsize(const void *objp);
 # define VM_SHSTK	VM_NONE
 #endif
 
+#ifdef CONFIG_X86_INTEL_BRANCH_TRACKING_USER
+# define VM_IBT		VM_HIGH_ARCH_6
+#else
+# define VM_IBT		VM_NONE
+#endif
+
 #ifndef VM_GROWSUP
 # define VM_GROWSUP	VM_NONE
 #endif
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFC PATCH 2/3] Introduce arch_prctl(ARCH_X86_CET_MARK_LEGACY_CODE)
  2019-06-28 19:41 [RFC PATCH 1/3] mm: Introduce VM_IBT for CET legacy code bitmap Yu-cheng Yu
@ 2019-06-28 19:41 ` Yu-cheng Yu
  2019-06-29 23:43   ` Andy Lutomirski
  2019-06-28 19:41 ` [RFC PATCH 3/3] Prevent user from writing to IBT bitmap Yu-cheng Yu
  2019-06-28 21:49 ` [RFC PATCH 1/3] mm: Introduce VM_IBT for CET legacy code bitmap Andy Lutomirski
  2 siblings, 1 reply; 7+ messages in thread
From: Yu-cheng Yu @ 2019-06-28 19:41 UTC (permalink / raw)
  To: x86, H. Peter Anvin, Thomas Gleixner, Ingo Molnar, linux-kernel,
	linux-doc, linux-mm, linux-arch, linux-api, Arnd Bergmann,
	Andy Lutomirski, Balbir Singh, Borislav Petkov, Cyrill Gorcunov,
	Dave Hansen, Eugene Syromiatnikov, Florian Weimer, H.J. Lu,
	Jann Horn, Jonathan Corbet, Kees Cook, Mike Kravetz, Nadav Amit,
	Oleg Nesterov, Pavel Machek, Peter Zijlstra, Randy Dunlap,
	Ravi V. Shankar, Vedvyas Shanbhogue, Dave Martin
  Cc: Yu-cheng Yu

The CET legacy code bitmap covers the whole user-mode address space and is
located at the top of the user-mode address space.  It is allocated only
when the first time arch_prctl(ARCH_X86_MARK_LEGACY_CODE) is called from
an application.

Introduce:

arch_prctl(ARCH_X86_MARK_LEGACY_CODE, unsigned long *buf)
    Mark an address range as IBT legacy code.

    *buf: starting linear address
    *(buf + 1): size of the legacy code
    *(buf + 2): set (1); clear (0)

Signed-off-by: Yu-cheng Yu <yu-cheng.yu@intel.com>
---
 arch/x86/include/asm/cet.h        |   3 +
 arch/x86/include/asm/processor.h  |  13 +++-
 arch/x86/include/uapi/asm/prctl.h |   1 +
 arch/x86/kernel/Makefile          |   2 +-
 arch/x86/kernel/cet_bitmap.c      | 119 ++++++++++++++++++++++++++++++
 arch/x86/kernel/cet_prctl.c       |  15 ++++
 6 files changed, 151 insertions(+), 2 deletions(-)
 create mode 100644 arch/x86/kernel/cet_bitmap.c

diff --git a/arch/x86/include/asm/cet.h b/arch/x86/include/asm/cet.h
index 9e613a6598c9..8ca497850f4a 100644
--- a/arch/x86/include/asm/cet.h
+++ b/arch/x86/include/asm/cet.h
@@ -4,6 +4,7 @@
 
 #ifndef __ASSEMBLY__
 #include <linux/types.h>
+#include <asm/processor.h>
 
 struct task_struct;
 struct sc_ext;
@@ -32,6 +33,7 @@ int cet_restore_signal(bool ia32, struct sc_ext *sc);
 int cet_setup_signal(bool ia32, unsigned long rstor, struct sc_ext *sc);
 int cet_setup_ibt(void);
 int cet_setup_ibt_bitmap(unsigned long bitmap, unsigned long size);
+int cet_mark_legacy_code(unsigned long addr, unsigned long size, unsigned long set);
 void cet_disable_ibt(void);
 #else
 static inline int prctl_cet(int option, unsigned long arg2) { return -EINVAL; }
@@ -44,6 +46,7 @@ static inline int cet_restore_signal(bool ia32, struct sc_ext *sc) { return -EIN
 static inline int cet_setup_signal(bool ia32, unsigned long rstor,
 				   struct sc_ext *sc) { return -EINVAL; }
 static inline int cet_setup_ibt(void) { return -EINVAL; }
+static inline int cet_mark_legacy_code(unsigned long addr, unsigned long size, unsigned long set) { return -EINVAL; }
 static inline void cet_disable_ibt(void) {}
 #endif
 
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 2ae7c1bf4e43..f4600157c73d 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -884,7 +884,18 @@ static inline void spin_lock_prefetch(const void *x)
 #define TASK_SIZE_OF(child)	((test_tsk_thread_flag(child, TIF_ADDR32)) ? \
 					IA32_PAGE_OFFSET : TASK_SIZE_MAX)
 
-#define STACK_TOP		TASK_SIZE_LOW
+#define MMAP_MAX		(unsigned long)(test_thread_flag(TIF_ADDR32) ? \
+					TASK_SIZE : TASK_SIZE_MAX)
+
+#define IBT_BITMAP_SIZE		(round_up(MMAP_MAX, PAGE_SIZE * BITS_PER_BYTE) / \
+					(PAGE_SIZE * BITS_PER_BYTE))
+
+#define IBT_BITMAP_ADDR		(TASK_SIZE - IBT_BITMAP_SIZE)
+
+#define STACK_TOP		(TASK_SIZE_LOW < IBT_BITMAP_ADDR - PAGE_SIZE ? \
+					TASK_SIZE_LOW : \
+					IBT_BITMAP_ADDR - PAGE_SIZE)
+
 #define STACK_TOP_MAX		TASK_SIZE_MAX
 
 #define INIT_THREAD  {						\
diff --git a/arch/x86/include/uapi/asm/prctl.h b/arch/x86/include/uapi/asm/prctl.h
index 5eb9aeb5c662..5f670e70dc00 100644
--- a/arch/x86/include/uapi/asm/prctl.h
+++ b/arch/x86/include/uapi/asm/prctl.h
@@ -20,5 +20,6 @@
 #define ARCH_X86_CET_ALLOC_SHSTK	0x3004
 #define ARCH_X86_CET_GET_LEGACY_BITMAP	0x3005 /* deprecated */
 #define ARCH_X86_CET_SET_LEGACY_BITMAP	0x3006
+#define ARCH_X86_CET_MARK_LEGACY_CODE	0x3007
 
 #endif /* _ASM_X86_PRCTL_H */
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index d908c95306fc..754dde1bf9ac 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -140,7 +140,7 @@ obj-$(CONFIG_UNWINDER_ORC)		+= unwind_orc.o
 obj-$(CONFIG_UNWINDER_FRAME_POINTER)	+= unwind_frame.o
 obj-$(CONFIG_UNWINDER_GUESS)		+= unwind_guess.o
 
-obj-$(CONFIG_X86_INTEL_CET)		+= cet.o cet_prctl.o
+obj-$(CONFIG_X86_INTEL_CET)		+= cet.o cet_prctl.o cet_bitmap.o
 
 ###
 # 64 bit specific files
diff --git a/arch/x86/kernel/cet_bitmap.c b/arch/x86/kernel/cet_bitmap.c
new file mode 100644
index 000000000000..6cb7ac2f66f7
--- /dev/null
+++ b/arch/x86/kernel/cet_bitmap.c
@@ -0,0 +1,119 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include <linux/mm.h>
+#include <linux/mman.h>
+#include <linux/bits.h>
+#include <asm/fpu/internal.h>
+#include <asm/cet.h>
+#include <linux/pagemap.h>
+#include <linux/err.h>
+#include <asm/vdso.h>
+
+static int alloc_bitmap(void)
+{
+	unsigned long addr;
+	u64 msr_ia32_u_cet;
+
+	addr = do_mmap_locked(NULL, IBT_BITMAP_ADDR, IBT_BITMAP_SIZE,
+			      PROT_READ | PROT_WRITE,
+			      MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED_NOREPLACE,
+			      VM_IBT | VM_NORESERVE, NULL);
+
+	if (IS_ERR((void *)addr))
+		return addr;
+
+	current->thread.cet.ibt_bitmap_addr = addr;
+	current->thread.cet.ibt_bitmap_size = IBT_BITMAP_SIZE;
+
+	modify_fpu_regs_begin();
+	rdmsrl(MSR_IA32_U_CET, msr_ia32_u_cet);
+	msr_ia32_u_cet |= (MSR_IA32_CET_LEG_IW_EN | addr);
+	wrmsrl(MSR_IA32_U_CET, msr_ia32_u_cet);
+	modify_fpu_regs_end();
+	return 0;
+}
+
+static int set_user_bits(unsigned long __user *buf, unsigned long buf_size,
+			 unsigned long start_bit, unsigned long end_bit, unsigned long set)
+{
+	unsigned long start_ul, end_ul, total_ul;
+	int i, j, r;
+
+	if (round_up(end_bit, BITS_PER_BYTE) / BITS_PER_BYTE > buf_size)
+		end_bit = buf_size * BITS_PER_BYTE - 1;
+
+	start_ul = start_bit / BITS_PER_LONG;
+	end_ul = end_bit / BITS_PER_LONG;
+	total_ul = (end_ul - start_ul + 1);
+
+	i = start_bit % BITS_PER_LONG;
+	j = end_bit % BITS_PER_LONG;
+
+	r = 0;
+	put_user_try {
+		unsigned long tmp;
+		unsigned long x;
+
+		if (total_ul == 1) {
+			get_user_ex(tmp, &buf[start_ul]);
+
+			if (set != 0)
+				tmp |= GENMASK(j, i);
+			else
+				tmp &= ~GENMASK(j, i);
+
+			put_user_ex(tmp, &buf[start_ul]);
+		} else {
+			get_user_ex(tmp, &buf[start_ul]);
+
+			if (set != 0)
+				tmp |= GENMASK(BITS_PER_LONG - 1, i);
+			else
+				tmp &= ~GENMASK(BITS_PER_LONG - 1, i);
+
+			put_user_ex(tmp, &buf[start_ul]);
+
+			get_user_ex(tmp, &buf[end_ul]);
+
+			if (set != 0)
+				tmp |= GENMASK(j, 0);
+			else
+				tmp &= ~GENMASK(j, 0);
+
+			put_user_ex(tmp, &buf[end_ul]);
+
+			if (set != 0) {
+				for (x = start_ul + 1; x < end_ul; x++)
+					put_user_ex(~0UL, &buf[x]);
+			} else {
+				for (x = start_ul + 1; x < end_ul; x++)
+					put_user_ex(0UL, &buf[x]);
+			}
+		}
+	} put_user_catch(r);
+
+	return r;
+}
+
+int cet_mark_legacy_code(unsigned long addr, unsigned long size, unsigned long set)
+{
+	unsigned long bitmap_addr, bitmap_size;
+	int r;
+
+	if (!current->thread.cet.ibt_enabled)
+		return -EINVAL;
+
+	if (current->thread.cet.ibt_bitmap_size == 0) {
+		r = alloc_bitmap();
+		if (r)
+			return r;
+	}
+
+	bitmap_addr = current->thread.cet.ibt_bitmap_addr;
+	bitmap_size = current->thread.cet.ibt_bitmap_size;
+
+	r = set_user_bits((unsigned long * __user)bitmap_addr, bitmap_size,
+			  addr / PAGE_SIZE, (addr + size - 1) / PAGE_SIZE, set);
+
+	return r;
+}
diff --git a/arch/x86/kernel/cet_prctl.c b/arch/x86/kernel/cet_prctl.c
index b7f37bbc0dd3..b2b7f462482f 100644
--- a/arch/x86/kernel/cet_prctl.c
+++ b/arch/x86/kernel/cet_prctl.c
@@ -68,6 +68,18 @@ static int handle_bitmap(unsigned long arg2)
 	return cet_setup_ibt_bitmap(addr, size);
 }
 
+static int handle_mark_legacy_code(unsigned long arg2)
+{
+	unsigned long addr, size, set;
+
+	if (get_user(addr, (unsigned long __user *)arg2) ||
+	    get_user(size, (unsigned long __user *)arg2 + 1) ||
+	    get_user(set, (unsigned long __user *)arg2 + 2))
+		return -EFAULT;
+
+	return cet_mark_legacy_code(addr, size, set);
+}
+
 int prctl_cet(int option, unsigned long arg2)
 {
 	if (!cpu_x86_cet_enabled())
@@ -100,6 +112,9 @@ int prctl_cet(int option, unsigned long arg2)
 	case ARCH_X86_CET_SET_LEGACY_BITMAP:
 		return handle_bitmap(arg2);
 
+	case ARCH_X86_CET_MARK_LEGACY_CODE:
+		return handle_mark_legacy_code(arg2);
+
 	default:
 		return -EINVAL;
 	}
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [RFC PATCH 3/3] Prevent user from writing to IBT bitmap.
  2019-06-28 19:41 [RFC PATCH 1/3] mm: Introduce VM_IBT for CET legacy code bitmap Yu-cheng Yu
  2019-06-28 19:41 ` [RFC PATCH 2/3] Introduce arch_prctl(ARCH_X86_CET_MARK_LEGACY_CODE) Yu-cheng Yu
@ 2019-06-28 19:41 ` Yu-cheng Yu
  2019-06-29 23:44   ` Andy Lutomirski
  2019-06-28 21:49 ` [RFC PATCH 1/3] mm: Introduce VM_IBT for CET legacy code bitmap Andy Lutomirski
  2 siblings, 1 reply; 7+ messages in thread
From: Yu-cheng Yu @ 2019-06-28 19:41 UTC (permalink / raw)
  To: x86, H. Peter Anvin, Thomas Gleixner, Ingo Molnar, linux-kernel,
	linux-doc, linux-mm, linux-arch, linux-api, Arnd Bergmann,
	Andy Lutomirski, Balbir Singh, Borislav Petkov, Cyrill Gorcunov,
	Dave Hansen, Eugene Syromiatnikov, Florian Weimer, H.J. Lu,
	Jann Horn, Jonathan Corbet, Kees Cook, Mike Kravetz, Nadav Amit,
	Oleg Nesterov, Pavel Machek, Peter Zijlstra, Randy Dunlap,
	Ravi V. Shankar, Vedvyas Shanbhogue, Dave Martin
  Cc: Yu-cheng Yu

The IBT bitmap is visiable from user-mode, but not writable.

Signed-off-by: Yu-cheng Yu <yu-cheng.yu@intel.com>

---
 arch/x86/mm/fault.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 59f4f66e4f2e..231196abb62e 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -1454,6 +1454,13 @@ void do_user_addr_fault(struct pt_regs *regs,
 	 * we can handle it..
 	 */
 good_area:
+#define USER_MODE_WRITE (FAULT_FLAG_WRITE | FAULT_FLAG_USER)
+	if (((flags & USER_MODE_WRITE)  == USER_MODE_WRITE) &&
+	    (vma->vm_flags & VM_IBT)) {
+		bad_area_access_error(regs, hw_error_code, address, vma);
+		return;
+	}
+
 	if (unlikely(access_error(hw_error_code, vma))) {
 		bad_area_access_error(regs, hw_error_code, address, vma);
 		return;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [RFC PATCH 1/3] mm: Introduce VM_IBT for CET legacy code bitmap
  2019-06-28 19:41 [RFC PATCH 1/3] mm: Introduce VM_IBT for CET legacy code bitmap Yu-cheng Yu
  2019-06-28 19:41 ` [RFC PATCH 2/3] Introduce arch_prctl(ARCH_X86_CET_MARK_LEGACY_CODE) Yu-cheng Yu
  2019-06-28 19:41 ` [RFC PATCH 3/3] Prevent user from writing to IBT bitmap Yu-cheng Yu
@ 2019-06-28 21:49 ` Andy Lutomirski
  2 siblings, 0 replies; 7+ messages in thread
From: Andy Lutomirski @ 2019-06-28 21:49 UTC (permalink / raw)
  To: Yu-cheng Yu
  Cc: x86, H. Peter Anvin, Thomas Gleixner, Ingo Molnar, linux-kernel,
	linux-doc, linux-mm, linux-arch, linux-api, Arnd Bergmann,
	Balbir Singh, Borislav Petkov, Cyrill Gorcunov, Dave Hansen,
	Eugene Syromiatnikov, Florian Weimer, H.J. Lu, Jann Horn,
	Jonathan Corbet, Kees Cook, Mike Kravetz, Nadav Amit,
	Oleg Nesterov, Pavel Machek, Peter Zijlstra, Randy Dunlap,
	Ravi V. Shankar, Vedvyas Shanbhogue, Dave Martin



> On Jun 28, 2019, at 12:41 PM, Yu-cheng Yu <yu-cheng.yu@intel.com> wrote:
> 
> The previous discussion of the IBT legacy code bitmap is here:
> 
>    https://lkml.org/lkml/2019/6/6/1032
> 
> When CET Indirect Branch Tracking (IBT) is enabled, the processor expects
> every branch target is an ENDBR instruction, or the target's address is
> marked as legacy in the legacy code bitmap.  The bitmap covers the whole
> user-mode address space (TASK_SIZE_MAX for 64-bit, TASK_SIZE for IA32),
> and each bit represents one page of linear address range.
> 
> This patch introduces VM_IBT for the bitmap.

There’s no need to allocate a bit for this and to clutter up the fault code with special cases. Use _install_special_mapping(), please.  If you need to make it more flexible to cover your use case, please do so.


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC PATCH 2/3] Introduce arch_prctl(ARCH_X86_CET_MARK_LEGACY_CODE)
  2019-06-28 19:41 ` [RFC PATCH 2/3] Introduce arch_prctl(ARCH_X86_CET_MARK_LEGACY_CODE) Yu-cheng Yu
@ 2019-06-29 23:43   ` Andy Lutomirski
  0 siblings, 0 replies; 7+ messages in thread
From: Andy Lutomirski @ 2019-06-29 23:43 UTC (permalink / raw)
  To: Yu-cheng Yu
  Cc: X86 ML, H. Peter Anvin, Thomas Gleixner, Ingo Molnar, LKML,
	open list:DOCUMENTATION, Linux-MM, linux-arch, Linux API,
	Arnd Bergmann, Balbir Singh, Borislav Petkov, Cyrill Gorcunov,
	Dave Hansen, Eugene Syromiatnikov, Florian Weimer, H.J. Lu,
	Jann Horn, Jonathan Corbet, Kees Cook, Mike Kravetz, Nadav Amit,
	Oleg Nesterov, Pavel Machek, Peter Zijlstra, Randy Dunlap,
	Ravi V. Shankar, Vedvyas Shanbhogue, Dave Martin

> On Jun 28, 2019, at 12:41 PM, Yu-cheng Yu <yu-cheng.yu@intel.com> wrote:
>
> The CET legacy code bitmap covers the whole user-mode address space and is
> located at the top of the user-mode address space.  It is allocated only
> when the first time arch_prctl(ARCH_X86_MARK_LEGACY_CODE) is called from
> an application.
>
> Introduce:
>
> arch_prctl(ARCH_X86_MARK_LEGACY_CODE, unsigned long *buf)
>    Mark an address range as IBT legacy code.

How about defining a struct for this?

The change log should discuss where the bitmap goes and how it’s allocated.

> +static int alloc_bitmap(void)
> +{
> +    unsigned long addr;
> +    u64 msr_ia32_u_cet;
> +
> +    addr = do_mmap_locked(NULL, IBT_BITMAP_ADDR, IBT_BITMAP_SIZE,
> +                  PROT_READ | PROT_WRITE,
> +                  MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED_NOREPLACE,
> +                  VM_IBT | VM_NORESERVE, NULL);
> +
> +    if (IS_ERR((void *)addr))
> +        return addr;
> +
> +    current->thread.cet.ibt_bitmap_addr = addr;

addr is a constant. Why are you storing it?  If it ends up not being
constant, you should wire up mremap like the vDSO does.


> +static int set_user_bits(unsigned long __user *buf, unsigned long buf_size,
> +             unsigned long start_bit, unsigned long end_bit, unsigned long set)
> +{
> +    unsigned long start_ul, end_ul, total_ul;
> +    int i, j, r;
> +
> +    if (round_up(end_bit, BITS_PER_BYTE) / BITS_PER_BYTE > buf_size)
> +        end_bit = buf_size * BITS_PER_BYTE - 1;
> +
> +    start_ul = start_bit / BITS_PER_LONG;
> +    end_ul = end_bit / BITS_PER_LONG;
> +    total_ul = (end_ul - start_ul + 1);
> +
> +    i = start_bit % BITS_PER_LONG;
> +    j = end_bit % BITS_PER_LONG;
> +
> +    r = 0;
> +    put_user_try {

put_user_try is obsolete.  Just use get_user(), etc.

Also, I must be missing something fundamental, because this series
claims that user code can't write directly to the bitmap.  This means
that this entire function shouldn't work at all.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC PATCH 3/3] Prevent user from writing to IBT bitmap.
  2019-06-28 19:41 ` [RFC PATCH 3/3] Prevent user from writing to IBT bitmap Yu-cheng Yu
@ 2019-06-29 23:44   ` Andy Lutomirski
  2019-07-01 19:48     ` Yu-cheng Yu
  0 siblings, 1 reply; 7+ messages in thread
From: Andy Lutomirski @ 2019-06-29 23:44 UTC (permalink / raw)
  To: Yu-cheng Yu
  Cc: X86 ML, H. Peter Anvin, Thomas Gleixner, Ingo Molnar, LKML,
	open list:DOCUMENTATION, Linux-MM, linux-arch, Linux API,
	Arnd Bergmann, Balbir Singh, Borislav Petkov, Cyrill Gorcunov,
	Dave Hansen, Eugene Syromiatnikov, Florian Weimer, H.J. Lu,
	Jann Horn, Jonathan Corbet, Kees Cook, Mike Kravetz, Nadav Amit,
	Oleg Nesterov, Pavel Machek, Peter Zijlstra, Randy Dunlap,
	Ravi V. Shankar, Vedvyas Shanbhogue, Dave Martin

On Fri, Jun 28, 2019 at 12:50 PM Yu-cheng Yu <yu-cheng.yu@intel.com> wrote:
>
> The IBT bitmap is visiable from user-mode, but not writable.
>
> Signed-off-by: Yu-cheng Yu <yu-cheng.yu@intel.com>
>
> ---
>  arch/x86/mm/fault.c | 7 +++++++
>  1 file changed, 7 insertions(+)
>
> diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
> index 59f4f66e4f2e..231196abb62e 100644
> --- a/arch/x86/mm/fault.c
> +++ b/arch/x86/mm/fault.c
> @@ -1454,6 +1454,13 @@ void do_user_addr_fault(struct pt_regs *regs,
>          * we can handle it..
>          */
>  good_area:
> +#define USER_MODE_WRITE (FAULT_FLAG_WRITE | FAULT_FLAG_USER)
> +       if (((flags & USER_MODE_WRITE)  == USER_MODE_WRITE) &&
> +           (vma->vm_flags & VM_IBT)) {
> +               bad_area_access_error(regs, hw_error_code, address, vma);
> +               return;
> +       }
> +

Just make the VMA have VM_WRITE and VM_MAYWRITE clear.  No new code
like this should be required.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [RFC PATCH 3/3] Prevent user from writing to IBT bitmap.
  2019-06-29 23:44   ` Andy Lutomirski
@ 2019-07-01 19:48     ` Yu-cheng Yu
  0 siblings, 0 replies; 7+ messages in thread
From: Yu-cheng Yu @ 2019-07-01 19:48 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: X86 ML, H. Peter Anvin, Thomas Gleixner, Ingo Molnar, LKML,
	open list:DOCUMENTATION, Linux-MM, linux-arch, Linux API,
	Arnd Bergmann, Balbir Singh, Borislav Petkov, Cyrill Gorcunov,
	Dave Hansen, Eugene Syromiatnikov, Florian Weimer, H.J. Lu,
	Jann Horn, Jonathan Corbet, Kees Cook, Mike Kravetz, Nadav Amit,
	Oleg Nesterov, Pavel Machek, Peter Zijlstra, Randy Dunlap,
	Ravi V. Shankar, Vedvyas Shanbhogue, Dave Martin

On Sat, 2019-06-29 at 16:44 -0700, Andy Lutomirski wrote:
> On Fri, Jun 28, 2019 at 12:50 PM Yu-cheng Yu <yu-cheng.yu@intel.com> wrote:
> > 
> > The IBT bitmap is visiable from user-mode, but not writable.
> > 
> > Signed-off-by: Yu-cheng Yu <yu-cheng.yu@intel.com>
> > 
> > ---
> >  arch/x86/mm/fault.c | 7 +++++++
> >  1 file changed, 7 insertions(+)
> > 
> > diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
> > index 59f4f66e4f2e..231196abb62e 100644
> > --- a/arch/x86/mm/fault.c
> > +++ b/arch/x86/mm/fault.c
> > @@ -1454,6 +1454,13 @@ void do_user_addr_fault(struct pt_regs *regs,
> >          * we can handle it..
> >          */
> >  good_area:
> > +#define USER_MODE_WRITE (FAULT_FLAG_WRITE | FAULT_FLAG_USER)
> > +       if (((flags & USER_MODE_WRITE)  == USER_MODE_WRITE) &&
> > +           (vma->vm_flags & VM_IBT)) {
> > +               bad_area_access_error(regs, hw_error_code, address, vma);
> > +               return;
> > +       }
> > +
> 
> Just make the VMA have VM_WRITE and VM_MAYWRITE clear.  No new code
> like this should be required.

Ok, I will work on that.

Thanks,
Yu-cheng

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2019-07-01 19:57 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-28 19:41 [RFC PATCH 1/3] mm: Introduce VM_IBT for CET legacy code bitmap Yu-cheng Yu
2019-06-28 19:41 ` [RFC PATCH 2/3] Introduce arch_prctl(ARCH_X86_CET_MARK_LEGACY_CODE) Yu-cheng Yu
2019-06-29 23:43   ` Andy Lutomirski
2019-06-28 19:41 ` [RFC PATCH 3/3] Prevent user from writing to IBT bitmap Yu-cheng Yu
2019-06-29 23:44   ` Andy Lutomirski
2019-07-01 19:48     ` Yu-cheng Yu
2019-06-28 21:49 ` [RFC PATCH 1/3] mm: Introduce VM_IBT for CET legacy code bitmap Andy Lutomirski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).