summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2020-08-27 16:54:24 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2020-08-27 16:54:24 +0000
commit40a5c1c6a6f2ef40a921bf261bb7318bfc7aa5d2 (patch)
tree2bc7aba4bf2dc99dc5fd2f965cfb413bc4507ae3 /sys
parent512fbb87c2835e0dcf8911411631b576d9db60a5 (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@
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/amd64/stand/efiboot/conf.c4
-rw-r--r--sys/arch/amd64/stand/efiboot/exec_i386.c40
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 */