From e8bc83db442ccaea2a971b99c07bca17e645d152 Mon Sep 17 00:00:00 2001
From: Simon South <ssouth@simonsouth.com>
Date: Wed, 21 Oct 2015 08:18:43 -0400
Subject: [PATCH] runtime_loader: Randomly position only relocatable code
The use of an unreliable test for relocatability effectively broke
runtime_loader's support for non-position-independent executables, as it
would insist on randomly positioning these files' segments in memory
anyway causing the program to quickly crash.
With this change runtime_loader uses the object type specified in the
file's header to determine whether its segments can be safely relocated,
restoring support for non-PI executables.
Fixes #12427.
---
headers/private/system/elf_common.h | 11 +++++++++++
src/system/runtime_loader/elf_load_image.cpp | 2 +-
src/system/runtime_loader/images.cpp | 16 +++++++++++-----
src/system/runtime_loader/images.h | 2 +-
4 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/headers/private/system/elf_common.h b/headers/private/system/elf_common.h
index 3e65305..23ab555 100644
a
|
b
|
|
31 | 31 | #define EI_VERSION 6 |
32 | 32 | #define EI_PAD 7 |
33 | 33 | |
| 34 | // e_type (Object file type) |
| 35 | #define ET_NONE 0 // No file type |
| 36 | #define ET_REL 1 // Relocatable file |
| 37 | #define ET_EXEC 2 // Executable file |
| 38 | #define ET_DYN 3 // Shared object file |
| 39 | #define ET_CORE 4 // Core file |
| 40 | #define ET_LOOS 0xfe00 // OS-specific range start |
| 41 | #define ET_HIOS 0xfeff // OS-specific range end |
| 42 | #define ET_LOPROC 0xff00 // Processor-specific range start |
| 43 | #define ET_HIPROC 0xffff // Processor-specific range end |
| 44 | |
34 | 45 | // e_machine (Architecture) |
35 | 46 | #define EM_NONE 0 // No machine |
36 | 47 | #define EM_M32 1 // AT&T WE 32100 |
diff --git a/src/system/runtime_loader/elf_load_image.cpp b/src/system/runtime_loader/elf_load_image.cpp
index 0110948..6393c26 100644
a
|
b
|
load_image(char const* name, image_type type, const char* rpath,
|
527 | 527 | goto err2; |
528 | 528 | } |
529 | 529 | |
530 | | status = map_image(fd, path, image); |
| 530 | status = map_image(fd, path, image, eheader.e_type == ET_EXEC); |
531 | 531 | if (status < B_OK) { |
532 | 532 | FATAL("%s: Could not map image: %s\n", image->path, strerror(status)); |
533 | 533 | status = B_ERROR; |
diff --git a/src/system/runtime_loader/images.cpp b/src/system/runtime_loader/images.cpp
index d851f9f..2b7f6df 100644
a
|
b
|
topological_sort(image_t* image, uint32 slot, image_t** initList,
|
169 | 169 | */ |
170 | 170 | static void |
171 | 171 | get_image_region_load_address(image_t* image, uint32 index, long lastDelta, |
172 | | addr_t& loadAddress, uint32& addressSpecifier) |
| 172 | bool fixed, addr_t& loadAddress, uint32& addressSpecifier) |
173 | 173 | { |
174 | | if (image->dynamic_ptr != 0) { |
| 174 | if (!fixed) { |
175 | 175 | // relocatable image... we can afford to place wherever |
176 | 176 | if (index == 0) { |
177 | 177 | // but only the first segment gets a free ride |
… |
… |
put_image(image_t* image)
|
286 | 286 | |
287 | 287 | |
288 | 288 | status_t |
289 | | map_image(int fd, char const* path, image_t* image) |
| 289 | map_image(int fd, char const* path, image_t* image, bool fixed) |
290 | 290 | { |
291 | 291 | // cut the file name from the path as base name for the created areas |
292 | 292 | const char* baseName = strrchr(path, '/'); |
… |
… |
map_image(int fd, char const* path, image_t* image)
|
304 | 304 | uint32 addressSpecifier = B_RANDOMIZED_ANY_ADDRESS; |
305 | 305 | |
306 | 306 | for (uint32 i = 0; i < image->num_regions; i++) { |
| 307 | // for BeOS compatibility: if we load an old BeOS executable, we |
| 308 | // have to relocate it, if possible - we recognize it because the |
| 309 | // vmstart is set to 0 (hopefully always) |
| 310 | if (fixed && image->regions[i].vmstart == 0) |
| 311 | fixed = false; |
| 312 | |
307 | 313 | uint32 regionAddressSpecifier; |
308 | 314 | get_image_region_load_address(image, i, |
309 | 315 | i > 0 ? loadAddress - image->regions[i - 1].vmstart : 0, |
310 | | loadAddress, regionAddressSpecifier); |
| 316 | fixed, loadAddress, regionAddressSpecifier); |
311 | 317 | if (i == 0) { |
312 | 318 | reservedAddress = loadAddress; |
313 | 319 | addressSpecifier = regionAddressSpecifier; |
… |
… |
map_image(int fd, char const* path, image_t* image)
|
339 | 345 | baseName, i, (image->regions[i].flags & RFLAG_RW) ? "rw" : "ro"); |
340 | 346 | |
341 | 347 | get_image_region_load_address(image, i, |
342 | | i > 0 ? image->regions[i - 1].delta : 0, loadAddress, |
| 348 | i > 0 ? image->regions[i - 1].delta : 0, fixed, loadAddress, |
343 | 349 | addressSpecifier); |
344 | 350 | |
345 | 351 | // If the image position is arbitrary, we must let it point to the start |
diff --git a/src/system/runtime_loader/images.h b/src/system/runtime_loader/images.h
index 7a309bb..a929040 100644
a
|
b
|
void delete_image_struct(image_t* image);
|
50 | 50 | void delete_image(image_t* image); |
51 | 51 | void put_image(image_t* image); |
52 | 52 | |
53 | | status_t map_image(int fd, char const* path, image_t* image); |
| 53 | status_t map_image(int fd, char const* path, image_t* image, bool fixed); |
54 | 54 | void unmap_image(image_t* image); |
55 | 55 | void remap_images(); |
56 | 56 | |