Skip to content

Implement mprotect()-based module isolation for the Linux/GNU simulation port (and Windows equivalent) #557

Description

@fdesbiens

Summary

The Linux/GNU simulation target has no module port. Adding one as a test scaffold only (no memory isolation) would allow the module manager sources to compile and be unit-tested on Linux but would not implement:

  • Memory isolation (no mprotect()/MPU enforcement)
  • The privileged dispatcher gate (no SVC-equivalent)
  • Module binary loading from filesystem images
  • Bounds checking on module-to-kernel pointer parameters

The goal of this issue is to go further and implement real mprotect()-based isolation in the Linux simulation port, making it useful for module boundary validation, developer tooling, and fuzzing.

Proposed implementation: mprotect()-based isolation

Use mprotect() as a software analog to the ARM MPU:

Embedded (ARM Cortex-M) Linux simulation
8–16 MPU region registers Two mprotect() region descriptors
SVC instruction → SVC handler C dispatcher gate with mprotect() permission swap
Hardware MPU reload on context switch mprotect() syscall (~1 µs per switch)
MEMFAULT exception SIGSEGVsigaction() handler

New directory structure

ports_module/linux/gnu/
├── inc/
│   └── txm_module_port.h                        # port header
└── module_manager/src/
    ├── txm_module_manager_mm_setup.c            # mmap regions, mprotect enforcement
    ├── txm_module_manager_user_mode_entry.c     # replaces SVC gate
    └── txm_module_manager_memory_fault.c        # SIGSEGV handler → module fault callback

TXM_MODULE_MANAGER_PORT_EXTENSION would add two mprotect region descriptors to TXM_MODULE_INSTANCE (code region + data region).

Dispatcher gate sketch

ALIGN_TYPE _txm_module_manager_user_mode_entry(ULONG request, ...)
{
    ALIGN_TYPE result;
    mprotect(module_code, code_size, PROT_NONE);
    mprotect(module_data, data_size, PROT_NONE);
    result = _txm_module_manager_kernel_dispatch(request, ...);
    mprotect(module_code, code_size, PROT_READ | PROT_EXEC);
    mprotect(module_data, data_size, PROT_READ | PROT_WRITE);
    return result;
}

Fault detection

static void module_fault_handler(int sig, siginfo_t *si, void *ctx)
{
    /* Walk module list, find owner of faulting address, invoke module fault callback */
    _txm_module_manager_fault_notify(faulting_module);
}

Known limitation: process-wide protection

mprotect() changes affect the entire process. In a multi-threaded scenario, only one module can be active at a time without a global lock. A future upgrade to Intel MPK (pkey_mprotect() + wrpkru) on capable hardware (Linux on Skylake+/Zen 2+) would remove this constraint because the PKRU register is thread-local.

Windows equivalent

A Windows counterpart in ports_module/win32/msvc/ is equally feasible using VirtualProtect() and AddVectoredExceptionHandler():

Linux Windows
mmap(MAP_ANONYMOUS|MAP_PRIVATE) VirtualAlloc(MEM_COMMIT|MEM_RESERVE)
mprotect(..., PROT_NONE) VirtualProtect(..., PAGE_NOACCESS, &old)
mprotect(..., PROT_READ|PROT_WRITE) VirtualProtect(..., PAGE_READWRITE, &old)
mprotect(..., PROT_READ|PROT_EXEC) VirtualProtect(..., PAGE_EXECUTE_READ, &old)
sigaction(SIGSEGV, ...) AddVectoredExceptionHandler(...)
SIGSEGV EXCEPTION_ACCESS_VIOLATION

Note: Intel MPK is not available on Windows. VirtualProtect() is the ceiling on that platform, which is acceptable for a simulation/test port.

Why this matters

  1. Module developer tooling: Catch isolation violations (stray pointer into kernel memory) as SIGSEGV instead of silent corruption on developer workstations, without requiring embedded hardware.
  2. Fuzzing infrastructure: AFL/libfuzzer can target module inputs with real boundary detection on Linux.
  3. CI coverage: Isolation-breach scenarios can be validated in automated pipelines without a hardware target.

Scope

This is a new platform feature. The ports_module/linux/gnu/ directory and CMake wiring need to be created from scratch as part of this work.

Estimated effort: ~500–800 lines of new C code plus tests for each platform port.

Metadata

Metadata

Assignees

No one assigned

    Labels

    featureNew feature or enhancement request

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions