Comments about vm_fault, vm_map_lookup and user-wired memory, part 2
Andrey Simonenko
simon at comsys.ntu-kpi.kiev.ua
Thu Mar 31 03:08:05 PST 2005
Greetings,
Second question. Consider following code (listing is given at
the end of this letter): mmap() anonymous private read-only
memory, fork() and mlock() this memory only in one process.
Here we have: COW, NEEDS_COPY, read-only memory in both
processes, but in one process it is USER_WIRED. Both memories
refer to the same vm_object.
Let's modify one byte in USER_WIRED memory from the debugger,
as the result both processes will get modification in own
memories:
1. When debugger wants to modify something in a memory, it
calls vm_fault() with VM_PROT_WRITE and VM_PROT_OVERRIDE_WRITE.
2. vm_fault() calls vm_map_lookup().
3. Since VM_PROT_OVERRIDE_WITE is on, vm_map_lookup() takes
entry->max_protection and finds out that VM_PROT_WRITE is Ok
for this memory (first if() condition passes). Since flag
VM_PROT_OVERRIDE_WRITE is on, we continue (second if() condition
passes). Since fault is on wired memory, vm_map_lookup()
drops fault_tipe to entry->protection, which has only VM_PROT_READ,
since our memory is read-only. As the result, shadow object
is not created.
4. Debugger calls uiomove_fromphys() and modifies memory in the
object, shared by both processes, but mappings are MAP_PRIVATE.
Here is my question: what is the idea of this code in vm_map_lookup(),
I mean modification of fault_type:
*wired = (entry->wired_count != 0);
if (*wired)
prot = fault_type = entry->protection;
And the result question from both my questions. As I understand
something is wrong here, at least I cannot find good explanation.
Is it allowed to create shadow objects for user-wired memory? If yes,
then should pages in a shared object, which shadow user-wired pages,
be also user-wired?
-----
if ( (addr = mmap((void *)0, 1, PROT_READ, MAP_ANON|MAP_PRIVATE,
-1, 0)) == MAP_FAILED)
err(1, "mmap");
printf("addr %p\n", addr);
if (fork() == 0)
for (;;) {
printf("<%c>\n", *(char *)addr);
sleep(1);
}
if (mlock(addr, 1) < 0)
err(1, "mlock");
for (;;) {
printf("[%c]\n", *(char *)addr);
sleep(1);
}
More information about the freebsd-hackers
mailing list