Copyout(9) on 4/4 i386 needs correct vm_page_array[].

On the 4/4 i386, copyout(9) may need to call pmap_extract_and_hold()
on arbitrary userspace mapping.  If the mapping is backed by the
non-managed cdev pager or by the sg pager, on dense configs we might
access arbitrary element of vm_page_array[], in particular, not
corresponding to a page from the memory segment.  Initialize such pages
as fictitious with the corresponding physical address.

Reported by:	bde
Reviewed by:	alc, markj (previous version)
Sponsored by:	The FreeBSD Foundation
Differential revision:	https://reviews.freebsd.org/D16085
This commit is contained in:
Konstantin Belousov 2018-07-05 16:43:15 +00:00
parent b26d7d4ceb
commit a66d7a8ddc

View File

@ -551,6 +551,9 @@ vm_page_startup(vm_offset_t vaddr)
vm_paddr_t biggestsize, last_pa, pa;
u_long pagecount;
int biggestone, i, segind;
#if defined(__i386__) && defined(VM_PHYSSEG_DENSE)
long ii;
#endif
biggestsize = 0;
biggestone = 0;
@ -789,6 +792,13 @@ vm_page_startup(vm_offset_t vaddr)
* Initialize the page structures and add every available page to the
* physical memory allocator's free lists.
*/
#if defined(__i386__) && defined(VM_PHYSSEG_DENSE)
for (ii = 0; ii < vm_page_array_size; ii++) {
m = &vm_page_array[ii];
vm_page_init_page(m, (first_page + ii) << PAGE_SHIFT, 0);
m->flags = PG_FICTITIOUS;
}
#endif
vm_cnt.v_page_count = 0;
for (segind = 0; segind < vm_phys_nsegs; segind++) {
seg = &vm_phys_segs[segind];