elf: restore correct region protection after relocation

This commit is contained in:
Pawel Dziepak
2013-04-16 03:44:38 +02:00
parent 9f3bd49737
commit 8614737f71
3 changed files with 44 additions and 8 deletions
+2
View File
@@ -121,6 +121,8 @@ status_t vm_delete_area(team_id teamID, area_id areaID, bool kernel);
status_t vm_create_vnode_cache(struct vnode *vnode, struct VMCache **_cache);
status_t vm_set_area_memory_type(area_id id, phys_addr_t physicalBase,
uint32 type);
status_t vm_set_area_protection(team_id team, area_id areaID,
uint32 newProtection, bool kernel);
status_t vm_get_page_mapping(team_id team, addr_t vaddr, phys_addr_t *paddr);
bool vm_test_map_modification(struct vm_page *page);
void vm_clear_map_flags(struct vm_page *page, uint32 flags);
+38 -3
View File
@@ -1827,6 +1827,7 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry)
int i;
addr_t delta = 0;
uint32 addressSpec = B_RANDOMIZED_BASE_ADDRESS;
area_id* mappedAreas = NULL;
TRACE(("elf_load: entry path '%s', team %p\n", path, team));
@@ -1906,7 +1907,14 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry)
strcpy(baseName, leaf);
}
// map the program's segments into memory
// map the program's segments into memory, initially with rw access
// correct area protection will be set after relocation
mappedAreas = (area_id*)malloc(sizeof(area_id) * elfHeader.e_phnum);
if (mappedAreas == NULL) {
status = B_NO_MEMORY;
goto error2;
}
image_info imageInfo;
memset(&imageInfo, 0, sizeof(image_info));
@@ -1917,6 +1925,8 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry)
char *originalRegionAddress;
area_id id;
mappedAreas[i] = -1;
if (programHeaders[i].p_type == PT_DYNAMIC) {
image->dynamic_section = programHeaders[i].p_vaddr;
continue;
@@ -1950,6 +1960,7 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry)
status = B_NOT_AN_EXECUTABLE;
goto error2;
}
mappedAreas[i] = id;
imageInfo.data = regionAddress;
imageInfo.data_size = memUpperBound;
@@ -1998,14 +2009,16 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry)
id = vm_map_file(team->id, regionName, (void **)&regionAddress,
addressSpec, segmentSize,
B_READ_AREA | B_EXECUTE_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP,
false, fd, ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
B_READ_AREA | B_WRITE_AREA, REGION_PRIVATE_MAP, false, fd,
ROUNDDOWN(programHeaders[i].p_offset, B_PAGE_SIZE));
if (id < B_OK) {
dprintf("error mapping file text: %s!\n", strerror(id));
status = B_NOT_AN_EXECUTABLE;
goto error2;
}
mappedAreas[i] = id;
imageInfo.text = regionAddress;
imageInfo.text_size = segmentSize;
@@ -2033,6 +2046,26 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry)
if (status != B_OK)
goto error2;
// set correct area protection
for (i = 0; i < elfHeader.e_phnum; i++) {
if (mappedAreas[i] == -1)
continue;
uint32 protection = 0;
if (programHeaders[i].p_flags & PF_EXECUTE)
protection |= B_EXECUTE_AREA;
if (programHeaders[i].p_flags & PF_WRITE)
protection |= B_WRITE_AREA;
if (programHeaders[i].p_flags & PF_READ)
protection |= B_READ_AREA;
status = vm_set_area_protection(team->id, mappedAreas[i], protection,
true);
if (status != B_OK)
goto error2;
}
// register the loaded image
imageInfo.type = B_LIBRARY_IMAGE;
imageInfo.device = st.st_dev;
@@ -2056,6 +2089,8 @@ elf_load_user_image(const char *path, Team *team, int flags, addr_t *entry)
status = B_OK;
error2:
free(mappedAreas);
image->elf_header = NULL;
delete_elf_image(image);
+4 -5
View File
@@ -274,6 +274,7 @@ static status_t map_backing_store(VMAddressSpace* addressSpace,
int protection, int mapping, uint32 flags,
const virtual_address_restrictions* addressRestrictions, bool kernel,
VMArea** _area, void** _virtualAddress);
static void fix_protection(uint32* protection);
// #pragma mark -
@@ -2527,10 +2528,12 @@ vm_copy_area(team_id team, const char* name, void** _address,
}
static status_t
status_t
vm_set_area_protection(team_id team, area_id areaID, uint32 newProtection,
bool kernel)
{
fix_protection(&newProtection);
TRACE(("vm_set_area_protection(team = %#" B_PRIx32 ", area = %#" B_PRIx32
", protection = %#" B_PRIx32 ")\n", team, areaID, newProtection));
@@ -5808,8 +5811,6 @@ _get_next_area_info(team_id team, ssize_t* cookie, area_info* info, size_t size)
status_t
set_area_protection(area_id area, uint32 newProtection)
{
fix_protection(&newProtection);
return vm_set_area_protection(VMAddressSpace::KernelID(), area,
newProtection, true);
}
@@ -6037,8 +6038,6 @@ _user_set_area_protection(area_id area, uint32 newProtection)
if ((newProtection & ~B_USER_PROTECTION) != 0)
return B_BAD_VALUE;
fix_protection(&newProtection);
return vm_set_area_protection(VMAddressSpace::CurrentID(), area,
newProtection, false);
}