[PATCH v5 06/11] x86/cet/ibt: Add arch_prctl functions for IBT

From: Yu-cheng Yu
Date: Thu Oct 11 2018 - 11:22:13 EST


Update ARCH_X86_CET_STATUS and ARCH_X86_CET_DISABLE to include
Indirect Branch Tracking features.

Introduce:

arch_prctl(ARCH_X86_CET_GET_LEGACY_BITMAP, unsigned long *addr)
Enable the Indirect Branch Tracking legacy code bitmap.
Allocate the bitmap if the task does not have one.

The parameter 'addr' is a pointer to a user buffer.
On returning to the caller, the kernel fills the following:

*addr = IBT bitmap base address
*(addr + 1) = IBT bitmap size

Signed-off-by: H.J. Lu <hjl.tools@xxxxxxxxx>
Signed-off-by: Yu-cheng Yu <yu-cheng.yu@xxxxxxxxx>
---
arch/x86/include/uapi/asm/prctl.h | 1 +
arch/x86/kernel/cet_prctl.c | 35 +++++++++++++++++++++++++++++++
2 files changed, 36 insertions(+)

diff --git a/arch/x86/include/uapi/asm/prctl.h b/arch/x86/include/uapi/asm/prctl.h
index d962f0ec9ccf..fd4eae92c733 100644
--- a/arch/x86/include/uapi/asm/prctl.h
+++ b/arch/x86/include/uapi/asm/prctl.h
@@ -18,5 +18,6 @@
#define ARCH_X86_CET_DISABLE 0x3002
#define ARCH_X86_CET_LOCK 0x3003
#define ARCH_X86_CET_ALLOC_SHSTK 0x3004
+#define ARCH_X86_CET_GET_LEGACY_BITMAP 0x3005

#endif /* _ASM_X86_PRCTL_H */
diff --git a/arch/x86/kernel/cet_prctl.c b/arch/x86/kernel/cet_prctl.c
index 320dbb620d61..dc7e9785f5e7 100644
--- a/arch/x86/kernel/cet_prctl.c
+++ b/arch/x86/kernel/cet_prctl.c
@@ -21,6 +21,8 @@ static int handle_get_status(unsigned long arg2)

if (current->thread.cet.shstk_enabled)
features |= GNU_PROPERTY_X86_FEATURE_1_SHSTK;
+ if (current->thread.cet.ibt_enabled)
+ features |= GNU_PROPERTY_X86_FEATURE_1_IBT;

shstk_base = current->thread.cet.shstk_base;
shstk_size = current->thread.cet.shstk_size;
@@ -56,6 +58,31 @@ static int handle_alloc_shstk(unsigned long arg2)
return 0;
}

+static int handle_bitmap(unsigned long arg2)
+{
+ unsigned long addr, size;
+
+ if (current->thread.cet.ibt_enabled) {
+ int err;
+
+ err = cet_setup_ibt_bitmap();
+ if (err)
+ return err;
+
+ addr = current->thread.cet.ibt_bitmap_addr;
+ size = current->thread.cet.ibt_bitmap_size;
+ } else {
+ addr = 0;
+ size = 0;
+ }
+
+ if (put_user(addr, (unsigned long __user *)arg2) ||
+ put_user(size, (unsigned long __user *)arg2 + 1))
+ return -EFAULT;
+
+ return 0;
+}
+
int prctl_cet(int option, unsigned long arg2)
{
if (!cpu_x86_cet_enabled())
@@ -70,6 +97,8 @@ int prctl_cet(int option, unsigned long arg2)
return -EPERM;
if (arg2 & GNU_PROPERTY_X86_FEATURE_1_SHSTK)
cet_disable_free_shstk(current);
+ if (arg2 & GNU_PROPERTY_X86_FEATURE_1_IBT)
+ cet_disable_ibt();

return 0;

@@ -80,6 +109,12 @@ int prctl_cet(int option, unsigned long arg2)
case ARCH_X86_CET_ALLOC_SHSTK:
return handle_alloc_shstk(arg2);

+ /*
+ * Allocate legacy bitmap and return address & size to user.
+ */
+ case ARCH_X86_CET_GET_LEGACY_BITMAP:
+ return handle_bitmap(arg2);
+
default:
return -EINVAL;
}
--
2.17.1