summaryrefslogtreecommitdiff
path: root/sys/arch/i386/include/pmap.h
diff options
context:
space:
mode:
authorArtur Grabowski <art@cvs.openbsd.org>2003-05-13 03:49:05 +0000
committerArtur Grabowski <art@cvs.openbsd.org>2003-05-13 03:49:05 +0000
commitd62b0a287052a9d4eeab55ad2d56f5e316e662d4 (patch)
treecb51e3103595e6b266ec16d29af87cd7253d614d /sys/arch/i386/include/pmap.h
parent371cd3ebede8749d196eb400e88ac4b26c4b723c (diff)
The current solution to handle the protection fault trap is not
correct. It breaks down if we're trying to jump through a function pointer. The protection fault trap on i386 must be one of the most braindead traps ever invented in the history of humankind. It doesn't give you any information about what went wrong except the instruction that faulted. Since the problem we're trying to deal with is a segmentation problem, we don't get the desitination that we want to jump to, we just get the instruction and we won't add a disassembler to trap handling just to try to figure out what went wrong. What we want to do is to handle this as a normal fault to let noexec accounting in pmap_enter deal with the changes to the code segment. Unfortunately that's impossible. We don't know the faulting address, so we need to change how the exec accounting works. Basically the code segment must already cover the address we want to execute before we can fault it in. New scheme: o Start with conservative code segment. o If we get a protection fault, go through all mappings in the process and find the highest executable mapping, fix up the code segment and record that address. If the code segment didn't change, the protection fault wasn't fixable - just die. o If the highest executable mapping is removed, just reset the code segment to something conservative and let the next protection fault deal with it. We can't read all the vm mappings of the process from the pmap because of locking hell. This should allow floating code segment whenever someone implements that. Also, fix the pmap_protect function to behave more like the other pmaps we have and be slightly more agressive to force more proper protection changes. ok:ed by various people.
Diffstat (limited to 'sys/arch/i386/include/pmap.h')
-rw-r--r--sys/arch/i386/include/pmap.h21
1 files changed, 13 insertions, 8 deletions
diff --git a/sys/arch/i386/include/pmap.h b/sys/arch/i386/include/pmap.h
index 8e086787f4f..cc806191c88 100644
--- a/sys/arch/i386/include/pmap.h
+++ b/sys/arch/i386/include/pmap.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pmap.h,v 1.31 2003/04/09 07:53:57 niklas Exp $ */
+/* $OpenBSD: pmap.h,v 1.32 2003/05/13 03:49:04 art Exp $ */
/* $NetBSD: pmap.h,v 1.44 2000/04/24 17:18:18 thorpej Exp $ */
/*
@@ -266,7 +266,7 @@ struct pmap {
struct vm_page *pm_ptphint; /* pointer to a PTP in our pmap */
struct pmap_statistics pm_stats; /* pmap stats (lck by object lock) */
- int pm_nxpages; /* # of executable pages on stack */
+ vaddr_t pm_hiexec; /* highest executable mapping */
int pm_flags; /* see below */
union descriptor *pm_ldt; /* user-set LDT */
@@ -387,6 +387,8 @@ static void pmap_update_pg(vaddr_t);
static void pmap_update_2pg(vaddr_t,vaddr_t);
void pmap_write_protect(struct pmap *, vaddr_t,
vaddr_t, vm_prot_t);
+int pmap_exec_fixup(struct vm_map *, struct trapframe *,
+ struct pcb *);
vaddr_t reserve_dumppages(vaddr_t); /* XXX: not a pmap fn */
@@ -475,12 +477,15 @@ pmap_protect(pmap, sva, eva, prot)
vaddr_t sva, eva;
vm_prot_t prot;
{
- if ((prot & VM_PROT_WRITE) == 0) {
- if (prot & (VM_PROT_READ|VM_PROT_EXECUTE)) {
- pmap_write_protect(pmap, sva, eva, prot);
- } else {
- pmap_remove(pmap, sva, eva);
- }
+ if ((prot & (VM_PROT_WRITE|VM_PROT_EXECUTE)) ==
+ (VM_PROT_WRITE|VM_PROT_EXECUTE))
+ return;
+
+ if ((prot & (VM_PROT_READ|VM_PROT_EXECUTE)) ==
+ (VM_PROT_READ|VM_PROT_EXECUTE)) {
+ pmap_write_protect(pmap, sva, eva, prot);
+ } else {
+ pmap_remove(pmap, sva, eva);
}
}