Skip to content

Commit

Permalink
Use non-absolute addresses in librrpage
Browse files Browse the repository at this point in the history
This matches the kernel's VDSO, so applications that inspect the VDSO library
won't get surprised.

Resolves #3791
  • Loading branch information
rocallahan committed Aug 17, 2024
1 parent 646d7ab commit 720ae46
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 5 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1413,6 +1413,7 @@ set(BASIC_TESTS
userfaultfd
utimes
vdso_parts
vdso_symbols
vfork_done
vfork_flush
vfork_setopts
Expand Down
11 changes: 6 additions & 5 deletions src/preload/rr_page.ld.in
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ PHDRS
}
SECTIONS
{
. = 0x70000000 - 3 * @PRELOAD_LIBRARY_PAGE_SIZE@ + SIZEOF_HEADERS;
rr_page_start = 3 * @PRELOAD_LIBRARY_PAGE_SIZE@;
. = SIZEOF_HEADERS;
.eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame_entry .eh_frame_entry.*) } :text :eh_frame
.eh_frame : { KEEP (*(.eh_frame)) *(.eh_frame.*) } :text :eh_frame
.note.gnu.build-id : { *(.note.gnu.build-id) } :text :note
Expand All @@ -23,19 +24,19 @@ SECTIONS
.gnu.version_r : { *(.gnu.version_r) } :text
.got : { *(.got) } :text
.got.plt : { *(.got.plt) } :text
. = 0x70000000 - 2 * @PRELOAD_LIBRARY_PAGE_SIZE@;
. = rr_page_start - 2 * @PRELOAD_LIBRARY_PAGE_SIZE@;
/* This space in .sh_placeholder is reserved for the section table
symtab/strtab, which ordinarily go after the text sections,
but we need to have before the rr page.
We move it there in a post-processing step, since linker
scripts can't specify these locations for legacy reasons */
.sh_placeholder : { *(.sh_placeholder) } :text
. = 0x70000000 - @PRELOAD_LIBRARY_PAGE_SIZE@;
. = rr_page_start - @PRELOAD_LIBRARY_PAGE_SIZE@;
.plt : { *(.plt) } :text
.vdso.text : { *(.vdso.text) } :text
. = 0x70000000;
. = rr_page_start;
.record.text : { *(.record.text) } :text
. = 0x70000000 + @PRELOAD_LIBRARY_PAGE_SIZE@;
. = rr_page_start + @PRELOAD_LIBRARY_PAGE_SIZE@;
.replay.text : { *(.replay.text) } :replay
/DISCARD/ : { *(.debug_* ) }
}
Expand Down
48 changes: 48 additions & 0 deletions src/test/vdso_symbols.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/* -*- Mode: C; tab-width: 8; c-basic-offset: 2; indent-tabs-mode: nil; -*- */

#include "util.h"

#ifdef __x86_64__
typedef Elf64_Ehdr Ehdr;
typedef Elf64_Shdr Shdr;
typedef Elf64_Sym Sym;
#else
typedef Elf32_Ehdr Ehdr;
typedef Elf32_Shdr Shdr;
typedef Elf32_Sym Sym;
#endif

static const char* find_string(Ehdr* ehdr, uintptr_t offset) {
Shdr* strings = (Shdr*)((char*)ehdr + ehdr->e_shoff + ehdr->e_shstrndx*ehdr->e_shentsize);
return (char*)ehdr + strings->sh_offset + offset;
}

static Shdr* find_section(Ehdr* ehdr, const char* name) {
for (int i = 0; i < ehdr->e_shnum; ++i) {
Shdr* hdr = (Shdr*)((char*)ehdr + ehdr->e_shoff + i*ehdr->e_shentsize);
if (!strcmp(find_string(ehdr, hdr->sh_name), name)) {
return hdr;
}
}
return NULL;
}

int main(void) {
char* vdso = (char*)getauxval(AT_SYSINFO_EHDR);
Ehdr* ehdr = (Ehdr*)vdso;
Shdr* dynsym = find_section(ehdr, ".dynsym");
if (!dynsym) {
atomic_puts("dynsym not found in VDSO");
return 1;
}

for (int si = 0; si*dynsym->sh_entsize < dynsym->sh_size; ++si) {
Sym* sym = (Sym*)(vdso + dynsym->sh_offset) + si;
// All symbols must be within the VDSO size, i.e. not the
// absolute address. We assume the VDSO is less than 64K.
test_assert(sym->st_value < 0x10000);
}

atomic_puts("EXIT-SUCCESS");
return 0;
}

0 comments on commit 720ae46

Please sign in to comment.