Skip to content

Targeted TCB Carveout #677

Open
oinoom wants to merge 1 commit intomainfrom
exp/targeted-tcb-main-baseline
Open

Targeted TCB Carveout #677
oinoom wants to merge 1 commit intomainfrom
exp/targeted-tcb-main-baseline

Conversation

@oinoom
Copy link
Copy Markdown
Contributor

@oinoom oinoom commented Mar 31, 2026

Problem

IA2 retags writable memory (including PT_TLS-backed TLS pages) to compartment pkeys.
On x86_64, the page containing __builtin_thread_pointer() (the TCB page addressed through %fs) holds process ABI state that can be accessed while different compartment PKRU values are active.

That ABI state includes stack-protector canary reads such as %fs:0x28, which occur in normal function prologues/epilogues and are not tied to a single compartment's policy boundary.
If this page remains compartment-tagged, code can fault when execution reaches one of these ABI reads under a PKRU that cannot access that page.

Observed on main during single-thread dav1d decode:

  • crash site: dav1d_ref_create+16
  • faulting instruction: mov %fs:0x28,%rax
  • fault class: PKRU permission failure on %fs-relative TCB access

Fix In This Branch

This branch applies a minimal x86_64-only startup hardening change (and replaces #671):

  • Keep existing protect_tls_pages() logic unchanged.
  • Add ia2_unprotect_thread_pointer_page() that:
    • computes tcb_page = round_down(__builtin_thread_pointer(), PAGE_SIZE)
    • retags exactly that one page to shared pkey 0 via ia2_mprotect_with_tag()
  • Call that helper in ia2_start() after compartment setup/TLS retagging has run, before init completion.
  • Keep AArch64 behavior unchanged (no-op stub for symbol parity).

What This Branch Accomplishes

  • Removes the first strict-mode dav1d decode blocker on main (the %fs:0x28 TCB access fault).
  • Demonstrates forward progress to the next independent blocker (__tls_get_addr / _rtld_local).

How This Differs From #671

#671 widened runtime TLS policy in protect_tls_pages() (bounded multi-page carveout set, sorted carveout walk, per-thread carveout handling, redundant-retag avoidance).

This branch intentionally does not do that.
It is a narrower replacement branch that changes only startup TP-page treatment and leaves protect_tls_pages() as in main.

Practical effect:

  • broader branch: attempts a generalized shared-TLS carveout policy
  • this branch: fixes only the x86_64 TP-page visibility blocker from first principles

@oinoom oinoom requested review from ayrtonm and fw-immunant March 31, 2026 17:54
@ayrtonm
Copy link
Copy Markdown
Contributor

ayrtonm commented Mar 31, 2026

I think this is a better approach than #671.

return ia2_get_tag();
}

void ia2_unprotect_thread_pointer_page(void) {}
Copy link
Copy Markdown
Contributor

@ayrtonm ayrtonm Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might be better to remove this no-op since it could easily get missed later on and instead just add #if defined(__x86_64__) around this function's callsite.

Copy link
Copy Markdown
Contributor

@ayrtonm ayrtonm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with a small change

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.

2 participants