Chapter 4: Virtual Process Memory
arch/i386/mm/fault.c
vma = find_vma(mm, address);
if (!vma)
goto bad_area;
if (vma->vm_start <= address)
goto good_area;
if (!(vma->vm_flags & VM_GROWSDOWN))
goto bad_area;
...
if (expand_stack(vma, address))
goto bad_area;
good_areaandbad_areaare labels to which the kernel jumps once it has discovered whether the address
is valid or invalid.
The search can yield various results:
❑ No region is found whose end address is afteraddress, in which case access is invalid.
❑ The fault address is within the region found, in which case access is valid and the page fault is
corrected by the kernel.
❑ A region is found whose end address is after the fault address but the fault address isnotwithin
the region. There may be two reasons for this:
- TheVM_GROWSDOWNflag of the region is set; this means that the region is a stack that grows
from top to bottom.expand_stackis then invoked to enlarge the stack accordingly. If it
succeeds, 0 is returned as the result, and the kernel resumes execution atgood_area.Oth-
erwise, access is interpreted as invalid.
- The region found is not a stack, so access is invalid.
good_areafollows on immediately after the above code.
arch/i386/mm/fault.c
...
good_area:
si_code = SEGV_ACCERR;
write = 0;
switch (error_code & 3) {
default: /* 3: write, present */
/* fall through */
case 2: /* write, not present */
if (!(vma->vm_flags & VM_WRITE))
goto bad_area;
write++;
break;
case 1: /* read, present */
goto bad_area;
case 0: /* read, not present */
if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
goto bad_area;
}
...