mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-20 06:07:59 +00:00
Handle corner case in nested RM handling
When using an ELF image as returned from the iso9660 server, such an image is represented as a managed dataspace composed of various portions of one RAM dataspace, each portion attached with a different offset. Now, when mapping the text segment of the ELF image (usually starting at 0x1000 within the image), the code mapped at 0x1000 may correspond to any offset within the RAM dataspace used by the iso9660 server. In particular, the src-fault address (the one within the RAM dataspace) may be higher than dst-fault address (somewhere just above 0x1000 where a page-fault occurred). Thereby, 'curr_rm_base' may become negative during the reverse lookup of 'Rm_client::pager'. This corner case used to let the 'Fault_area::constrain' function return an invalid fault area, and thereby let the reverse lookup fail. The improved version explicitly checks for the address overflow condition and tries to constrain the dst fault address to the largest possible log2 page within the positive address range.
This commit is contained in:
parent
31cda45e26
commit
91f59690c4
@ -596,8 +596,26 @@ bool Rm_session_component::reverse_lookup(addr_t dst_base,
|
||||
if (!*src_dataspace)
|
||||
return false;
|
||||
|
||||
/* constrain destination fault area to region */
|
||||
dst_fault_area->constrain(dst_base + region->base(), region->size());
|
||||
/*
|
||||
* Constrain destination fault area to region
|
||||
*
|
||||
* Handle corner case when the 'dst_base' is negative. In this case, we
|
||||
* determine the largest flexpage within the positive portion of the
|
||||
* region.
|
||||
*/
|
||||
addr_t region_base = region->base() + dst_base;
|
||||
size_t region_size = region->size();
|
||||
|
||||
/* check for overflow condition */
|
||||
while ((long)region_base < 0 && (long)(region_base + region_size) > 0) {
|
||||
|
||||
/* increment base address by half of the region size */
|
||||
region_base += region_size >> 1;
|
||||
|
||||
/* lower the region size by one log2 step */
|
||||
region_size >>= 1;
|
||||
}
|
||||
dst_fault_area->constrain(region_base, region_size);
|
||||
|
||||
/* calculate source fault address relative to 'src_dataspace' */
|
||||
addr_t src_fault_offset = fault_addr - region->base() + region->offset();
|
||||
|
Loading…
Reference in New Issue
Block a user