Skip to content

Conversation

@oinoom
Copy link
Contributor

@oinoom oinoom commented Sep 30, 2025

No description provided.

- 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
oinoom and others added 7 commits October 3, 2025 14:05
- 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.
- 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
@oinoom oinoom force-pushed the fix.so branch 2 times, most recently from c971bc4 to b07883e Compare October 3, 2025 20:14
@ayrtonm
Copy link
Contributor

ayrtonm commented Nov 12, 2025

Overall approach LGTM. The only part I have left to review is the __wrap_cxa_finalize assembly

@oinoom oinoom requested a review from ayrtonm November 21, 2025 17:11
@@ -0,0 +1,8 @@
#if defined(IA2_LIBC_COMPARTMENT) && IA2_LIBC_COMPARTMENT
Copy link
Contributor

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) {
Copy link
Contributor

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.

@ayrtonm
Copy link
Contributor

ayrtonm commented Nov 25, 2025

A few minor nits, but otherwise looks fine

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.

3 participants