diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2020-08-27 16:54:24 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2020-08-27 16:54:24 +0000 |
commit | 40a5c1c6a6f2ef40a921bf261bb7318bfc7aa5d2 (patch) | |
tree | 2bc7aba4bf2dc99dc5fd2f965cfb413bc4507ae3 | |
parent | 512fbb87c2835e0dcf8911411631b576d9db60a5 (diff) |
Improve write un-protecting of kernel memory. For the Computrace module
on the HP EliteBook 830 G6 we added a workaround which tries to re-map
the pages where we want to place to kernel read-write. On some machines
though this workaround causes a regression. Fix those by changing a few
things: Only set the writeable bit if it isn't set yet. Un-protect
write-protected page directories. Skip lower levels if large-page is
set, since the next level is already a page. Don't do anything at all
if paging is disabled.
From Christian Ehrhardt
ok bluhm@ tobhe@
-rw-r--r-- | sys/arch/amd64/stand/efiboot/conf.c | 4 | ||||
-rw-r--r-- | sys/arch/amd64/stand/efiboot/exec_i386.c | 40 |
2 files changed, 32 insertions, 12 deletions
diff --git a/sys/arch/amd64/stand/efiboot/conf.c b/sys/arch/amd64/stand/efiboot/conf.c index 2e5dc4ccd71..07992878d60 100644 --- a/sys/arch/amd64/stand/efiboot/conf.c +++ b/sys/arch/amd64/stand/efiboot/conf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: conf.c,v 1.29 2020/06/14 16:06:25 deraadt Exp $ */ +/* $OpenBSD: conf.c,v 1.30 2020/08/27 16:54:23 patrick Exp $ */ /* * Copyright (c) 1996 Michael Shalayeff @@ -40,7 +40,7 @@ #include "efidev.h" #include "efipxe.h" -const char version[] = "3.52"; +const char version[] = "3.53"; #ifdef EFI_DEBUG int debug = 0; diff --git a/sys/arch/amd64/stand/efiboot/exec_i386.c b/sys/arch/amd64/stand/efiboot/exec_i386.c index d4f49d9e344..38f6560c5e6 100644 --- a/sys/arch/amd64/stand/efiboot/exec_i386.c +++ b/sys/arch/amd64/stand/efiboot/exec_i386.c @@ -1,4 +1,4 @@ -/* $OpenBSD: exec_i386.c,v 1.3 2019/12/12 13:09:35 bluhm Exp $ */ +/* $OpenBSD: exec_i386.c,v 1.4 2020/08/27 16:54:23 patrick Exp $ */ /* * Copyright (c) 1997-1998 Michael Shalayeff @@ -238,19 +238,39 @@ protect_writeable(uint64_t addr, size_t len) { uint64_t end = addr + len; uint64_t *cr3, *p; - size_t off; + uint64_t cr0; + size_t idx; + __asm volatile("movq %%cr0, %0;" : "=r"(cr0) : :); + if ((cr0 & CR0_PG) == 0) + return; __asm volatile("movq %%cr3, %0;" : "=r"(cr3) : :); for (addr &= ~(uint64_t)PAGE_MASK; addr < end; addr += PAGE_SIZE) { - off = (addr & L4_MASK) >> L4_SHIFT; - p = (void *)(cr3[off] & ~(uint64_t)PAGE_MASK); - off = (addr & L3_MASK) >> L3_SHIFT; - p = (void *)(p[off] & ~(uint64_t)PAGE_MASK); - off = (addr & L2_MASK) >> L2_SHIFT; - p = (void *)(p[off] & ~(uint64_t)PAGE_MASK); - off = (addr & L1_MASK) >> L1_SHIFT; - p[off] |= PG_RW; + idx = (addr & L4_MASK) >> L4_SHIFT; + if ((p[idx] & PG_RW) == 0) + p[idx] |= PG_RW; + if (p[idx] & PG_PS) + continue; + p = (uint64_t *)(cr3[idx] & PG_FRAME); + + idx = (addr & L3_MASK) >> L3_SHIFT; + if ((p[idx] & PG_RW) == 0) + p[idx] |= PG_RW; + if (p[idx] & PG_PS) + continue; + p = (uint64_t *)(p[idx] & PG_FRAME); + + idx = (addr & L2_MASK) >> L2_SHIFT; + if ((p[idx] & PG_RW) == 0) + p[idx] |= PG_RW; + if (p[idx] & PG_PS) + continue; + p = (uint64_t *)(p[idx] & PG_FRAME); + + idx = (addr & L1_MASK) >> L1_SHIFT; + if ((p[idx] & PG_RW) == 0) + p[idx] |= PG_RW; } /* tlb flush */ |