diff --git a/src/system/runtime_loader/elf_load_image.cpp b/src/system/runtime_loader/elf_load_image.cpp index ab0d51141e..16f7d2002e 100644 --- a/src/system/runtime_loader/elf_load_image.cpp +++ b/src/system/runtime_loader/elf_load_image.cpp @@ -120,6 +120,17 @@ parse_program_headers(image_t* image, char* buff, int phnum, int phentsize) /* NOP header */ break; case PT_LOAD: + { + uint32 flags = 0; + if (pheader->p_flags & PF_WRITE) { + // this is a writable segment + flags |= RFLAG_WRITABLE; + } + if (pheader->p_flags & PF_EXECUTE) { + // this is an executable segment + flags |= RFLAG_EXECUTABLE; + } + if (pheader->p_memsz == pheader->p_filesz) { /* * everything in one area @@ -134,11 +145,7 @@ parse_program_headers(image_t* image, char* buff, int phnum, int phentsize) image->regions[regcount].fdstart = pheader->p_offset; image->regions[regcount].fdsize = pheader->p_filesz; image->regions[regcount].delta = 0; - image->regions[regcount].flags = 0; - if (pheader->p_flags & PF_WRITE) { - // this is a writable segment - image->regions[regcount].flags |= RFLAG_RW; - } + image->regions[regcount].flags = flags; } else { /* * may require splitting @@ -158,11 +165,7 @@ parse_program_headers(image_t* image, char* buff, int phnum, int phentsize) image->regions[regcount].fdstart = pheader->p_offset; image->regions[regcount].fdsize = pheader->p_filesz; image->regions[regcount].delta = 0; - image->regions[regcount].flags = 0; - if (pheader->p_flags & PF_WRITE) { - // this is a writable segment - image->regions[regcount].flags |= RFLAG_RW; - } + image->regions[regcount].flags = flags; if (A != B) { /* @@ -182,15 +185,12 @@ parse_program_headers(image_t* image, char* buff, int phnum, int phentsize) image->regions[regcount].fdstart = 0; image->regions[regcount].fdsize = 0; image->regions[regcount].delta = 0; - image->regions[regcount].flags = RFLAG_ANON; - if (pheader->p_flags & PF_WRITE) { - // this is a writable segment - image->regions[regcount].flags |= RFLAG_RW; - } + image->regions[regcount].flags = flags | RFLAG_ANON; } } regcount += 1; break; + } case PT_DYNAMIC: image->dynamic_ptr = pheader->p_vaddr; break; diff --git a/src/system/runtime_loader/images.cpp b/src/system/runtime_loader/images.cpp index 15dcfc4aab..da33bd67ca 100644 --- a/src/system/runtime_loader/images.cpp +++ b/src/system/runtime_loader/images.cpp @@ -348,9 +348,10 @@ map_image(int fd, char const* path, image_t* image, bool fixed) for (uint32 i = 0; i < image->num_regions; i++) { char regionName[B_OS_NAME_LENGTH]; - snprintf(regionName, sizeof(regionName), "%s_seg%" B_PRIu32 "%s", - baseName, i, (image->regions[i].flags & RFLAG_RW) ? "rw" : "ro"); + baseName, i, (image->regions[i].flags & RFLAG_EXECUTABLE) ? + ((image->regions[i].flags & RFLAG_WRITABLE) ? "rwx" : "rx") + : (image->regions[i].flags & RFLAG_WRITABLE) ? "rw" : "ro"); get_image_region_load_address(image, i, i > 0 ? image->regions[i - 1].delta : 0, fixed, loadAddress, @@ -380,7 +381,7 @@ map_image(int fd, char const* path, image_t* image, bool fixed) // of memory to be committed for them temporarily, just because we // have to write map them. uint32 protection = B_READ_AREA | B_WRITE_AREA - | ((image->regions[i].flags & RFLAG_RW) != 0 + | ((image->regions[i].flags & RFLAG_WRITABLE) != 0 ? 0 : B_OVERCOMMITTING_AREA); image->regions[i].id = _kern_map_file(regionName, (void**)&loadAddress, B_EXACT_ADDRESS, @@ -394,10 +395,10 @@ map_image(int fd, char const* path, image_t* image, bool fixed) TRACE(("\"%s\" at %p, 0x%lx bytes (%s)\n", path, (void *)loadAddress, image->regions[i].vmsize, - image->regions[i].flags & RFLAG_RW ? "rw" : "read-only")); + image->regions[i].flags & RFLAG_WRITABLE ? "rw" : "read-only")); // handle trailer bits in data segment - if (image->regions[i].flags & RFLAG_RW) { + if (image->regions[i].flags & RFLAG_WRITABLE) { addr_t startClearing = loadAddress + PAGE_OFFSET(image->regions[i].start) + image->regions[i].size; @@ -437,11 +438,11 @@ unmap_image(image_t* image) } -/*! This function will change the protection of all read-only segments to really - be read-only (and executable). +/*! This function will change the protection of all segments to what they're + supposed to be. The areas have to be read/write first, so that they can be relocated. - If at least one image is in compatibility mode then we allow execution of + If at least one image is in compatibility mode then we allow write/execute of all areas. */ void @@ -455,9 +456,15 @@ remap_images() if ((region.flags & RFLAG_REMAPPED) != 0) continue; - uint32 protection = B_READ_AREA | B_EXECUTE_AREA; - if ((region.flags & RFLAG_RW) != 0 || image->abi < B_HAIKU_ABI_GCC_2_HAIKU) - protection |= B_WRITE_AREA; + uint32 protection = B_READ_AREA; + if (image->abi < B_HAIKU_ABI_GCC_2_HAIKU) { + protection |= B_WRITE_AREA | B_EXECUTE_AREA; + } else { + if ((region.flags & RFLAG_WRITABLE) != 0) + protection |= B_WRITE_AREA; + if ((region.flags & RFLAG_EXECUTABLE) != 0) + protection |= B_EXECUTE_AREA; + } status_t result = _kern_set_area_protection(region.id, protection); if (result == B_OK) @@ -498,7 +505,7 @@ register_image(image_t* image, int fd, const char* path) for (uint32 i= 0; i < image->num_regions; i++) { addr_t base = image->regions[i].vmstart; addr_t end = base + image->regions[i].vmsize; - if (image->regions[i].flags & RFLAG_RW) { + if (image->regions[i].flags & RFLAG_WRITABLE) { // data if (dataBase == 0) { dataBase = base; diff --git a/src/system/runtime_loader/images.h b/src/system/runtime_loader/images.h index a929040b42..bf50803d29 100644 --- a/src/system/runtime_loader/images.h +++ b/src/system/runtime_loader/images.h @@ -16,8 +16,9 @@ enum { // the lower two bits are reserved for RTLD_NOW and RTLD_GLOBAL - RFLAG_RW = 0x0010, - RFLAG_ANON = 0x0020, + RFLAG_WRITABLE = 0x0010, + RFLAG_EXECUTABLE = 0x0020, + RFLAG_ANON = 0x0040, RFLAG_TERMINATED = 0x0200, RFLAG_INITIALIZED = 0x0400,