-
Notifications
You must be signed in to change notification settings - Fork 1
libc/ld compartmentalization (minus dynamic allocations) #642
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
- Modified ia2.c to allow system libraries (ld.so, libc) in compartment 1 - Added new test dl_debug_test that uses iconv to trigger _dl_debug_state - Updated rewriter to skip wrappers for same-compartment calls - Test demonstrates _dl_debug_state inherits compartment from calling libc function
Enables iconv to work across compartments when libc is protected in compartment 1. Uses shared memory (pkey 0) for both pointer containers and data buffers to allow iconv in compartment 1 to access parameters passed from compartment 2. Changes: - tests/dl_debug_test/library.c: Use shared_malloc for iconv buffers and pointer containers to avoid SEGV_PKUERR when accessing stack - tests/dl_debug_test/main.c: Set PKRU=0 before test exit to allow destructors from different compartments to access their .bss sections - runtime/libia2/exit.c: Set PKRU=0 during exit cleanup to prevent violations when destructors access protected memory - runtime/libia2/init.c: Disable ia2_setup_destructors to avoid compartment 0 switches that cause libc exit handler failures This is a testing workaround that maintains protection during execution while relaxing it during cleanup. See ICONV_SHARED_MEMORY_SOLUTION.md for complete analysis.
- record the September 30, 2025 ctest run in the phase0 progress note - add a status snapshot to the exit-handler roadmap before starting phase 1
Library destructors need to call libc functions (e.g., __cxa_finalize) which access libc's .bss section protected by pkey 1. Previously, destructor wrappers switched exclusively to the target compartment (e.g., pkey 2), causing SEGV_PKUERR when the destructor called back into libc. Solution: Use union PKRU value (0xffffffc0 for pkeys 1+2) that allows simultaneous access to both the exit compartment (libc, pkey 1) and target compartment (pkey 2) during destructor execution. This prevents protection key violations when destructors call libc functions via PLT without requiring wrappers for every libc call. Changes: - tools/rewriter/GenCallAsm.cpp: Add optional union_pkey parameter to emit_set_pkru() - tools/rewriter/GenCallAsm.h: Add use_union_pkru parameter to emit_asm_wrapper() - tools/rewriter/SourceRewriter.cpp: Pass use_union_pkru=true for destructor wrappers - runtime/libia2/init.c: Re-enable ia2_setup_destructors() call - runtime/libia2/CMakeLists.txt: Add trace_exit.c to build - runtime/libia2/include/ia2_internal.h: Add ia2_trace_exit_record() declaration
- expose --exit-mode on the rewriter and plumb args from test helpers - add __cxa_finalize callgate hooks so destructor PKRUs honor policy - default dl_debug scenarios to callgate mode while keeping union escape
Replace .ifdef (assembly symbol check) with #if defined() (C preprocessor). The .ifdef never worked because IA2_TRACE_EXIT is a -D flag, not an ELF symbol.
wip callgate policy
- Remove PKRU=0 security bypass, restore proper PKRU(0) - Initialize exit policy early to avoid pthread_once during cleanup - Fix test environment variable propagation (use explicit test names) - Switch dl_debug_mbstowcs_test to callgate mode
c971bc4 to
b07883e
Compare
|
Overall approach LGTM. The only part I have left to review is the __wrap_cxa_finalize assembly |
| @@ -0,0 +1,8 @@ | |||
| #if defined(IA2_LIBC_COMPARTMENT) && IA2_LIBC_COMPARTMENT | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm confused. Is this file supposed to be a header? Also if you're only calling __real___cxa_finalize from assembly there's no point to having a function declaration and we should just remove it.
| #include "ia2_internal.h" | ||
|
|
||
| #if defined(__x86_64__) | ||
| uint32_t ia2_read_pkru(void) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can just remove static from the ia2_get_pkru function in ia2.c and add a function declaration for it somewhere. You could also move ia2_write_pkru to that source file.
|
A few minor nits, but otherwise looks fine |
No description provided.