Skip to content

release: RELRO runtime re-protection (mach #1778)#339

Merged
octalide merged 3 commits into
mainfrom
dev
Jul 2, 2026
Merged

release: RELRO runtime re-protection (mach #1778)#339
octalide merged 3 commits into
mainfrom
dev

Conversation

@octalide

@octalide octalide commented Jul 2, 2026

Copy link
Copy Markdown
Collaborator

Release dev -> main. The only unreleased change is the RELRO runtime half of briar-systems/mach#1778 (#335): _rt_relocate captures AT_PAGESZ + PT_GNU_RELRO and, after applying RELATIVE relocations, mprotects the writer-page-rounded region PROT_READ before main — gated on exact page congruence, no runtime arithmetic, best-effort skip on large-page kernels (#336 tracks surfacing AT_PAGESZ to the OS layer).

Execution-verified on x86_64/aarch64(qemu)/riscv64(qemu): a write to a relocated val/vtable slot faults (SIGSEGV) post-hardening, reads and .data writes unaffected; mach-std mach test . 571 ok. The linker half (PT_GNU_RELRO emission) merged to mach dev as #1811; the mach-side lock bump + int write-fault guard follows this release. No other dev work is swept in.

octalide and others added 3 commits July 2, 2026 01:03
…ation

The static-PIE self-relocation maps a read-only segment holding relocated
constants (`.rodata` with vtables or `val` pointer globals) writable so it can
slide their RELATIVE slots. Once applied, re-protect that region read-only,
restoring the constants' hardening before `main`.

`_rt_relocate` now captures the PT_GNU_RELRO program header (and AT_PAGESZ) and,
after the relocation pass, `mprotect`s `[bias+p_vaddr, page-rounded end)` to
PROT_READ. The step runs after relocation, so it uses the ordinary syscall path;
it is best-effort (a kernel page larger than the image's segment alignment leaves
the region writable rather than failing the program).

Runtime half of briar-systems/mach#1778; the linker emits the PT_GNU_RELRO.
Address review of the PT_GNU_RELRO re-protection:

- No runtime page arithmetic. The writer now emits p_memsz already page-rounded,
  so `_rt_relocate` gates on the region being a whole number of runtime pages
  (start and size both AT_PAGESZ-congruent) and mprotects it exactly. On a kernel
  page larger than the image's 4 KiB segment alignment the gate skips, leaving the
  region writable (correct, just unhardened) instead of risking EINVAL or
  over-protecting the following segment. Tracked by #336.
- Drop the AT_PAGESZ==0 -> 4096 fabrication; AT_PAGESZ is mandatory on linux, so
  skip hardening when it is absent rather than guessing.
- Decouple the re-protection from reloc presence: the RELATIVE apply is guarded
  rather than early-returned, so the mprotect no longer sits behind a reloc-count
  gate (they are only coupled by the writer, which emits RELRO for reloc-bearing
  segments).
- Use the bare literal 0x6474e552 for PT_GNU_RELRO in the pre-relocation phdr walk
  (matching its neighbors, so a codegen change can't silently disable it), and
  export PROT_READ from the shared OS layer instead of a duplicate local constant.
feat(runtime/linux): mprotect PT_GNU_RELRO read-only after self-relocation
@octalide octalide merged commit 89a7540 into main Jul 2, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant