Merge "Align-up and randomize shared libraries."

This commit is contained in:
Evgenii Stepanov 2016-07-20 20:31:41 +00:00 committed by Gerrit Code Review
commit a9fbaee593
4 changed files with 60 additions and 3 deletions

View File

@ -45,6 +45,7 @@
#include <unistd.h>
#include <wchar.h>
#include "private/bionic_macros.h"
#include "private/libc_logging.h"
extern "C" {

View File

@ -17,6 +17,8 @@
#ifndef _BIONIC_MACROS_H_
#define _BIONIC_MACROS_H_
#include <stdint.h>
// Frameworks OpenGL code currently leaks this header and allows
// collisions with other declarations, e.g., from libnativehelper.
// TODO: Remove once cleaned up. b/18334516
@ -46,4 +48,22 @@
? (1UL << (64 - __builtin_clzl(static_cast<unsigned long>(value)))) \
: (1UL << (32 - __builtin_clz(static_cast<unsigned int>(value)))))
static inline uintptr_t align_down(uintptr_t p, size_t align) {
return p & ~(align - 1);
}
static inline uintptr_t align_up(uintptr_t p, size_t align) {
return (p + align - 1) & ~(align - 1);
}
template <typename T>
static inline T* align_down(T* p, size_t align) {
return reinterpret_cast<T*>(align_down(reinterpret_cast<uintptr_t>(p), align));
}
template <typename T>
static inline T* align_up(T* p, size_t align) {
return reinterpret_cast<T*>(align_up(reinterpret_cast<uintptr_t>(p), align));
}
#endif // _BIONIC_MACROS_H_

View File

@ -503,4 +503,7 @@ android_namespace_t* create_namespace(const void* caller_addr,
const char* permitted_when_isolated_path,
android_namespace_t* parent_namespace);
constexpr unsigned kLibraryAlignmentBits = 18;
constexpr size_t kLibraryAlignment = 1UL << kLibraryAlignmentBits;
#endif

View File

@ -449,6 +449,40 @@ size_t phdr_table_get_load_size(const ElfW(Phdr)* phdr_table, size_t phdr_count,
return max_vaddr - min_vaddr;
}
// Reserve a virtual address range such that if it's limits were extended to the next 2**align
// boundary, it would not overlap with any existing mappings.
static void* ReserveAligned(void* hint, size_t size, size_t align) {
int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
// Address hint is only used in Art for the image mapping, and it is pretty important. Don't mess
// with it.
// FIXME: try an aligned allocation and fall back to plain mmap() if the former does not provide a
// mapping at the requested address?
if (align == PAGE_SIZE || hint != nullptr) {
void* mmap_ptr = mmap(hint, size, PROT_NONE, mmap_flags, -1, 0);
if (mmap_ptr == MAP_FAILED) {
return nullptr;
}
return mmap_ptr;
}
// Allocate enough space so that the end of the desired region aligned up is still inside the
// mapping.
size_t mmap_size = align_up(size, align) + align - PAGE_SIZE;
uint8_t* mmap_ptr =
reinterpret_cast<uint8_t*>(mmap(nullptr, mmap_size, PROT_NONE, mmap_flags, -1, 0));
if (mmap_ptr == MAP_FAILED) {
return nullptr;
}
uint8_t* first = align_up(mmap_ptr, align);
uint8_t* last = align_down(mmap_ptr + mmap_size, align) - size;
size_t n = arc4random_uniform((last - first) / PAGE_SIZE + 1);
uint8_t* start = first + n * PAGE_SIZE;
munmap(mmap_ptr, start - mmap_ptr);
munmap(start + size, mmap_ptr + mmap_size - (start + size));
return start;
}
// Reserve a virtual address range big enough to hold all loadable
// segments of a program header table. This is done by creating a
// private anonymous mmap() with PROT_NONE.
@ -490,9 +524,8 @@ bool ElfReader::ReserveAddressSpace(const android_dlextinfo* extinfo) {
reserved_size - load_size_, load_size_, name_.c_str());
return false;
}
int mmap_flags = MAP_PRIVATE | MAP_ANONYMOUS;
start = mmap(mmap_hint, load_size_, PROT_NONE, mmap_flags, -1, 0);
if (start == MAP_FAILED) {
start = ReserveAligned(mmap_hint, load_size_, kLibraryAlignment);
if (start == nullptr) {
DL_ERR("couldn't reserve %zd bytes of address space for \"%s\"", load_size_, name_.c_str());
return false;
}