|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH] x86/cet: Use dedicated NOP4 for cf_clobber
For livepatching, we need to look at a potentially clobbered function and
determine whether it used to have an ENDBR64 instruction.
Use a non-default 4-byte P6 long nop, not emitted by toolchains, and introduce
the was_endbr64() predicate.
Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
CC: Jan Beulich <JBeulich@xxxxxxxx>
CC: Roger Pau Monné <roger.pau@xxxxxxxxxx>
CC: Wei Liu <wl@xxxxxxx>
CC: Bjoern Doebel <doebel@xxxxxxxxx>
CC: Michael Kurth <mku@xxxxxxxxx>
CC: Martin Pohlack <mpohlack@xxxxxxxxx>
Bjoern: For the livepatching code, I think you want:
if ( is_endbr64(...) || was_endbr64(...) )
needed += ENDBR64_LEN;
---
xen/arch/x86/alternative.c | 10 +++++++++-
xen/arch/x86/include/asm/endbr.h | 12 ++++++++++++
2 files changed, 21 insertions(+), 1 deletion(-)
diff --git a/xen/arch/x86/alternative.c b/xen/arch/x86/alternative.c
index d41eeef1bcaf..ffb1b1d960c8 100644
--- a/xen/arch/x86/alternative.c
+++ b/xen/arch/x86/alternative.c
@@ -362,7 +362,15 @@ static void init_or_livepatch _apply_alternatives(struct
alt_instr *start,
if ( !is_kernel_text(ptr) || !is_endbr64(ptr) )
continue;
- add_nops(ptr, ENDBR64_LEN);
+ /*
+ * Can't use add_nops() here. ENDBR64_POISON is specifically
+ * different to NOP4 so it can be spotted after the fact.
+ *
+ * All CET-capable hardware uses P6 NOPS (no need to plumb through
+ * ideal_nops), and doesn't require a branch to synchronise the
+ * instruction stream.
+ */
+ memcpy(ptr, ENDBR64_POISON, ENDBR64_LEN);
clobbered++;
}
diff --git a/xen/arch/x86/include/asm/endbr.h b/xen/arch/x86/include/asm/endbr.h
index 6090afeb0bd8..5e1e55cb467d 100644
--- a/xen/arch/x86/include/asm/endbr.h
+++ b/xen/arch/x86/include/asm/endbr.h
@@ -52,4 +52,16 @@ static inline void place_endbr64(void *ptr)
*(uint32_t *)ptr = gen_endbr64();
}
+/*
+ * After clobbering ENDBR64, we may need to confirm that the site used to
+ * contain an ENDBR64 instruction. Use an encoding which isn't the default
+ * P6_NOP4.
+ */
+#define ENDBR64_POISON "\x66\x0f\x1f\x00" /* osp nopl (%rax) */
+
+static inline bool was_endbr64(const void *ptr)
+{
+ return *(const uint32_t *)ptr == 0x001f0f66;
+}
+
#endif /* XEN_ASM_ENDBR_H */
--
2.11.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |