diff options
author | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2021-11-28 11:09:38 +0100 |
---|---|---|
committer | Samuel Thibault <samuel.thibault@ens-lyon.org> | 2021-11-28 11:44:16 +0100 |
commit | 7bb961dfd808df26b9245c999b8cb4e897439019 (patch) | |
tree | 5e88b52b7b837f99840105df57a1c48eecf1e7f3 | |
parent | bca8c004cec8971d48b8411b0592f5ee6fb57bf6 (diff) | |
download | gnumach-7bb961dfd808df26b9245c999b8cb4e897439019.tar.gz gnumach-7bb961dfd808df26b9245c999b8cb4e897439019.tar.bz2 gnumach-7bb961dfd808df26b9245c999b8cb4e897439019.zip |
Fix rejecting the mapping of some pages
The memmmap method may reject some offsets (because it falls in non-device
ranges), so device_map_page has to notice this and report the error.
device_pager_data_request then has to notice as well and report.
-rw-r--r-- | device/dev_pager.c | 26 | ||||
-rw-r--r-- | vm/vm_object.c | 5 | ||||
-rw-r--r-- | vm/vm_object.h | 6 |
3 files changed, 27 insertions, 10 deletions
diff --git a/device/dev_pager.c b/device/dev_pager.c index 066be462..cd41fee4 100644 --- a/device/dev_pager.c +++ b/device/dev_pager.c @@ -416,6 +416,7 @@ kern_return_t device_pager_data_request( vm_prot_t protection_required) { dev_pager_t ds; + kern_return_t ret; if (device_pager_debug) printf("(device_pager)data_request: pager=%p, offset=0x%lx, length=0x%lx\n", @@ -440,9 +441,18 @@ kern_return_t device_pager_data_request( return (KERN_SUCCESS); } - vm_object_page_map(object, - offset, length, - device_map_page, (void *)ds); + ret = vm_object_page_map(object, + offset, length, + device_map_page, (void *)ds); + + if (ret != KERN_SUCCESS) { + (void) r_memory_object_data_error(pager_request, + offset, length, + ret); + vm_object_deallocate(object); + dev_pager_deallocate(ds); + return (KERN_SUCCESS); + } vm_object_deallocate(object); } @@ -510,12 +520,16 @@ vm_offset_t device_map_page( vm_offset_t offset) { dev_pager_t ds = (dev_pager_t) dsp; - - return pmap_phys_address( + vm_offset_t pagenum = (*(ds->device->dev_ops->d_mmap)) (ds->device->dev_number, ds->offset + offset, - ds->prot)); + ds->prot); + + if (pagenum == -1) + return vm_page_fictitious_addr; + + return pmap_phys_address(pagenum); } kern_return_t device_pager_init_pager( diff --git a/vm/vm_object.c b/vm/vm_object.c index bbc1d6e2..9e5ae859 100644 --- a/vm/vm_object.c +++ b/vm/vm_object.c @@ -2816,7 +2816,7 @@ ipc_port_t vm_object_name( * The mapping function and its private data are used to obtain the * physical addresses for each page to be mapped. */ -void +kern_return_t vm_object_page_map( vm_object_t object, vm_offset_t offset, @@ -2835,6 +2835,8 @@ vm_object_page_map( for (i = 0; i < num_pages; i++, offset += PAGE_SIZE) { addr = (*map_fn)(map_fn_data, offset); + if (addr == vm_page_fictitious_addr) + return KERN_NO_ACCESS; while ((m = vm_page_grab_fictitious()) == VM_PAGE_NULL) vm_page_more_fictitious(); @@ -2857,6 +2859,7 @@ vm_object_page_map( PAGE_WAKEUP_DONE(m); vm_object_unlock(object); } + return KERN_SUCCESS; } diff --git a/vm/vm_object.h b/vm/vm_object.h index 80d449a0..fe436453 100644 --- a/vm/vm_object.h +++ b/vm/vm_object.h @@ -232,10 +232,10 @@ extern void vm_object_pager_create( extern void vm_object_destroy( struct ipc_port *pager); -extern void vm_object_page_map( +extern kern_return_t vm_object_page_map( vm_object_t, - vm_offset_t, - vm_size_t, + vm_offset_t, + vm_size_t, vm_offset_t (*)(void *, vm_offset_t), void *); |