mirror of
https://github.com/opnsense/src.git
synced 2026-02-25 11:00:15 -05:00
vm_fault_copy_entry: accept invalid source pages.
Either msync(MS_INVALIDATE) or the object unlock during vnode truncation can expose invalid pages backing wired entries. Accept them, but do not install them into destrination pmap. We must create copied pages in the copy case, because e.g. vm_object_unwire() expects that the entry is fully backed. Reported by: syzkaller, via emaste Reported by: syzbot+514d40ce757a3f8b15bc@syzkaller.appspotmail.com Reviewed by: markj Tested by: pho Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D19615
This commit is contained in:
parent
5e874d26a2
commit
45d72c7d7f
1 changed files with 12 additions and 6 deletions
|
|
@ -1757,8 +1757,7 @@ again:
|
|||
}
|
||||
pmap_copy_page(src_m, dst_m);
|
||||
VM_OBJECT_RUNLOCK(object);
|
||||
dst_m->valid = VM_PAGE_BITS_ALL;
|
||||
dst_m->dirty = VM_PAGE_BITS_ALL;
|
||||
dst_m->dirty = dst_m->valid = src_m->valid;
|
||||
} else {
|
||||
dst_m = src_m;
|
||||
if (vm_page_sleep_if_busy(dst_m, "fltupg"))
|
||||
|
|
@ -1771,8 +1770,6 @@ again:
|
|||
*/
|
||||
break;
|
||||
vm_page_xbusy(dst_m);
|
||||
KASSERT(dst_m->valid == VM_PAGE_BITS_ALL,
|
||||
("invalid dst page %p", dst_m));
|
||||
}
|
||||
VM_OBJECT_WUNLOCK(dst_object);
|
||||
|
||||
|
|
@ -1780,9 +1777,18 @@ again:
|
|||
* Enter it in the pmap. If a wired, copy-on-write
|
||||
* mapping is being replaced by a write-enabled
|
||||
* mapping, then wire that new mapping.
|
||||
*
|
||||
* The page can be invalid if the user called
|
||||
* msync(MS_INVALIDATE) or truncated the backing vnode
|
||||
* or shared memory object. In this case, do not
|
||||
* insert it into pmap, but still do the copy so that
|
||||
* all copies of the wired map entry have similar
|
||||
* backing pages.
|
||||
*/
|
||||
pmap_enter(dst_map->pmap, vaddr, dst_m, prot,
|
||||
access | (upgrade ? PMAP_ENTER_WIRED : 0), 0);
|
||||
if (dst_m->valid == VM_PAGE_BITS_ALL) {
|
||||
pmap_enter(dst_map->pmap, vaddr, dst_m, prot,
|
||||
access | (upgrade ? PMAP_ENTER_WIRED : 0), 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Mark it no longer busy, and put it on the active list.
|
||||
|
|
|
|||
Loading…
Reference in a new issue