Re: [RFC PATCH 00/16] PTI support for x86-32

From: Nadav Amit
Date: Sun Jan 21 2018 - 18:46:35 EST


I wanted to see whether segments protection can be a replacement for PTI
(yes, excluding SMEP emulation), or whether speculative execution âignoresâ
limit checks, similarly to the way paging protection is skipped.

It does seem that segmentation provides sufficient protection from Meltdown.
The âreliabilityâ test of Gratz PoC fails if the segment limit is set to
prevent access to the kernel memory. [ It passes if the limit is not set,
even if the DS is reloaded. ] My test is enclosed below.

So my question: wouldnât it be much more efficient to use segmentation
protection for x86-32, and allow users to choose whether they want SMEP-like
protection if needed (and then enable PTI)?

[ There might be some corner cases in which setting a segment limit
introduces a problem, for example when modify_ldt() is used to set invalid
limit, but I presume that these are relatively uncommon, can be detected on
runtime, and PTI can then be used as a fallback mechanism. ]

Thanks,
Nadav

-- >8 --
Subject: [PATCH] Test segmentation protection

---
libkdump/libkdump.c | 31 +++++++++++++++++++++++++++++++
1 file changed, 31 insertions(+)

diff --git a/libkdump/libkdump.c b/libkdump/libkdump.c
index c590391..db5bac3 100644
--- a/libkdump/libkdump.c
+++ b/libkdump/libkdump.c
@@ -10,6 +10,9 @@
#include <stdarg.h>
#include <stdlib.h>
#include <unistd.h>
+#include <assert.h>
+#include <sys/types.h>
+#include <asm/ldt.h>

libkdump_config_t libkdump_auto_config = {0};

@@ -500,6 +503,31 @@ int __attribute__((optimize("-Os"), noinline)) libkdump_read_tsx() {
return 0;
}

+extern int modify_ldt(int, void*, unsigned long);
+
+void change_ds(void)
+{
+ int r;
+ struct user_desc desc = {
+ .entry_number = 1,
+ .base_addr = 0,
+#ifdef NO_SEGMENTS
+ .limit = 0xffffeu,
+#else
+ .limit = 0xbffffu,
+#endif
+ .seg_32bit = 1,
+ .contents = 0,
+ .read_exec_only = 0,
+ .limit_in_pages = 1,
+ .seg_not_present = 0,
+ };
+
+ r = modify_ldt(1 /* write */, &desc, sizeof(desc));
+ assert(r == 0);
+ asm volatile ("mov %0, %%ds\n\t" : : "r"((1 << 3) | (1 << 2) | 3));
+}
+
// ---------------------------------------------------------------------------
int __attribute__((optimize("-Os"), noinline)) libkdump_read_signal_handler() {
size_t retries = config.retries + 1;
@@ -507,6 +535,9 @@ int __attribute__((optimize("-Os"), noinline)) libkdump_read_signal_handler() {

while (retries--) {
if (!setjmp(buf)) {
+ /* longjmp reloads the original DS... */
+ change_ds();
+
MELTDOWN;
}

Nadav Amit <nadav.amit@xxxxxxxxx> wrote:

> Please ignore my previous email. I got it workingâ Sorry for the spam.
>
>
> Nadav Amit <nadav.amit@xxxxxxxxx> wrote:
>
>> I am looking on PTI on x86-32, but I did not mange to get the PoC to work on
>> this setup (kaslr disabled, similar setup works on 64-bit).
>>
>> Did you use any PoC to âtestâ the protection?
>>
>> Thanks,
>> Nadav
>>
>>
>> Joerg Roedel <joro@xxxxxxxxxx> wrote:
>>
>>> From: Joerg Roedel <jroedel@xxxxxxx>
>>>
>>> Hi,
>>>
>>> here is my current WIP code to enable PTI on x86-32. It is
>>> still in a pretty early state, but it successfully boots my
>>> KVM guest with PAE and with legacy paging. The existing PTI
>>> code for x86-64 already prepares a lot of the stuff needed
>>> for 32 bit too, thanks for that to all the people involved
>>> in its development :)
>>>
>>> The patches are split as follows:
>>>
>>> - 1-3 contain the entry-code changes to enter and
>>> exit the kernel via the sysenter trampoline stack.
>>>
>>> - 4-7 are fixes to get the code compile on 32 bit
>>> with CONFIG_PAGE_TABLE_ISOLATION=y.
>>>
>>> - 8-14 adapt the existing PTI code to work properly
>>> on 32 bit and add the needed parts to 32 bit
>>> page-table code.
>>>
>>> - 15 switches PTI on by adding the CR3 switches to
>>> kernel entry/exit.
>>>
>>> - 16 enables the Kconfig for all of X86
>>>
>>> The code has not run on bare-metal yet, I'll test that in
>>> the next days once I setup a 32 bit box again. I also havn't
>>> tested Wine and DosEMU yet, so this might also be broken.
>>>
>>> With that post I'd like to ask for all kinds of constructive
>>> feedback on the approaches I have taken and of course the
>>> many things I broke with it :)
>>>
>>> One of the things that are surely broken is XEN_PV support.
>>> I'd appreciate any help with testing and bugfixing on that
>>> front.
>>>
>>> So please review and let me know your thoughts.
>>>
>>> Thanks,
>>>
>>> Joerg
>>>
>>> Joerg Roedel (16):
>>> x86/entry/32: Rename TSS_sysenter_sp0 to TSS_sysenter_stack
>>> x86/entry/32: Enter the kernel via trampoline stack
>>> x86/entry/32: Leave the kernel via the trampoline stack
>>> x86/pti: Define X86_CR3_PTI_PCID_USER_BIT on x86_32
>>> x86/pgtable: Move pgdp kernel/user conversion functions to pgtable.h
>>> x86/mm/ldt: Reserve high address-space range for the LDT
>>> x86/mm: Move two more functions from pgtable_64.h to pgtable.h
>>> x86/pgtable/32: Allocate 8k page-tables when PTI is enabled
>>> x86/mm/pti: Clone CPU_ENTRY_AREA on PMD level on x86_32
>>> x86/mm/pti: Populate valid user pud entries
>>> x86/mm/pgtable: Move pti_set_user_pgd() to pgtable.h
>>> x86/mm/pae: Populate the user page-table with user pgd's
>>> x86/mm/pti: Add an overflow check to pti_clone_pmds()
>>> x86/mm/legacy: Populate the user page-table with user pgd's
>>> x86/entry/32: Switch between kernel and user cr3 on entry/exit
>>> x86/pti: Allow CONFIG_PAGE_TABLE_ISOLATION for x86_32
>>>
>>> arch/x86/entry/entry_32.S | 170 +++++++++++++++++++++++++++++---
>>> arch/x86/include/asm/pgtable-2level.h | 3 +
>>> arch/x86/include/asm/pgtable-3level.h | 3 +
>>> arch/x86/include/asm/pgtable.h | 88 +++++++++++++++++
>>> arch/x86/include/asm/pgtable_32_types.h | 5 +-
>>> arch/x86/include/asm/pgtable_64.h | 85 ----------------
>>> arch/x86/include/asm/processor-flags.h | 8 +-
>>> arch/x86/include/asm/switch_to.h | 6 +-
>>> arch/x86/kernel/asm-offsets_32.c | 5 +-
>>> arch/x86/kernel/cpu/common.c | 5 +-
>>> arch/x86/kernel/head_32.S | 23 ++++-
>>> arch/x86/kernel/process.c | 2 -
>>> arch/x86/kernel/process_32.c | 6 ++
>>> arch/x86/mm/pgtable.c | 11 ++-
>>> arch/x86/mm/pti.c | 34 ++++++-
>>> security/Kconfig | 2 +-
>>> 16 files changed, 333 insertions(+), 123 deletions(-)
>>>
>>> --
>>> 2.13.6
>>>
>>> --
>>> To unsubscribe, send a message with 'unsubscribe linux-mm' in
>>> the body to majordomo@xxxxxxxxxx For more info on Linux MM,
>>> see: http://www.linux-mm.org/ .
>>> Don't email: <a href=mailto:"dont@xxxxxxxxx";> email@xxxxxxxxx </a>