Control-flow Enforcement (CET) is a new Intel processor feature that blocks
return/jump-oriented programming attacks. Details are in "Intel 64 and
IA-32 Architectures Software Developer's Manual" [1].
This is the second part of CET and enables Indirect Branch Tracking (IBT).
It is built on top of the shadow stack series.
Changes in v26:
- Rebase to Linus tree v5.12.
Changes in v25:
- Make updates to Kconfig and CPU feature flags for the removal of Kconfig
X86_CET and software-defined X86_FEATURE_CET.
- Update ENDBR definition.
- Rebase to Linus tree v5.12-rc7.
[1] Intel 64 and IA-32 Architectures Software Developer's Manual:
https://software.intel.com/en-us/download/intel-64-and-ia-32-
architectures-sdm-combined-volumes-1-2a-2b-2c-2d-3a-3b-3c-3d-and-4
[2] Indirect Branch Tracking patches v25:
https://lore.kernel.org/r/[email protected]/
H.J. Lu (3):
x86/cet/ibt: Update arch_prctl functions for Indirect Branch Tracking
x86/vdso: Insert endbr32/endbr64 to vDSO
x86/vdso/32: Add ENDBR to __kernel_vsyscall entry point
Yu-cheng Yu (6):
x86/cet/ibt: Add Kconfig option for Indirect Branch Tracking
x86/cet/ibt: Add user-mode Indirect Branch Tracking support
x86/cet/ibt: Handle signals for Indirect Branch Tracking
x86/cet/ibt: Update ELF header parsing for Indirect Branch Tracking
x86/vdso: Introduce ENDBR macro
x86/vdso: Add ENDBR to __vdso_sgx_enter_enclave
arch/x86/Kconfig | 21 +++++++++
arch/x86/entry/vdso/Makefile | 4 ++
arch/x86/entry/vdso/vdso32/system_call.S | 2 +
arch/x86/entry/vdso/vsgx.S | 4 ++
arch/x86/include/asm/cet.h | 9 ++++
arch/x86/include/asm/disabled-features.h | 8 +++-
arch/x86/include/asm/vdso.h | 20 ++++++++-
arch/x86/include/uapi/asm/sigcontext.h | 1 +
arch/x86/kernel/Makefile | 1 +
arch/x86/kernel/cet_prctl.c | 5 +++
arch/x86/kernel/fpu/signal.c | 33 ++++++++++++--
arch/x86/kernel/ibt.c | 57 ++++++++++++++++++++++++
arch/x86/kernel/process_64.c | 8 ++++
13 files changed, 168 insertions(+), 5 deletions(-)
create mode 100644 arch/x86/kernel/ibt.c
--
2.21.0
From: "H.J. Lu" <[email protected]>
Update ARCH_X86_CET_STATUS and ARCH_X86_CET_DISABLE for Indirect Branch
Tracking.
Signed-off-by: H.J. Lu <[email protected]>
Signed-off-by: Yu-cheng Yu <[email protected]>
Reviewed-by: Kees Cook <[email protected]>
---
v24:
- Update for function name changes introduced from splitting shadow stack and ibt.
arch/x86/kernel/cet_prctl.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/x86/kernel/cet_prctl.c b/arch/x86/kernel/cet_prctl.c
index 3bb9f32ca70d..ab05597545c5 100644
--- a/arch/x86/kernel/cet_prctl.c
+++ b/arch/x86/kernel/cet_prctl.c
@@ -22,6 +22,9 @@ static int cet_copy_status_to_user(struct cet_status *cet, u64 __user *ubuf)
buf[2] = cet->shstk_size;
}
+ if (cet->ibt_enabled)
+ buf[0] |= GNU_PROPERTY_X86_FEATURE_1_IBT;
+
return copy_to_user(ubuf, buf, sizeof(buf));
}
@@ -46,6 +49,8 @@ int prctl_cet(int option, u64 arg2)
return -EINVAL;
if (arg2 & GNU_PROPERTY_X86_FEATURE_1_SHSTK)
shstk_disable();
+ if (arg2 & GNU_PROPERTY_X86_FEATURE_1_IBT)
+ ibt_disable();
return 0;
case ARCH_X86_CET_LOCK:
--
2.21.0
From: "H.J. Lu" <[email protected]>
When Indirect Branch Tracking (IBT) is enabled, vDSO functions may be
called indirectly, and must have ENDBR32 or ENDBR64 as the first
instruction. The compiler must support -fcf-protection=branch so that it
can be used to compile vDSO.
Signed-off-by: H.J. Lu <[email protected]>
Signed-off-by: Yu-cheng Yu <[email protected]>
Cc: Andy Lutomirski <[email protected]>
Cc: Kees Cook <[email protected]>
---
v24:
- Replace CONFIG_X86_CET with CONFIG_X86_IBT to reflect splitting of shadow
stack and ibt.
arch/x86/entry/vdso/Makefile | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/x86/entry/vdso/Makefile b/arch/x86/entry/vdso/Makefile
index 05c4abc2fdfd..a773a5f03b63 100644
--- a/arch/x86/entry/vdso/Makefile
+++ b/arch/x86/entry/vdso/Makefile
@@ -93,6 +93,10 @@ endif
$(vobjs): KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_LTO) $(GCC_PLUGINS_CFLAGS) $(RETPOLINE_CFLAGS),$(KBUILD_CFLAGS)) $(CFL)
+ifdef CONFIG_X86_IBT
+$(vobjs) $(vobjs32): KBUILD_CFLAGS += -fcf-protection=branch
+endif
+
#
# vDSO code runs in userspace and -pg doesn't help with profiling anyway.
#
--
2.21.0
When an indirect CALL/JMP instruction is executed and before it reaches
the target, it is in 'WAIT_ENDBR' status, which can be read from
MSR_IA32_U_CET. The status is part of a task's status before a signal is
raised and preserved in the signal frame. It is restored for sigreturn.
IBT state machine is described in Intel SDM Vol. 1, Sec. 18.3.
Signed-off-by: Yu-cheng Yu <[email protected]>
Cc: Kees Cook <[email protected]>
---
v25:
- Move the addition of sc_ext.wait_endbr from an earlier shadow stack
patch to here.
- Change X86_FEATURE_CET to X86_FEATURE_SHSTK.
- Change wrmsrl() to wrmsrl_safe() and handle error.
v24:
- Update for changes from splitting shadow stack and ibt.
arch/x86/include/uapi/asm/sigcontext.h | 1 +
arch/x86/kernel/fpu/signal.c | 33 +++++++++++++++++++++++---
2 files changed, 31 insertions(+), 3 deletions(-)
diff --git a/arch/x86/include/uapi/asm/sigcontext.h b/arch/x86/include/uapi/asm/sigcontext.h
index 10d7fa192d48..ee5bacce7d87 100644
--- a/arch/x86/include/uapi/asm/sigcontext.h
+++ b/arch/x86/include/uapi/asm/sigcontext.h
@@ -203,6 +203,7 @@ struct _xstate {
struct sc_ext {
unsigned long total_size;
unsigned long ssp;
+ unsigned long wait_endbr;
};
/*
diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c
index 0488407bec81..0ed01e70b09e 100644
--- a/arch/x86/kernel/fpu/signal.c
+++ b/arch/x86/kernel/fpu/signal.c
@@ -71,16 +71,29 @@ int save_extra_state_to_sigframe(int ia32, void __user *fp, void __user *restore
return err;
ext.ssp = token_addr;
+ }
+ if (new_ssp || cet->ibt_enabled) {
fpregs_lock();
if (test_thread_flag(TIF_NEED_FPU_LOAD))
__fpregs_load_activate();
if (new_ssp)
err = wrmsrl_safe(MSR_IA32_PL3_SSP, new_ssp);
+
+ if (!err && cet->ibt_enabled) {
+ u64 msr_val;
+
+ err = rdmsrl_safe(MSR_IA32_U_CET, &msr_val);
+ if (!err && (msr_val & CET_WAIT_ENDBR)) {
+ ext.wait_endbr = 1;
+ msr_val &= ~CET_WAIT_ENDBR;
+ err = wrmsrl_safe(MSR_IA32_U_CET, msr_val);
+ }
+ }
fpregs_unlock();
}
- if (!err && ext.ssp) {
+ if (!err && (ext.ssp || cet->ibt_enabled)) {
void __user *p = fp;
ext.total_size = sizeof(ext);
@@ -110,7 +123,8 @@ static int get_extra_state_from_sigframe(int ia32, void __user *fp, struct sc_ex
if (!cpu_feature_enabled(X86_FEATURE_SHSTK))
return 0;
- if (!cet->shstk_size)
+ if (!cet->shstk_size &&
+ !cet->ibt_enabled)
return 0;
memset(ext, 0, sizeof(*ext));
@@ -149,6 +163,19 @@ static int restore_extra_state_to_xregs(struct sc_ext *sc_ext)
if (cet->shstk_size)
err = wrmsrl_safe(MSR_IA32_PL3_SSP, sc_ext->ssp);
+
+ if (err)
+ return err;
+
+ if (cet->ibt_enabled && sc_ext->wait_endbr) {
+ u64 msr_val;
+
+ err = rdmsrl_safe(MSR_IA32_U_CET, &msr_val);
+ if (!err) {
+ msr_val |= CET_WAIT_ENDBR;
+ err = wrmsrl_safe(MSR_IA32_U_CET, msr_val);
+ }
+ }
#endif
return err;
}
@@ -616,7 +643,7 @@ static unsigned long fpu__alloc_sigcontext_ext(unsigned long sp)
* sigcontext_ext is at: fpu + fpu_user_xstate_size +
* FP_XSTATE_MAGIC2_SIZE, then aligned to 8.
*/
- if (cet->shstk_size)
+ if (cet->shstk_size || cet->ibt_enabled)
sp -= (sizeof(struct sc_ext) + 8);
#endif
return sp;
--
2.21.0
Indirect Branch Tracking (IBT) provides protection against CALL-/JMP-
oriented programming attacks. It is active when the kernel has this
feature enabled, and the processor and the application support it.
When this feature is enabled, legacy non-IBT applications continue to
work, but without IBT protection.
Signed-off-by: Yu-cheng Yu <[email protected]>
Cc: Kees Cook <[email protected]>
---
v25:
- Make CONFIG_X86_IBT depend on CONFIG_X86_SHADOW_STACK.
arch/x86/Kconfig | 19 +++++++++++++++++++
arch/x86/include/asm/disabled-features.h | 8 +++++++-
2 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 77d2e44995d7..6bb69fba0dad 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1965,6 +1965,25 @@ config X86_SHADOW_STACK
If unsure, say N.
+config X86_IBT
+ prompt "Intel Indirect Branch Tracking"
+ def_bool n
+ depends on X86_SHADOW_STACK
+ depends on $(cc-option,-fcf-protection)
+ help
+ Indirect Branch Tracking (IBT) provides protection against
+ CALL-/JMP-oriented programming attacks. It is active when
+ the kernel has this feature enabled, and the processor and
+ the application support it. When this feature is enabled,
+ legacy non-IBT applications continue to work, but without
+ IBT protection.
+ Support for this feature is present on Tiger Lake family of
+ processors released in 2020 or later. Enabling this feature
+ increases kernel text size by 3.7 KB.
+ See Documentation/x86/intel_cet.rst for more information.
+
+ If unsure, say N.
+
config EFI
bool "EFI runtime service support"
depends on ACPI
diff --git a/arch/x86/include/asm/disabled-features.h b/arch/x86/include/asm/disabled-features.h
index e5c6ed9373e8..07cc40d49947 100644
--- a/arch/x86/include/asm/disabled-features.h
+++ b/arch/x86/include/asm/disabled-features.h
@@ -74,6 +74,12 @@
#define DISABLE_SHSTK (1 << (X86_FEATURE_SHSTK & 31))
#endif
+#ifdef CONFIG_X86_IBT
+#define DISABLE_IBT 0
+#else
+#define DISABLE_IBT (1 << (X86_FEATURE_IBT & 31))
+#endif
+
/*
* Make sure to add features to the correct mask
*/
@@ -96,7 +102,7 @@
#define DISABLED_MASK16 (DISABLE_PKU|DISABLE_OSPKE|DISABLE_LA57|DISABLE_UMIP| \
DISABLE_ENQCMD|DISABLE_SHSTK)
#define DISABLED_MASK17 0
-#define DISABLED_MASK18 0
+#define DISABLED_MASK18 (DISABLE_IBT)
#define DISABLED_MASK19 0
#define DISABLED_MASK_CHECK BUILD_BUG_ON_ZERO(NCAPINTS != 20)
--
2.21.0
An ELF file's .note.gnu.property indicates features the file supports.
The property is parsed at loading time and passed to arch_setup_elf_
property(). Update it for Indirect Branch Tracking.
Signed-off-by: Yu-cheng Yu <[email protected]>
Cc: Kees Cook <[email protected]>
---
v24:
- Update for changes introduced from splitting shadow stack and ibt.
arch/x86/Kconfig | 2 ++
arch/x86/kernel/process_64.c | 8 ++++++++
2 files changed, 10 insertions(+)
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 6bb69fba0dad..7436e3a608e8 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1970,6 +1970,8 @@ config X86_IBT
def_bool n
depends on X86_SHADOW_STACK
depends on $(cc-option,-fcf-protection)
+ select ARCH_USE_GNU_PROPERTY
+ select ARCH_BINFMT_ELF_STATE
help
Indirect Branch Tracking (IBT) provides protection against
CALL-/JMP-oriented programming attacks. It is active when
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index d71045b29475..bf8ef10e5b78 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -864,6 +864,14 @@ int arch_setup_elf_property(struct arch_elf_state *state)
r = shstk_setup();
}
+ if (r < 0)
+ return r;
+
+ if (cpu_feature_enabled(X86_FEATURE_IBT)) {
+ if (state->gnu_property & GNU_PROPERTY_X86_FEATURE_1_IBT)
+ r = ibt_setup();
+ }
+
return r;
}
#endif
--
2.21.0
ENDBR is a special new instruction for the Indirect Branch Tracking (IBT)
component of CET. IBT prevents attacks by ensuring that (most) indirect
branches and function calls may only land at ENDBR instructions. Branches
that don't follow the rules will result in control flow (#CF) exceptions.
ENDBR is a noop when IBT is unsupported or disabled. Most ENDBR
instructions are inserted automatically by the compiler, but branch
targets written in assembly must have ENDBR added manually.
Add ENDBR to __vdso_sgx_enter_enclave() branch targets.
Signed-off-by: Yu-cheng Yu <[email protected]>
Cc: Andy Lutomirski <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: Dave Hansen <[email protected]>
Cc: Jarkko Sakkinen <[email protected]>
Cc: Peter Zijlstra <[email protected]>
---
arch/x86/entry/vdso/vsgx.S | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/x86/entry/vdso/vsgx.S b/arch/x86/entry/vdso/vsgx.S
index 86a0e94f68df..f3ebd38d1898 100644
--- a/arch/x86/entry/vdso/vsgx.S
+++ b/arch/x86/entry/vdso/vsgx.S
@@ -4,6 +4,7 @@
#include <asm/export.h>
#include <asm/errno.h>
#include <asm/enclu.h>
+#include <asm/vdso.h>
#include "extable.h"
@@ -27,6 +28,7 @@
SYM_FUNC_START(__vdso_sgx_enter_enclave)
/* Prolog */
.cfi_startproc
+ ENDBR64
push %rbp
.cfi_adjust_cfa_offset 8
.cfi_rel_offset %rbp, 0
@@ -62,6 +64,7 @@ SYM_FUNC_START(__vdso_sgx_enter_enclave)
.Lasync_exit_pointer:
.Lenclu_eenter_eresume:
enclu
+ ENDBR64
/* EEXIT jumps here unless the enclave is doing something fancy. */
mov SGX_ENCLAVE_OFFSET_OF_RUN(%rbp), %rbx
@@ -91,6 +94,7 @@ SYM_FUNC_START(__vdso_sgx_enter_enclave)
jmp .Lout
.Lhandle_exception:
+ ENDBR64
mov SGX_ENCLAVE_OFFSET_OF_RUN(%rbp), %rbx
/* Set the exception info. */
--
2.21.0
ENDBR is a special new instruction for the Indirect Branch Tracking (IBT)
component of CET. IBT prevents attacks by ensuring that (most) indirect
branches and function calls may only land at ENDBR instructions. Branches
that don't follow the rules will result in control flow (#CF) exceptions.
ENDBR is a noop when IBT is unsupported or disabled. Most ENDBR
instructions are inserted automatically by the compiler, but branch
targets written in assembly must have ENDBR added manually.
Introduce ENDBR64/ENDBR32 macros.
Signed-off-by: Yu-cheng Yu <[email protected]>
Cc: Andy Lutomirski <[email protected]>
Cc: Borislav Petkov <[email protected]>
Cc: Dave Hansen <[email protected]>
Cc: Jarkko Sakkinen <[email protected]>
Cc: Peter Zijlstra <[email protected]>
---
v25:
- Change from using the compiler's cet.h back to just ENDBR64/ENDBR32,
since the information is already known, and keep it simple.
arch/x86/include/asm/vdso.h | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)
diff --git a/arch/x86/include/asm/vdso.h b/arch/x86/include/asm/vdso.h
index 98aa103eb4ab..97358246e4c7 100644
--- a/arch/x86/include/asm/vdso.h
+++ b/arch/x86/include/asm/vdso.h
@@ -52,6 +52,24 @@ extern int map_vdso_once(const struct vdso_image *image, unsigned long addr);
extern bool fixup_vdso_exception(struct pt_regs *regs, int trapnr,
unsigned long error_code,
unsigned long fault_addr);
-#endif /* __ASSEMBLER__ */
+#else /* __ASSEMBLER__ */
+
+/*
+ * ENDBR is an instruction for the Indirect Branch Tracking (IBT) component
+ * of CET. IBT prevents attacks by ensuring that (most) indirect branches
+ * function calls may only land at ENDBR instructions. Branches that don't
+ * follow the rules will result in control flow (#CF) exceptions.
+ * ENDBR is a noop when IBT is unsupported or disabled. Most ENDBR
+ * instructions are inserted automatically by the compiler, but branch
+ * targets written in assembly must have ENDBR added manually.
+ */
+#ifdef CONFIG_X86_IBT
+#define ENDBR64 endbr64
+#define ENDBR32 endbr32
+#else
+#define ENDBR64
+#define ENDBR32
+#endif
+#endif /* __ASSEMBLER__ */
#endif /* _ASM_X86_VDSO_H */
--
2.21.0
Introduce user-mode Indirect Branch Tracking (IBT) support. Add routines
for the setup/disable of IBT.
Signed-off-by: Yu-cheng Yu <[email protected]>
Cc: Kees Cook <[email protected]>
---
v24:
- Move IBT routines to a separate ibt.c, update related areas accordingly.
arch/x86/include/asm/cet.h | 9 ++++++
arch/x86/kernel/Makefile | 1 +
arch/x86/kernel/ibt.c | 57 ++++++++++++++++++++++++++++++++++++++
3 files changed, 67 insertions(+)
create mode 100644 arch/x86/kernel/ibt.c
diff --git a/arch/x86/include/asm/cet.h b/arch/x86/include/asm/cet.h
index 662335ceb57f..17afcc9ea4d1 100644
--- a/arch/x86/include/asm/cet.h
+++ b/arch/x86/include/asm/cet.h
@@ -15,6 +15,7 @@ struct cet_status {
unsigned long shstk_base;
unsigned long shstk_size;
unsigned int locked:1;
+ unsigned int ibt_enabled:1;
};
#ifdef CONFIG_X86_SHADOW_STACK
@@ -41,6 +42,14 @@ static inline int shstk_check_rstor_token(bool ia32, unsigned long token_addr,
unsigned long *new_ssp) { return 0; }
#endif
+#ifdef CONFIG_X86_IBT
+int ibt_setup(void);
+void ibt_disable(void);
+#else
+static inline int ibt_setup(void) { return 0; }
+static inline void ibt_disable(void) {}
+#endif
+
#ifdef CONFIG_X86_SHADOW_STACK
int prctl_cet(int option, u64 arg2);
#else
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index eb13d578ad36..e10e007c1d80 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -151,6 +151,7 @@ obj-$(CONFIG_UNWINDER_GUESS) += unwind_guess.o
obj-$(CONFIG_AMD_MEM_ENCRYPT) += sev-es.o
obj-$(CONFIG_X86_SHADOW_STACK) += shstk.o cet_prctl.o
+obj-$(CONFIG_X86_IBT) += ibt.o
###
# 64 bit specific files
diff --git a/arch/x86/kernel/ibt.c b/arch/x86/kernel/ibt.c
new file mode 100644
index 000000000000..d2cef1a0345b
--- /dev/null
+++ b/arch/x86/kernel/ibt.c
@@ -0,0 +1,57 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ibt.c - Intel Indirect Branch Tracking support
+ *
+ * Copyright (c) 2021, Intel Corporation.
+ * Yu-cheng Yu <[email protected]>
+ */
+
+#include <linux/user.h>
+#include <asm/msr.h>
+#include <asm/fpu/internal.h>
+#include <asm/fpu/xstate.h>
+#include <asm/fpu/types.h>
+#include <asm/cet.h>
+
+static void start_update_msrs(void)
+{
+ fpregs_lock();
+ if (test_thread_flag(TIF_NEED_FPU_LOAD))
+ __fpregs_load_activate();
+}
+
+static void end_update_msrs(void)
+{
+ fpregs_unlock();
+}
+
+int ibt_setup(void)
+{
+ u64 msr_val;
+
+ if (!cpu_feature_enabled(X86_FEATURE_IBT))
+ return -EOPNOTSUPP;
+
+ start_update_msrs();
+ rdmsrl(MSR_IA32_U_CET, msr_val);
+ msr_val |= (CET_ENDBR_EN | CET_NO_TRACK_EN);
+ wrmsrl(MSR_IA32_U_CET, msr_val);
+ end_update_msrs();
+ current->thread.cet.ibt_enabled = 1;
+ return 0;
+}
+
+void ibt_disable(void)
+{
+ u64 msr_val;
+
+ if (!cpu_feature_enabled(X86_FEATURE_IBT))
+ return;
+
+ start_update_msrs();
+ rdmsrl(MSR_IA32_U_CET, msr_val);
+ msr_val &= ~CET_ENDBR_EN;
+ wrmsrl(MSR_IA32_U_CET, msr_val);
+ end_update_msrs();
+ current->thread.cet.ibt_enabled = 0;
+}
--
2.21.0
From: "H.J. Lu" <[email protected]>
ENDBR is a special new instruction for the Indirect Branch Tracking (IBT)
component of CET. IBT prevents attacks by ensuring that (most) indirect
branches and function calls may only land at ENDBR instructions. Branches
that don't follow the rules will result in control flow (#CF) exceptions.
ENDBR is a noop when IBT is unsupported or disabled. Most ENDBR
instructions are inserted automatically by the compiler, but branch
targets written in assembly must have ENDBR added manually.
Add that to __kernel_vsyscall entry point.
Signed-off-by: H.J. Lu <[email protected]>
Signed-off-by: Yu-cheng Yu <[email protected]>
Cc: Andy Lutomirski <[email protected]>
Cc: Kees Cook <[email protected]>
---
arch/x86/entry/vdso/vdso32/system_call.S | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/x86/entry/vdso/vdso32/system_call.S b/arch/x86/entry/vdso/vdso32/system_call.S
index de1fff7188aa..7793dc221726 100644
--- a/arch/x86/entry/vdso/vdso32/system_call.S
+++ b/arch/x86/entry/vdso/vdso32/system_call.S
@@ -7,6 +7,7 @@
#include <asm/dwarf2.h>
#include <asm/cpufeatures.h>
#include <asm/alternative-asm.h>
+#include <asm/vdso.h>
.text
.globl __kernel_vsyscall
@@ -14,6 +15,7 @@
ALIGN
__kernel_vsyscall:
CFI_STARTPROC
+ ENDBR32
/*
* Reshuffle regs so that all of any of the entry instructions
* will preserve enough state.
--
2.21.0
From: Yu-cheng Yu
> Sent: 27 April 2021 21:47
>
> Control-flow Enforcement (CET) is a new Intel processor feature that blocks
> return/jump-oriented programming attacks. Details are in "Intel 64 and
> IA-32 Architectures Software Developer's Manual" [1].
...
Does this feature require that 'binary blobs' for out of tree drivers
be compiled by a version of gcc that adds the ENDBRA instructions?
If enabled for userspace, what happens if an old .so is dynamically
loaded?
Or do all userspace programs and libraries have to have been compiled
with the ENDBRA instructions?
David
-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)
On Wed, Apr 28, 2021 at 7:52 AM Andy Lutomirski <[email protected]> wrote:
>
> On Wed, Apr 28, 2021 at 7:48 AM David Laight <[email protected]> wrote:
> >
> > From: Yu-cheng Yu
> > > Sent: 27 April 2021 21:47
> > >
> > > Control-flow Enforcement (CET) is a new Intel processor feature that blocks
> > > return/jump-oriented programming attacks. Details are in "Intel 64 and
> > > IA-32 Architectures Software Developer's Manual" [1].
> > ...
> >
> > Does this feature require that 'binary blobs' for out of tree drivers
> > be compiled by a version of gcc that adds the ENDBRA instructions?
> >
> > If enabled for userspace, what happens if an old .so is dynamically
> > loaded?
CET will be disabled by ld.so in this case.
> > Or do all userspace programs and libraries have to have been compiled
> > with the ENDBRA instructions?
Correct. ld and ld.so check this.
> If you believe that the userspace tooling for the legacy IBT table
> actually works, then it should just work. Yu-cheng, etc: how well
> tested is it?
>
Legacy IBT bitmap isn't unused since it doesn't cover legacy codes
generated by legacy JITs.
--
H.J.
On Wed, Apr 28, 2021 at 7:57 AM H.J. Lu <[email protected]> wrote:
>
> On Wed, Apr 28, 2021 at 7:52 AM Andy Lutomirski <[email protected]> wrote:
> >
> > On Wed, Apr 28, 2021 at 7:48 AM David Laight <[email protected]> wrote:
> > >
> > > From: Yu-cheng Yu
> > > > Sent: 27 April 2021 21:47
> > > >
> > > > Control-flow Enforcement (CET) is a new Intel processor feature that blocks
> > > > return/jump-oriented programming attacks. Details are in "Intel 64 and
> > > > IA-32 Architectures Software Developer's Manual" [1].
> > > ...
> > >
> > > Does this feature require that 'binary blobs' for out of tree drivers
> > > be compiled by a version of gcc that adds the ENDBRA instructions?
> > >
> > > If enabled for userspace, what happens if an old .so is dynamically
> > > loaded?
>
> CET will be disabled by ld.so in this case.
What if a program starts a thread and then dlopens a legacy .so?
>
> > > Or do all userspace programs and libraries have to have been compiled
> > > with the ENDBRA instructions?
>
> Correct. ld and ld.so check this.
>
> > If you believe that the userspace tooling for the legacy IBT table
> > actually works, then it should just work. Yu-cheng, etc: how well
> > tested is it?
> >
>
> Legacy IBT bitmap isn't unused since it doesn't cover legacy codes
> generated by legacy JITs.
>
How does ld.so decide whether a legacy JIT is in use?
From: Andy Lutomirski
> Sent: 28 April 2021 16:15
>
> On Wed, Apr 28, 2021 at 7:57 AM H.J. Lu <[email protected]> wrote:
> >
> > On Wed, Apr 28, 2021 at 7:52 AM Andy Lutomirski <[email protected]> wrote:
> > >
> > > On Wed, Apr 28, 2021 at 7:48 AM David Laight <[email protected]> wrote:
> > > >
> > > > From: Yu-cheng Yu
> > > > > Sent: 27 April 2021 21:47
> > > > >
> > > > > Control-flow Enforcement (CET) is a new Intel processor feature that blocks
> > > > > return/jump-oriented programming attacks. Details are in "Intel 64 and
> > > > > IA-32 Architectures Software Developer's Manual" [1].
> > > > ...
> > > >
> > > > Does this feature require that 'binary blobs' for out of tree drivers
> > > > be compiled by a version of gcc that adds the ENDBRA instructions?
> > > >
> > > > If enabled for userspace, what happens if an old .so is dynamically
> > > > loaded?
> >
> > CET will be disabled by ld.so in this case.
>
> What if a program starts a thread and then dlopens a legacy .so?
Or has shadow stack enabled and opens a .so that uses retpolines?
> > > > Or do all userspace programs and libraries have to have been compiled
> > > > with the ENDBRA instructions?
> >
> > Correct. ld and ld.so check this.
> >
> > > If you believe that the userspace tooling for the legacy IBT table
> > > actually works, then it should just work. Yu-cheng, etc: how well
> > > tested is it?
> > >
> >
> > Legacy IBT bitmap isn't unused since it doesn't cover legacy codes
> > generated by legacy JITs.
> >
>
> How does ld.so decide whether a legacy JIT is in use?
What if your malware just precedes its 'jump into the middle of a function'
with a %ds segment override?
I may have a real problem here.
We currently release program/library binaries that run on Linux
distributions that go back as far as RHEL6 (2.6.32 kernel era).
To do this everything is compiled on a userspace of the same vintage.
I'm not at all sure a new enough gcc to generate the ENDBR64 instructions
will run on the relevant system - and may barf on the system headers
even if we got it to run.
I really don't want to have to build multiple copies of everything.
David
-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)
On 4/28/2021 8:14 AM, Andy Lutomirski wrote:
> On Wed, Apr 28, 2021 at 7:57 AM H.J. Lu <[email protected]> wrote:
>>
>> On Wed, Apr 28, 2021 at 7:52 AM Andy Lutomirski <[email protected]> wrote:
>>>
>>> On Wed, Apr 28, 2021 at 7:48 AM David Laight <[email protected]> wrote:
>>>>
>>>> From: Yu-cheng Yu
>>>>> Sent: 27 April 2021 21:47
>>>>>
>>>>> Control-flow Enforcement (CET) is a new Intel processor feature that blocks
>>>>> return/jump-oriented programming attacks. Details are in "Intel 64 and
>>>>> IA-32 Architectures Software Developer's Manual" [1].
>>>> ...
>>>>
>>>> Does this feature require that 'binary blobs' for out of tree drivers
>>>> be compiled by a version of gcc that adds the ENDBRA instructions?
David, do you mean kernel loadable drivers here? Do not worry about it
for now, since shadow stack/ibt is not enabled for kernel-mode yet.
>>>>
>>>> If enabled for userspace, what happens if an old .so is dynamically
>>>> loaded?
>>
>> CET will be disabled by ld.so in this case.
>
> What if a program starts a thread and then dlopens a legacy .so?
>
>>
>>>> Or do all userspace programs and libraries have to have been compiled
>>>> with the ENDBRA instructions?
>>
>> Correct. ld and ld.so check this.
>>
>>> If you believe that the userspace tooling for the legacy IBT table
>>> actually works, then it should just work. Yu-cheng, etc: how well
>>> tested is it?
>>>
>>
>> Legacy IBT bitmap isn't unused since it doesn't cover legacy codes
>> generated by legacy JITs.
>>
>
> How does ld.so decide whether a legacy JIT is in use?
>
Let me clarify. IBT bitmap isn't used at all. How dlopen() works
depends entirely on the tunable of glibc.cpu.x86_ibt. There are three
values: on, off, permissive. On is always on, and off is always off,
regardless of the .so having ibt or not. The default is "permissive,"
which turns off ibt upon dlopen a legacy .so. I hope this also answers
Andy's question above.
Yu-cheng
On Wed, Apr 28, 2021 at 7:48 AM David Laight <[email protected]> wrote:
>
> From: Yu-cheng Yu
> > Sent: 27 April 2021 21:47
> >
> > Control-flow Enforcement (CET) is a new Intel processor feature that blocks
> > return/jump-oriented programming attacks. Details are in "Intel 64 and
> > IA-32 Architectures Software Developer's Manual" [1].
> ...
>
> Does this feature require that 'binary blobs' for out of tree drivers
> be compiled by a version of gcc that adds the ENDBRA instructions?
>
> If enabled for userspace, what happens if an old .so is dynamically
> loaded?
> Or do all userspace programs and libraries have to have been compiled
> with the ENDBRA instructions?
If you believe that the userspace tooling for the legacy IBT table
actually works, then it should just work. Yu-cheng, etc: how well
tested is it?
--Andy
On 4/28/2021 8:33 AM, David Laight wrote:
> From: Andy Lutomirski
>> Sent: 28 April 2021 16:15
>>
>> On Wed, Apr 28, 2021 at 7:57 AM H.J. Lu <[email protected]> wrote:
>>>
>>> On Wed, Apr 28, 2021 at 7:52 AM Andy Lutomirski <[email protected]> wrote:
>>>>
>>>> On Wed, Apr 28, 2021 at 7:48 AM David Laight <[email protected]> wrote:
>>>>>
>>>>> From: Yu-cheng Yu
>>>>>> Sent: 27 April 2021 21:47
>>>>>>
>>>>>> Control-flow Enforcement (CET) is a new Intel processor feature that blocks
>>>>>> return/jump-oriented programming attacks. Details are in "Intel 64 and
>>>>>> IA-32 Architectures Software Developer's Manual" [1].
>>>>> ...
>>>>>
>>>>> Does this feature require that 'binary blobs' for out of tree drivers
>>>>> be compiled by a version of gcc that adds the ENDBRA instructions?
>>>>>
>>>>> If enabled for userspace, what happens if an old .so is dynamically
>>>>> loaded?
>>>
>>> CET will be disabled by ld.so in this case.
>>
>> What if a program starts a thread and then dlopens a legacy .so?
>
> Or has shadow stack enabled and opens a .so that uses retpolines?
>
When shadow stack is enabled, retpolines are not necessary. I don't
know if glibc has been updated for detection of this case. H.J.?
>>>>> Or do all userspace programs and libraries have to have been compiled
>>>>> with the ENDBRA instructions?
>>>
>>> Correct. ld and ld.so check this.
>>>
>>>> If you believe that the userspace tooling for the legacy IBT table
>>>> actually works, then it should just work. Yu-cheng, etc: how well
>>>> tested is it?
>>>>
>>>
>>> Legacy IBT bitmap isn't unused since it doesn't cover legacy codes
>>> generated by legacy JITs.
>>>
>>
>> How does ld.so decide whether a legacy JIT is in use?
>
> What if your malware just precedes its 'jump into the middle of a function'
> with a %ds segment override?
>
Do you mean far jump? It is not tracked by ibt, which tracks near
indirect jump. The details can be found in Intel SDM.
> I may have a real problem here.
> We currently release program/library binaries that run on Linux
> distributions that go back as far as RHEL6 (2.6.32 kernel era).
> To do this everything is compiled on a userspace of the same vintage.
> I'm not at all sure a new enough gcc to generate the ENDBR64 instructions
> will run on the relevant system - and may barf on the system headers
> even if we got it to run.
> I really don't want to have to build multiple copies of everything.
This is likely OK. We have tested many combinations. Should you run
into any issue, please let glibc people know.
Thanks!
>
> David
>
> -
> Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
> Registration No: 1397386 (Wales)
>
On Wed, Apr 28, 2021 at 9:25 AM Yu, Yu-cheng <[email protected]> wrote:
>
> On 4/28/2021 8:33 AM, David Laight wrote:
> > From: Andy Lutomirski
> >> Sent: 28 April 2021 16:15
> >>
> >> On Wed, Apr 28, 2021 at 7:57 AM H.J. Lu <[email protected]> wrote:
> >>>
> >>> On Wed, Apr 28, 2021 at 7:52 AM Andy Lutomirski <[email protected]> wrote:
> >>>>
> >>>> On Wed, Apr 28, 2021 at 7:48 AM David Laight <[email protected]> wrote:
> >>>>>
> >>>>> From: Yu-cheng Yu
> >>>>>> Sent: 27 April 2021 21:47
> >>>>>>
> >>>>>> Control-flow Enforcement (CET) is a new Intel processor feature that blocks
> >>>>>> return/jump-oriented programming attacks. Details are in "Intel 64 and
> >>>>>> IA-32 Architectures Software Developer's Manual" [1].
> >>>>> ...
> >>>>>
> >>>>> Does this feature require that 'binary blobs' for out of tree drivers
> >>>>> be compiled by a version of gcc that adds the ENDBRA instructions?
> >>>>>
> >>>>> If enabled for userspace, what happens if an old .so is dynamically
> >>>>> loaded?
> >>>
> >>> CET will be disabled by ld.so in this case.
> >>
> >> What if a program starts a thread and then dlopens a legacy .so?
> >
> > Or has shadow stack enabled and opens a .so that uses retpolines?
> >
>
> When shadow stack is enabled, retpolines are not necessary. I don't
> know if glibc has been updated for detection of this case. H.J.?
>
> >>>>> Or do all userspace programs and libraries have to have been compiled
> >>>>> with the ENDBRA instructions?
> >>>
> >>> Correct. ld and ld.so check this.
> >>>
> >>>> If you believe that the userspace tooling for the legacy IBT table
> >>>> actually works, then it should just work. Yu-cheng, etc: how well
> >>>> tested is it?
> >>>>
> >>>
> >>> Legacy IBT bitmap isn't unused since it doesn't cover legacy codes
> >>> generated by legacy JITs.
> >>>
> >>
> >> How does ld.so decide whether a legacy JIT is in use?
> >
> > What if your malware just precedes its 'jump into the middle of a function'
> > with a %ds segment override?
> >
>
> Do you mean far jump? It is not tracked by ibt, which tracks near
> indirect jump. The details can be found in Intel SDM.
>
> > I may have a real problem here.
> > We currently release program/library binaries that run on Linux
> > distributions that go back as far as RHEL6 (2.6.32 kernel era).
> > To do this everything is compiled on a userspace of the same vintage.
> > I'm not at all sure a new enough gcc to generate the ENDBR64 instructions
> > will run on the relevant system - and may barf on the system headers
> > even if we got it to run.
> > I really don't want to have to build multiple copies of everything.
>
> This is likely OK. We have tested many combinations. Should you run
> into any issue, please let glibc people know.
>
If you have a Tiger Lake laptop, you can install the CET kernel on
Fedora 34 or Ubuntu 20.10/21.04.
--
H.J.
On Tue, Apr 27, 2021 at 01:47:13PM -0700, Yu-cheng Yu wrote:
> Introduce user-mode Indirect Branch Tracking (IBT) support. Add routines
> for the setup/disable of IBT.
>
> Signed-off-by: Yu-cheng Yu <[email protected]>
Reviewed-by: Kees Cook <[email protected]>
--
Kees Cook
On Tue, Apr 27, 2021 at 01:47:15PM -0700, Yu-cheng Yu wrote:
> An ELF file's .note.gnu.property indicates features the file supports.
> The property is parsed at loading time and passed to arch_setup_elf_
> property(). Update it for Indirect Branch Tracking.
>
> Signed-off-by: Yu-cheng Yu <[email protected]>
Reviewed-by: Kees Cook <[email protected]>
--
Kees Cook
On Tue, Apr 27, 2021 at 01:47:17PM -0700, Yu-cheng Yu wrote:
> From: "H.J. Lu" <[email protected]>
>
> When Indirect Branch Tracking (IBT) is enabled, vDSO functions may be
> called indirectly, and must have ENDBR32 or ENDBR64 as the first
> instruction. The compiler must support -fcf-protection=branch so that it
> can be used to compile vDSO.
If you respin this, you can maybe rephrase this since CONFIG_X86_IBT
has already tested for the compiler support.
>
> Signed-off-by: H.J. Lu <[email protected]>
> Signed-off-by: Yu-cheng Yu <[email protected]>
> Cc: Andy Lutomirski <[email protected]>
> Cc: Kees Cook <[email protected]>
Reviewed-by: Kees Cook <[email protected]>
-Kees
> ---
> v24:
> - Replace CONFIG_X86_CET with CONFIG_X86_IBT to reflect splitting of shadow
> stack and ibt.
>
> arch/x86/entry/vdso/Makefile | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/arch/x86/entry/vdso/Makefile b/arch/x86/entry/vdso/Makefile
> index 05c4abc2fdfd..a773a5f03b63 100644
> --- a/arch/x86/entry/vdso/Makefile
> +++ b/arch/x86/entry/vdso/Makefile
> @@ -93,6 +93,10 @@ endif
>
> $(vobjs): KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_LTO) $(GCC_PLUGINS_CFLAGS) $(RETPOLINE_CFLAGS),$(KBUILD_CFLAGS)) $(CFL)
>
> +ifdef CONFIG_X86_IBT
> +$(vobjs) $(vobjs32): KBUILD_CFLAGS += -fcf-protection=branch
> +endif
> +
> #
> # vDSO code runs in userspace and -pg doesn't help with profiling anyway.
> #
> --
> 2.21.0
>
--
Kees Cook
On Tue, Apr 27, 2021 at 01:47:19PM -0700, Yu-cheng Yu wrote:
> From: "H.J. Lu" <[email protected]>
>
> ENDBR is a special new instruction for the Indirect Branch Tracking (IBT)
> component of CET. IBT prevents attacks by ensuring that (most) indirect
> branches and function calls may only land at ENDBR instructions. Branches
> that don't follow the rules will result in control flow (#CF) exceptions.
>
> ENDBR is a noop when IBT is unsupported or disabled. Most ENDBR
> instructions are inserted automatically by the compiler, but branch
> targets written in assembly must have ENDBR added manually.
>
> Add that to __kernel_vsyscall entry point.
>
> Signed-off-by: H.J. Lu <[email protected]>
Reviewed-by: Kees Cook <[email protected]>
--
Kees Cook
On Tue, Apr 27, 2021 at 01:47:17PM -0700, Yu-cheng Yu wrote:
> From: "H.J. Lu" <[email protected]>
>
> When Indirect Branch Tracking (IBT) is enabled, vDSO functions may be
> called indirectly, and must have ENDBR32 or ENDBR64 as the first
> instruction. The compiler must support -fcf-protection=branch so that it
> can be used to compile vDSO.
>
> Signed-off-by: H.J. Lu <[email protected]>
Reviewed-by: Kees Cook <[email protected]>
--
Kees Cook
On Tue, Apr 27, 2021 at 01:47:19PM -0700, Yu-cheng Yu wrote:
> From: "H.J. Lu" <[email protected]>
>
> ENDBR is a special new instruction for the Indirect Branch Tracking (IBT)
> component of CET. IBT prevents attacks by ensuring that (most) indirect
> branches and function calls may only land at ENDBR instructions. Branches
> that don't follow the rules will result in control flow (#CF) exceptions.
>
> ENDBR is a noop when IBT is unsupported or disabled. Most ENDBR
> instructions are inserted automatically by the compiler, but branch
> targets written in assembly must have ENDBR added manually.
>
> Add that to __kernel_vsyscall entry point.
>
> Signed-off-by: H.J. Lu <[email protected]>
Reviewed-by: Kees Cook <[email protected]>
--
Kees Cook
On 4/28/2021 1:33 PM, Kees Cook wrote:
> On Tue, Apr 27, 2021 at 01:47:17PM -0700, Yu-cheng Yu wrote:
>> From: "H.J. Lu" <[email protected]>
>>
>> When Indirect Branch Tracking (IBT) is enabled, vDSO functions may be
>> called indirectly, and must have ENDBR32 or ENDBR64 as the first
>> instruction. The compiler must support -fcf-protection=branch so that it
>> can be used to compile vDSO.
>
> If you respin this, you can maybe rephrase this since CONFIG_X86_IBT
> has already tested for the compiler support.
>
Yes, I will fix this. Thanks for reviewing!
Yu-cheng
>>
>> Signed-off-by: H.J. Lu <[email protected]>
>> Signed-off-by: Yu-cheng Yu <[email protected]>
>> Cc: Andy Lutomirski <[email protected]>
>> Cc: Kees Cook <[email protected]>
>
> Reviewed-by: Kees Cook <[email protected]>
>
> -Kees
>
>> ---
>> v24:
>> - Replace CONFIG_X86_CET with CONFIG_X86_IBT to reflect splitting of shadow
>> stack and ibt.
>>
>> arch/x86/entry/vdso/Makefile | 4 ++++
>> 1 file changed, 4 insertions(+)
>>
>> diff --git a/arch/x86/entry/vdso/Makefile b/arch/x86/entry/vdso/Makefile
>> index 05c4abc2fdfd..a773a5f03b63 100644
>> --- a/arch/x86/entry/vdso/Makefile
>> +++ b/arch/x86/entry/vdso/Makefile
>> @@ -93,6 +93,10 @@ endif
>>
>> $(vobjs): KBUILD_CFLAGS := $(filter-out $(CC_FLAGS_LTO) $(GCC_PLUGINS_CFLAGS) $(RETPOLINE_CFLAGS),$(KBUILD_CFLAGS)) $(CFL)
>>
>> +ifdef CONFIG_X86_IBT
>> +$(vobjs) $(vobjs32): KBUILD_CFLAGS += -fcf-protection=branch
>> +endif
>> +
>> #
>> # vDSO code runs in userspace and -pg doesn't help with profiling anyway.
>> #
>> --
>> 2.21.0
>>
>
On Tue, Apr 27, 2021 at 01:47:12PM -0700, Yu-cheng Yu wrote:
> Indirect Branch Tracking (IBT) provides protection against CALL-/JMP-
> oriented programming attacks. It is active when the kernel has this
> feature enabled, and the processor and the application support it.
> When this feature is enabled, legacy non-IBT applications continue to
> work, but without IBT protection.
>
> Signed-off-by: Yu-cheng Yu <[email protected]>
Reviewed-by: Kees Cook <[email protected]>
--
Kees Cook
On Tue, Apr 27, 2021 at 01:47:14PM -0700, Yu-cheng Yu wrote:
> When an indirect CALL/JMP instruction is executed and before it reaches
> the target, it is in 'WAIT_ENDBR' status, which can be read from
> MSR_IA32_U_CET. The status is part of a task's status before a signal is
> raised and preserved in the signal frame. It is restored for sigreturn.
>
> IBT state machine is described in Intel SDM Vol. 1, Sec. 18.3.
>
> Signed-off-by: Yu-cheng Yu <[email protected]>
Reviewed-by: Kees Cook <[email protected]>
--
Kees Cook
On Tue, Apr 27, 2021 at 01:47:20PM -0700, Yu-cheng Yu wrote:
> ENDBR is a special new instruction for the Indirect Branch Tracking (IBT)
> component of CET. IBT prevents attacks by ensuring that (most) indirect
> branches and function calls may only land at ENDBR instructions. Branches
> that don't follow the rules will result in control flow (#CF) exceptions.
>
> ENDBR is a noop when IBT is unsupported or disabled. Most ENDBR
> instructions are inserted automatically by the compiler, but branch
> targets written in assembly must have ENDBR added manually.
>
> Add ENDBR to __vdso_sgx_enter_enclave() branch targets.
>
> Signed-off-by: Yu-cheng Yu <[email protected]>
Reviewed-by: Kees Cook <[email protected]>
--
Kees Cook
On Tue, Apr 27, 2021 at 01:47:18PM -0700, Yu-cheng Yu wrote:
> ENDBR is a special new instruction for the Indirect Branch Tracking (IBT)
> component of CET. IBT prevents attacks by ensuring that (most) indirect
> branches and function calls may only land at ENDBR instructions. Branches
> that don't follow the rules will result in control flow (#CF) exceptions.
>
> ENDBR is a noop when IBT is unsupported or disabled. Most ENDBR
> instructions are inserted automatically by the compiler, but branch
> targets written in assembly must have ENDBR added manually.
>
> Introduce ENDBR64/ENDBR32 macros.
>
> Signed-off-by: Yu-cheng Yu <[email protected]>
Reviewed-by: Kees Cook <[email protected]>
--
Kees Cook