summaryrefslogtreecommitdiffstats
path: root/sys/kern/sys_process.c
diff options
context:
space:
mode:
authoralc <alc@FreeBSD.org>2009-11-26 05:16:07 +0000
committeralc <alc@FreeBSD.org>2009-11-26 05:16:07 +0000
commit2d9252d6c71a08629a451a1966338c6e119912d1 (patch)
tree439fa48cd35e4006d82b065ffb58d6904316bd64 /sys/kern/sys_process.c
parent91785603f392f8a8a6ce7a20efe9065cfa5d2701 (diff)
downloadFreeBSD-src-2d9252d6c71a08629a451a1966338c6e119912d1.zip
FreeBSD-src-2d9252d6c71a08629a451a1966338c6e119912d1.tar.gz
Replace VM_PROT_OVERRIDE_WRITE by VM_PROT_COPY. VM_PROT_OVERRIDE_WRITE has
represented a write access that is allowed to override write protection. Until now, VM_PROT_OVERRIDE_WRITE has been used to write breakpoints into text pages. Text pages are not just write protected but they are also copy-on-write. VM_PROT_OVERRIDE_WRITE overrides the write protection on the text page and triggers the replication of the page so that the breakpoint will be written to a private copy. However, here is where things become confused. It is the debugger, not the process being debugged that requires write access to the copied page. Nonetheless, the copied page is being mapped into the process with write access enabled. In other words, once the debugger sets a breakpoint within a text page, the program can write to its private copy of that text page. Whereas prior to setting the breakpoint, a SIGSEGV would have occurred upon a write access. VM_PROT_COPY addresses this problem. The combination of VM_PROT_READ and VM_PROT_COPY forces the replication of a copy-on-write page even though the access is only for read. Moreover, the replicated page is only mapped into the process with read access, and not write access. Reviewed by: kib MFC after: 4 weeks
Diffstat (limited to 'sys/kern/sys_process.c')
-rw-r--r--sys/kern/sys_process.c21
1 files changed, 12 insertions, 9 deletions
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index 1aa6995..dfc36ba 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -59,6 +59,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_kern.h>
#include <vm/vm_object.h>
#include <vm/vm_page.h>
+#include <vm/vm_pager.h>
#include <vm/vm_param.h>
#ifdef COMPAT_IA32
@@ -213,10 +214,10 @@ int
proc_rwmem(struct proc *p, struct uio *uio)
{
vm_map_t map;
- vm_object_t backing_object, object = NULL;
- vm_offset_t pageno = 0; /* page number */
+ vm_object_t backing_object, object;
+ vm_offset_t pageno; /* page number */
vm_prot_t reqprot;
- int error, fault_flags, writing;
+ int error, writing;
/*
* Assert that someone has locked this vmspace. (Should be
@@ -232,9 +233,7 @@ proc_rwmem(struct proc *p, struct uio *uio)
map = &p->p_vmspace->vm_map;
writing = uio->uio_rw == UIO_WRITE;
- reqprot = writing ? (VM_PROT_WRITE | VM_PROT_OVERRIDE_WRITE) :
- VM_PROT_READ;
- fault_flags = writing ? VM_FAULT_DIRTY : VM_FAULT_NORMAL;
+ reqprot = writing ? VM_PROT_COPY | VM_PROT_READ : VM_PROT_READ;
/*
* Only map in one page at a time. We don't have to, but it
@@ -269,7 +268,7 @@ proc_rwmem(struct proc *p, struct uio *uio)
/*
* Fault the page on behalf of the process
*/
- error = vm_fault(map, pageno, reqprot, fault_flags);
+ error = vm_fault(map, pageno, reqprot, VM_FAULT_NORMAL);
if (error) {
if (error == KERN_RESOURCE_SHORTAGE)
error = ENOMEM;
@@ -279,8 +278,8 @@ proc_rwmem(struct proc *p, struct uio *uio)
}
/*
- * Now we need to get the page. out_entry, wired,
- * and single_use aren't used. One would think the vm code
+ * Now we need to get the page. out_entry and wired
+ * aren't used. One would think the vm code
* would be a *bit* nicer... We use tmap because
* vm_map_lookup() can change the map argument.
*/
@@ -303,6 +302,10 @@ proc_rwmem(struct proc *p, struct uio *uio)
VM_OBJECT_UNLOCK(object);
object = backing_object;
}
+ if (writing && m != NULL) {
+ vm_page_dirty(m);
+ vm_pager_page_unswapped(m);
+ }
VM_OBJECT_UNLOCK(object);
if (m == NULL) {
vm_map_lookup_done(tmap, out_entry);
OpenPOWER on IntegriCloud