Merge "Simplify Oryon ifunc resolvers." into main
diff --git a/libc/arch-arm64/bionic/__bionic_clone.S b/libc/arch-arm64/bionic/__bionic_clone.S
index e9932ad..581b47a 100644
--- a/libc/arch-arm64/bionic/__bionic_clone.S
+++ b/libc/arch-arm64/bionic/__bionic_clone.S
@@ -39,7 +39,7 @@
svc #0
# Are we the child?
- cbz x0, .L_bc_child
+ cbz x0, L(child)
# Set errno if something went wrong.
cmn x0, #(MAX_ERRNO + 1)
@@ -48,7 +48,7 @@
ret
-.L_bc_child:
+L(child):
# We're in the child now. Set the end of the frame record chain.
mov x29, #0
# Setting x30 to 0 will make the unwinder stop at __start_thread.
diff --git a/libc/arch-arm64/bionic/vfork.S b/libc/arch-arm64/bionic/vfork.S
index dd16349..26ac255 100644
--- a/libc/arch-arm64/bionic/vfork.S
+++ b/libc/arch-arm64/bionic/vfork.S
@@ -72,7 +72,7 @@
mov x8, __NR_clone
svc #0
- cbz x0, .L_exit
+ cbz x0, L(done)
// rc != 0: reset cached_pid_ and vforked_.
str w10, [x9, #20]
@@ -80,7 +80,7 @@
cneg x0, x0, hi
b.hi __set_errno_internal
-.L_exit:
+L(done):
ret
END(vfork)
diff --git a/libc/arch-arm64/string/__memcpy_chk.S b/libc/arch-arm64/string/__memcpy_chk.S
index a8e9e83..c9fc2f7 100644
--- a/libc/arch-arm64/string/__memcpy_chk.S
+++ b/libc/arch-arm64/string/__memcpy_chk.S
@@ -31,10 +31,10 @@
ENTRY(__memcpy_chk)
cmp x2, x3
// Direct b.ls memcpy may not have enough range
- b.hi .L_memcpy_chk_fail
+ b.hi L(__memcpy_chk_fail_trampoline)
b memcpy
-.L_memcpy_chk_fail:
+L(__memcpy_chk_fail_trampoline):
// Preserve for accurate backtrace.
stp x29, x30, [sp, -16]!
.cfi_def_cfa_offset 16
diff --git a/libc/arch-arm64/string/__memset_chk.S b/libc/arch-arm64/string/__memset_chk.S
index e1e29d0..7a105ce 100644
--- a/libc/arch-arm64/string/__memset_chk.S
+++ b/libc/arch-arm64/string/__memset_chk.S
@@ -31,10 +31,10 @@
ENTRY(__memset_chk)
cmp x2, x3
// Direct b.ls memcpy may not have enough range
- b.hi .L_memset_chk_fail
+ b.hi L(__memset_chk_fail_trampoline)
b memset
-.L_memset_chk_fail:
+L(__memset_chk_fail_trampoline):
// Preserve for accurate backtrace.
stp x29, x30, [sp, -16]!
.cfi_def_cfa_offset 16
diff --git a/libc/arch-riscv64/bionic/__bionic_clone.S b/libc/arch-riscv64/bionic/__bionic_clone.S
index 2827857..be386b1 100644
--- a/libc/arch-riscv64/bionic/__bionic_clone.S
+++ b/libc/arch-riscv64/bionic/__bionic_clone.S
@@ -41,19 +41,19 @@
ecall
# Are we the child?
- beqz a0, .L_bc_child
+ beqz a0, L(child)
# Did the clone(2) fail?
- bltz a0, .L_bc_failure
+ bltz a0, L(failure)
# Nope, we're the parent, and our work here is done.
ret
-.L_bc_failure:
+L(failure):
# Set errno if something went wrong.
neg a0, a0
tail __set_errno_internal
-.L_bc_child:
+L(child):
# We're in the child now. Set the end of the frame record chain.
li fp, 0
# Setting ra to 0 will make the unwinder stop at __start_thread.
diff --git a/libc/arch-riscv64/bionic/setjmp.S b/libc/arch-riscv64/bionic/setjmp.S
index 81b1e35..5de1099 100644
--- a/libc/arch-riscv64/bionic/setjmp.S
+++ b/libc/arch-riscv64/bionic/setjmp.S
@@ -205,7 +205,7 @@
// Check the checksum before doing anything.
m_calculate_checksum t0, a0, t1
ld t1, _JB_CHECKSUM(a0)
- bne t0, t1, 3f
+ bne t0, t1, L(checksum_failure)
// Do we need to restore the signal mask?
ld a2, _JB_SIGFLAG(a0)
@@ -290,7 +290,7 @@
mv a0, a1
ret
-3:
+L(checksum_failure):
call __bionic_setjmp_checksum_mismatch
END(siglongjmp)
diff --git a/libc/arch-riscv64/bionic/syscall.S b/libc/arch-riscv64/bionic/syscall.S
index 1a6e60a..ca735c7 100644
--- a/libc/arch-riscv64/bionic/syscall.S
+++ b/libc/arch-riscv64/bionic/syscall.S
@@ -44,10 +44,10 @@
// Did it fail?
li a7, -MAX_ERRNO
- bgtu a0, a7, 1f
-
+ bgtu a0, a7, L(failure)
ret
-1:
+
+L(failure):
neg a0, a0
tail __set_errno_internal
END(syscall)
diff --git a/libc/arch-riscv64/bionic/vfork.S b/libc/arch-riscv64/bionic/vfork.S
index 29ab405..06ebc3e 100644
--- a/libc/arch-riscv64/bionic/vfork.S
+++ b/libc/arch-riscv64/bionic/vfork.S
@@ -51,16 +51,16 @@
ecall
// if (rc == 0) we're the child, and finished...
- beqz a0, .L_success
+ beqz a0, L(success)
// else if (rc != 0): reset cached_pid_ and vforked_...
sw t2, 20(t0)
// ...and work out whether we succeeded or failed.
- bltz a0, .L_failure
-.L_success:
+ bltz a0, L(failure)
+L(success):
ret
-.L_failure:
+L(failure):
neg a0, a0
tail __set_errno_internal
END(vfork)
diff --git a/libc/arch-x86/bionic/setjmp.S b/libc/arch-x86/bionic/setjmp.S
index d22683a..b9e6bdf 100644
--- a/libc/arch-x86/bionic/setjmp.S
+++ b/libc/arch-x86/bionic/setjmp.S
@@ -65,19 +65,16 @@
.endm
ENTRY_WEAK_FOR_NATIVE_BRIDGE(setjmp)
- movl 4(%esp),%ecx
mov $1,%eax
jmp .L_sigsetjmp
END(setjmp)
ENTRY_WEAK_FOR_NATIVE_BRIDGE(_setjmp)
- movl 4(%esp),%ecx
movl $0,%eax
jmp .L_sigsetjmp
END(_setjmp)
ENTRY_WEAK_FOR_NATIVE_BRIDGE(sigsetjmp)
- movl 4(%esp),%ecx
movl 8(%esp),%eax
.L_sigsetjmp:
@@ -88,6 +85,7 @@
PIC_EPILOGUE
// Record the setjmp cookie and whether or not we're saving the signal mask.
+ movl 4(%esp),%ecx
movl %eax,(_JB_SIGFLAG * 4)(%ecx)
// Do we need to save the signal mask?
diff --git a/libc/bionic/gwp_asan_wrappers.cpp b/libc/bionic/gwp_asan_wrappers.cpp
index 251633d..11f7ced 100644
--- a/libc/bionic/gwp_asan_wrappers.cpp
+++ b/libc/bionic/gwp_asan_wrappers.cpp
@@ -258,14 +258,14 @@
options->Backtrace = android_unsafe_frame_pointer_chase;
options->SampleRate = kDefaultSampleRate;
options->MaxSimultaneousAllocations = kDefaultMaxAllocs;
+ options->Recoverable = true;
+ GwpAsanRecoverable = true;
- *process_sample_rate = 1;
- if (mallopt_options.desire == Action::TURN_ON_WITH_SAMPLING) {
+ if (mallopt_options.desire == Action::TURN_ON_WITH_SAMPLING ||
+ mallopt_options.desire == Action::TURN_ON_FOR_APP_SAMPLED_NON_CRASHING) {
*process_sample_rate = kDefaultProcessSampling;
- } else if (mallopt_options.desire == Action::TURN_ON_FOR_APP_SAMPLED_NON_CRASHING) {
- *process_sample_rate = kDefaultProcessSampling;
- options->Recoverable = true;
- GwpAsanRecoverable = true;
+ } else {
+ *process_sample_rate = 1;
}
}
@@ -403,7 +403,7 @@
/* default */ kDefaultMaxAllocs / frequency_multiplier;
}
- bool recoverable = false;
+ bool recoverable = true;
if (GetGwpAsanBoolOption(&recoverable, mallopt_options, kRecoverableSystemSysprop,
kRecoverableAppSysprop, kRecoverableTargetedSyspropPrefix,
kRecoverableEnvVar, "recoverable")) {
diff --git a/libc/bionic/heap_tagging.cpp b/libc/bionic/heap_tagging.cpp
index c4347e8..4d1981c 100644
--- a/libc/bionic/heap_tagging.cpp
+++ b/libc/bionic/heap_tagging.cpp
@@ -65,7 +65,7 @@
};
});
-#if defined(USE_SCUDO)
+#if defined(USE_SCUDO) && !__has_feature(hwaddress_sanitizer)
switch (heap_tagging_level) {
case M_HEAP_TAGGING_LEVEL_TBI:
case M_HEAP_TAGGING_LEVEL_NONE:
@@ -123,7 +123,7 @@
return false;
}
}
-#if defined(USE_SCUDO)
+#if defined(USE_SCUDO) && !__has_feature(hwaddress_sanitizer)
scudo_malloc_disable_memory_tagging();
#endif
break;
@@ -151,12 +151,12 @@
if (!set_tcf_on_all_threads(PR_MTE_TCF_ASYNC | PR_MTE_TCF_SYNC)) {
set_tcf_on_all_threads(PR_MTE_TCF_ASYNC);
}
-#if defined(USE_SCUDO)
+#if defined(USE_SCUDO) && !__has_feature(hwaddress_sanitizer)
scudo_malloc_set_track_allocation_stacks(0);
#endif
} else if (tag_level == M_HEAP_TAGGING_LEVEL_SYNC) {
set_tcf_on_all_threads(PR_MTE_TCF_SYNC);
-#if defined(USE_SCUDO)
+#if defined(USE_SCUDO) && !__has_feature(hwaddress_sanitizer)
scudo_malloc_set_track_allocation_stacks(1);
#endif
}
diff --git a/libc/bionic/libc_init_common.cpp b/libc/bionic/libc_init_common.cpp
index 944098f..c82c52e 100644
--- a/libc/bionic/libc_init_common.cpp
+++ b/libc/bionic/libc_init_common.cpp
@@ -96,7 +96,7 @@
SetDefaultHeapTaggingLevel();
// TODO(b/158870657) make this unconditional when all devices support SCUDO.
-#if defined(USE_SCUDO)
+#if defined(USE_SCUDO) && !__has_feature(hwaddress_sanitizer)
#if defined(SCUDO_PATTERN_FILL_CONTENTS)
scudo_malloc_set_pattern_fill_contents(1);
#elif defined(SCUDO_ZERO_CONTENTS)
@@ -182,7 +182,7 @@
extern "C" void scudo_malloc_set_add_large_allocation_slack(int add_slack);
__BIONIC_WEAK_FOR_NATIVE_BRIDGE void __libc_set_target_sdk_version(int target __unused) {
-#if defined(USE_SCUDO)
+#if defined(USE_SCUDO) && !__has_feature(hwaddress_sanitizer)
scudo_malloc_set_add_large_allocation_slack(target < __ANDROID_API_S__);
#endif
}
diff --git a/libc/bionic/malloc_common_dynamic.cpp b/libc/bionic/malloc_common_dynamic.cpp
index 8858178..6db6251 100644
--- a/libc/bionic/malloc_common_dynamic.cpp
+++ b/libc/bionic/malloc_common_dynamic.cpp
@@ -381,7 +381,7 @@
MaybeInitGwpAsanFromLibc(globals);
-#if defined(USE_SCUDO)
+#if defined(USE_SCUDO) && !__has_feature(hwaddress_sanitizer)
__libc_shared_globals()->scudo_stack_depot = __scudo_get_stack_depot_addr();
__libc_shared_globals()->scudo_region_info = __scudo_get_region_info_addr();
__libc_shared_globals()->scudo_ring_buffer = __scudo_get_ring_buffer_addr();
diff --git a/libc/include/bits/page_size.h b/libc/include/bits/page_size.h
index df0cb7f..594ffe5 100644
--- a/libc/include/bits/page_size.h
+++ b/libc/include/bits/page_size.h
@@ -32,7 +32,16 @@
__BEGIN_DECLS
-#if !defined(__BIONIC_NO_PAGE_SIZE_MACRO) || defined(__BIONIC_DEPRECATED_PAGE_SIZE_MACRO)
+// PAGE_SIZE is going away in Android. Prefer getpagesize() instead.
+//
+// For more info, see https://developer.android.com/16kb-page-size.
+//
+// To restore the original behavior, use __BIONIC_DEPRECATED_PAGE_SIZE_MACRO.
+
+#if (defined(__NDK_MAJOR__) && __NDK_MAJOR__ <= 27 && !defined(__BIONIC_NO_PAGE_SIZE_MACRO)) \
+ || defined(__BIONIC_DEPRECATED_PAGE_SIZE_MACRO) \
+ || defined(__arm__) \
+ || defined(__i386__)
#define PAGE_SIZE 4096
#define PAGE_MASK (~(PAGE_SIZE - 1))
#endif
diff --git a/libc/include/limits.h b/libc/include/limits.h
index 48e7ea9..80fc45d 100644
--- a/libc/include/limits.h
+++ b/libc/include/limits.h
@@ -136,6 +136,9 @@
#define IOV_MAX 1024
#define SEM_VALUE_MAX 0x3fffffff
+/** Do not use: prefer getline() or asprintf() rather than hard-coding an arbitrary size. */
+#define LINE_MAX _POSIX2_LINE_MAX
+
/* POSIX says these belong in <unistd.h> but BSD has some in <limits.h>. */
#include <bits/posix_limits.h>
diff --git a/libc/include/sys/param.h b/libc/include/sys/param.h
index 79ae067..1c991ae 100644
--- a/libc/include/sys/param.h
+++ b/libc/include/sys/param.h
@@ -41,8 +41,11 @@
/** The unit of `st_blocks` in `struct stat`. */
#define DEV_BSIZE 512
-/** A historical name for PATH_MAX. */
-#define MAXPATHLEN PATH_MAX
+/** A historical name for PATH_MAX. Use PATH_MAX in new code. */
+#define MAXPATHLEN PATH_MAX
+
+/** A historical name for NGROUPS_MAX. Use NGROUPS_MAX in new code. */
+#define NGROUPS NGROUPS_MAX
#define MAXSYMLINKS 8
diff --git a/libc/include/sys/shm.h b/libc/include/sys/shm.h
index fb6f20c..8ab3d9a 100644
--- a/libc/include/sys/shm.h
+++ b/libc/include/sys/shm.h
@@ -36,11 +36,12 @@
#include <sys/cdefs.h>
#include <sys/ipc.h>
#include <sys/types.h>
+#include <unistd.h>
#include <linux/shm.h>
#define shmid_ds shmid64_ds
-#define SHMLBA 4096
+#define SHMLBA getpagesize()
__BEGIN_DECLS
diff --git a/libc/platform/bionic/malloc.h b/libc/platform/bionic/malloc.h
index a06b8ee..ffc6d4a 100644
--- a/libc/platform/bionic/malloc.h
+++ b/libc/platform/bionic/malloc.h
@@ -152,6 +152,10 @@
// mode, and bug reports will be created by debuggerd, however the process
// will recover and continue to function as if the memory safety bug wasn't
// detected.
+ //
+ // In Android 15, this is the same as TURN_ON_WITH_SAMPLING, as GWP-ASan is
+ // only ever used in non-crashing mode (even for platform executables and
+ // system apps).
TURN_ON_FOR_APP_SAMPLED_NON_CRASHING,
};
diff --git a/libc/private/WriteProtected.h b/libc/private/WriteProtected.h
index fac07cb..bbe35e5 100644
--- a/libc/private/WriteProtected.h
+++ b/libc/private/WriteProtected.h
@@ -51,30 +51,39 @@
void initialize() {
// Not strictly necessary, but this will hopefully segfault if we initialize
// multiple times by accident.
- memset(&contents, 0, sizeof(contents));
+ memset(contents_addr(), 0, sizeof(contents));
set_protection(PROT_READ);
}
const T* operator->() {
- return &contents.value;
+ return &contents_addr()->value;
}
const T& operator*() {
- return contents.value;
+ return contents_addr()->value;
}
template <typename Mutator>
void mutate(Mutator mutator) {
set_protection(PROT_READ | PROT_WRITE);
- mutator(&contents.value);
+ mutator(&contents_addr()->value);
set_protection(PROT_READ);
}
private:
WriteProtectedContents<T> contents;
- void set_protection(int prot) {
+ WriteProtectedContents<T>* contents_addr() {
auto addr = &contents;
+ // Hide the fact that we're returning the address of contents from the compiler.
+ // Otherwise it may generate code assuming alignment of 64KB even though the
+ // variable is only guaranteed to have 4KB alignment.
+ __asm__ __volatile__("" : "+r"(addr));
+ return addr;
+ }
+
+ void set_protection(int prot) {
+ auto addr = contents_addr();
#if __has_feature(hwaddress_sanitizer)
// The mprotect system call does not currently untag pointers, so do it
// ourselves.
diff --git a/linker/linker.cpp b/linker/linker.cpp
index f813c1a..8b467a3 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -2788,7 +2788,7 @@
return true;
}
-void soinfo::apply_relr_reloc(ElfW(Addr) offset) {
+static void apply_relr_reloc(ElfW(Addr) offset, ElfW(Addr) load_bias) {
ElfW(Addr) address = offset + load_bias;
*reinterpret_cast<ElfW(Addr)*>(address) += load_bias;
}
@@ -2796,20 +2796,18 @@
// Process relocations in SHT_RELR section (experimental).
// Details of the encoding are described in this post:
// https://groups.google.com/d/msg/generic-abi/bX460iggiKg/Pi9aSwwABgAJ
-bool soinfo::relocate_relr() {
- ElfW(Relr)* begin = relr_;
- ElfW(Relr)* end = relr_ + relr_count_;
+bool relocate_relr(const ElfW(Relr)* begin, const ElfW(Relr)* end, ElfW(Addr) load_bias) {
constexpr size_t wordsize = sizeof(ElfW(Addr));
ElfW(Addr) base = 0;
- for (ElfW(Relr)* current = begin; current < end; ++current) {
+ for (const ElfW(Relr)* current = begin; current < end; ++current) {
ElfW(Relr) entry = *current;
ElfW(Addr) offset;
if ((entry&1) == 0) {
// Even entry: encodes the offset for next relocation.
offset = static_cast<ElfW(Addr)>(entry);
- apply_relr_reloc(offset);
+ apply_relr_reloc(offset, load_bias);
// Set base offset for subsequent bitmap entries.
base = offset + wordsize;
continue;
@@ -2820,7 +2818,7 @@
while (entry != 0) {
entry >>= 1;
if ((entry&1) != 0) {
- apply_relr_reloc(offset);
+ apply_relr_reloc(offset, load_bias);
}
offset += wordsize;
}
diff --git a/linker/linker.h b/linker/linker.h
index 275182f..ac2222d 100644
--- a/linker/linker.h
+++ b/linker/linker.h
@@ -179,6 +179,7 @@
int get_application_target_sdk_version();
ElfW(Versym) find_verdef_version_index(const soinfo* si, const version_info* vi);
bool validate_verdef_section(const soinfo* si);
+bool relocate_relr(const ElfW(Relr)* begin, const ElfW(Relr)* end, ElfW(Addr) load_bias);
struct platform_properties {
#if defined(__aarch64__)
diff --git a/linker/linker_main.cpp b/linker/linker_main.cpp
index b1fa979..77769f5 100644
--- a/linker/linker_main.cpp
+++ b/linker/linker_main.cpp
@@ -635,9 +635,10 @@
}
}
-static void call_ifunc_resolvers() {
- // Find the IRELATIVE relocations using the DT_JMPREL and DT_PLTRELSZ, or
- // DT_RELA/DT_RELASZ (DT_REL/DT_RELSZ on ILP32).
+static void relocate_linker() {
+ // The linker should only have relative relocations (in RELR) and IRELATIVE
+ // relocations. Find the IRELATIVE relocations using the DT_JMPREL and
+ // DT_PLTRELSZ, or DT_RELA/DT_RELASZ (DT_REL/DT_RELSZ on ILP32).
auto ehdr = reinterpret_cast<ElfW(Addr)>(&__ehdr_start);
auto* phdr = reinterpret_cast<ElfW(Phdr)*>(ehdr + __ehdr_start.e_phoff);
for (size_t i = 0; i != __ehdr_start.e_phnum; ++i) {
@@ -645,21 +646,33 @@
continue;
}
auto *dyn = reinterpret_cast<ElfW(Dyn)*>(ehdr + phdr[i].p_vaddr);
- ElfW(Addr) pltrel = 0, pltrelsz = 0, rel = 0, relsz = 0;
+ ElfW(Addr) relr = 0, relrsz = 0, pltrel = 0, pltrelsz = 0, rel = 0, relsz = 0;
for (size_t j = 0, size = phdr[i].p_filesz / sizeof(ElfW(Dyn)); j != size; ++j) {
+ const auto tag = dyn[j].d_tag;
+ const auto val = dyn[j].d_un.d_ptr;
// We don't currently handle IRELATIVE relocations in DT_ANDROID_REL[A].
// We disabled DT_ANDROID_REL[A] at build time; verify that it was actually disabled.
- CHECK(dyn[j].d_tag != DT_ANDROID_REL && dyn[j].d_tag != DT_ANDROID_RELA);
- if (dyn[j].d_tag == DT_JMPREL) {
- pltrel = dyn[j].d_un.d_ptr;
- } else if (dyn[j].d_tag == DT_PLTRELSZ) {
- pltrelsz = dyn[j].d_un.d_ptr;
- } else if (dyn[j].d_tag == kRelTag) {
- rel = dyn[j].d_un.d_ptr;
- } else if (dyn[j].d_tag == kRelSzTag) {
- relsz = dyn[j].d_un.d_ptr;
+ CHECK(tag != DT_ANDROID_REL && tag != DT_ANDROID_RELA);
+ if (tag == DT_RELR || tag == DT_ANDROID_RELR) {
+ relr = val;
+ } else if (tag == DT_RELRSZ || tag == DT_ANDROID_RELRSZ) {
+ relrsz = val;
+ } else if (tag == DT_JMPREL) {
+ pltrel = val;
+ } else if (tag == DT_PLTRELSZ) {
+ pltrelsz = val;
+ } else if (tag == kRelTag) {
+ rel = val;
+ } else if (tag == kRelSzTag) {
+ relsz = val;
}
}
+ // Apply RELR relocations first so that the GOT is initialized for ifunc
+ // resolvers.
+ if (relr && relrsz) {
+ relocate_relr(reinterpret_cast<ElfW(Relr*)>(ehdr + relr),
+ reinterpret_cast<ElfW(Relr*)>(ehdr + relr + relrsz), ehdr);
+ }
if (pltrel && pltrelsz) {
call_ifunc_resolvers_for_section(reinterpret_cast<RelType*>(ehdr + pltrel),
reinterpret_cast<RelType*>(ehdr + pltrel + pltrelsz));
@@ -737,8 +750,12 @@
ElfW(Ehdr)* elf_hdr = reinterpret_cast<ElfW(Ehdr)*>(linker_addr);
ElfW(Phdr)* phdr = reinterpret_cast<ElfW(Phdr)*>(linker_addr + elf_hdr->e_phoff);
- // string.h functions must not be used prior to calling the linker's ifunc resolvers.
- call_ifunc_resolvers();
+ // Relocate the linker. This step will initialize the GOT, which is needed for
+ // accessing non-hidden global variables. (On some targets, the stack
+ // protector uses GOT accesses rather than TLS.) Relocating the linker will
+ // also call the linker's ifunc resolvers so that string.h functions can be
+ // used.
+ relocate_linker();
soinfo tmp_linker_so(nullptr, nullptr, nullptr, 0, 0);
@@ -750,7 +767,6 @@
tmp_linker_so.phnum = elf_hdr->e_phnum;
tmp_linker_so.set_linker_flag();
- // Prelink the linker so we can access linker globals.
if (!tmp_linker_so.prelink_image()) __linker_cannot_link(args.argv[0]);
if (!tmp_linker_so.link_image(SymbolLookupList(&tmp_linker_so), &tmp_linker_so, nullptr, nullptr)) __linker_cannot_link(args.argv[0]);
diff --git a/linker/linker_phdr.cpp b/linker/linker_phdr.cpp
index 074012d..ef7671c 100644
--- a/linker/linker_phdr.cpp
+++ b/linker/linker_phdr.cpp
@@ -724,6 +724,16 @@
continue;
}
+ // If the PT_NOTE extends beyond the file. The ELF is doing something
+ // strange -- obfuscation, embedding hidden loaders, ...
+ //
+ // It doesn't contain the pad_segment note. Skip it to avoid SIGBUS
+ // by accesses beyond the file.
+ off64_t note_end_off = file_offset_ + phdr->p_offset + phdr->p_filesz;
+ if (note_end_off > file_size_) {
+ continue;
+ }
+
// note_fragment is scoped to within the loop so that there is
// at most 1 PT_NOTE mapped at anytime during this search.
MappedFileFragment note_fragment;
@@ -1270,11 +1280,6 @@
#if defined(__arm__)
-
-# ifndef PT_ARM_EXIDX
-# define PT_ARM_EXIDX 0x70000001 /* .ARM.exidx segment */
-# endif
-
/* Return the address and size of the .ARM.exidx section in memory,
* if present.
*
diff --git a/linker/linker_phdr.h b/linker/linker_phdr.h
index 4deed33..61242eb 100644
--- a/linker/linker_phdr.h
+++ b/linker/linker_phdr.h
@@ -43,8 +43,8 @@
public:
ElfReader();
- bool Read(const char* name, int fd, off64_t file_offset, off64_t file_size);
- bool Load(address_space_params* address_space);
+ [[nodiscard]] bool Read(const char* name, int fd, off64_t file_offset, off64_t file_size);
+ [[nodiscard]] bool Load(address_space_params* address_space);
const char* name() const { return name_.c_str(); }
size_t phdr_count() const { return phdr_num_; }
@@ -61,18 +61,18 @@
bool should_pad_segments() const { return should_pad_segments_; }
private:
- bool ReadElfHeader();
- bool VerifyElfHeader();
- bool ReadProgramHeaders();
- bool ReadSectionHeaders();
- bool ReadDynamicSection();
- bool ReadPadSegmentNote();
- bool ReserveAddressSpace(address_space_params* address_space);
- bool LoadSegments();
- bool FindPhdr();
- bool FindGnuPropertySection();
- bool CheckPhdr(ElfW(Addr));
- bool CheckFileRange(ElfW(Addr) offset, size_t size, size_t alignment);
+ [[nodiscard]] bool ReadElfHeader();
+ [[nodiscard]] bool VerifyElfHeader();
+ [[nodiscard]] bool ReadProgramHeaders();
+ [[nodiscard]] bool ReadSectionHeaders();
+ [[nodiscard]] bool ReadDynamicSection();
+ [[nodiscard]] bool ReadPadSegmentNote();
+ [[nodiscard]] bool ReserveAddressSpace(address_space_params* address_space);
+ [[nodiscard]] bool LoadSegments();
+ [[nodiscard]] bool FindPhdr();
+ [[nodiscard]] bool FindGnuPropertySection();
+ [[nodiscard]] bool CheckPhdr(ElfW(Addr));
+ [[nodiscard]] bool CheckFileRange(ElfW(Addr) offset, size_t size, size_t alignment);
bool did_read_;
bool did_load_;
diff --git a/linker/linker_relocate.cpp b/linker/linker_relocate.cpp
index 40299e9..85f7b3a 100644
--- a/linker/linker_relocate.cpp
+++ b/linker/linker_relocate.cpp
@@ -609,9 +609,13 @@
relocator.tlsdesc_args = &tlsdesc_args_;
relocator.tls_tp_base = __libc_shared_globals()->static_tls_layout.offset_thread_pointer();
- if (relr_ != nullptr) {
+ // The linker already applied its RELR relocations in an earlier pass, so
+ // skip the RELR relocations for the linker.
+ if (relr_ != nullptr && !is_linker()) {
DEBUG("[ relocating %s relr ]", get_realpath());
- if (!relocate_relr()) {
+ const ElfW(Relr)* begin = relr_;
+ const ElfW(Relr)* end = relr_ + relr_count_;
+ if (!relocate_relr(begin, end, load_bias)) {
return false;
}
}
diff --git a/linker/linker_soinfo.h b/linker/linker_soinfo.h
index a5d31d5..9a13af2 100644
--- a/linker/linker_soinfo.h
+++ b/linker/linker_soinfo.h
@@ -384,8 +384,6 @@
private:
bool relocate(const SymbolLookupList& lookup_list);
- bool relocate_relr();
- void apply_relr_reloc(ElfW(Addr) offset);
// This part of the structure is only available
// when FLAG_NEW_SOINFO is set in this->flags.
diff --git a/tests/headers/posix/limits_h.c b/tests/headers/posix/limits_h.c
index 7e92d81..0ca80a5 100644
--- a/tests/headers/posix/limits_h.c
+++ b/tests/headers/posix/limits_h.c
@@ -130,10 +130,10 @@
MACRO(CHARCLASS_NAME_MAX);
MACRO(COLL_WEIGHTS_MAX);
MACRO(EXPR_NEST_MAX);
- MACRO(LINE_MAX);
MACRO(NGROUPS_MAX);
MACRO(RE_DUP_MAX);
#endif
+ MACRO(LINE_MAX);
MACRO_VALUE(_POSIX_CLOCKRES_MIN, 20000000);
diff --git a/tests/limits_test.cpp b/tests/limits_test.cpp
index e5902ad..bc13a3f 100644
--- a/tests/limits_test.cpp
+++ b/tests/limits_test.cpp
@@ -21,6 +21,7 @@
TEST(limits, macros) {
ASSERT_EQ(8, CHAR_BIT);
ASSERT_EQ(8 * static_cast<int>(sizeof(int)), WORD_BIT);
+ ASSERT_EQ(2048, LINE_MAX);
ASSERT_EQ(20, NZERO);
#if !defined(MB_LEN_MAX)
#error MB_LEN_MAX