6.5 KiB
eatmycode_version
| eatmycode_version |
|---|
| 2.1.0 |
POSIX Personalities and Syscalls
Owner: Project architecture
Read when: changing qiling/os/posix/ except kernel_proxy/, or Linux, FreeBSD, macOS and QNX personalities.
Responsibility and Status
Owns syscall ABIs/dispatch, common POSIX handlers, Linux processes/threads, futex/procfs and FreeBSD/macOS/QNX personalities, including driver API support. In progress: representative Linux, RISC-V and QNX execution passes; full syscall, threading, network and macOS behavior is unverified.
Code Map
| Path / symbol | Role |
|---|---|
posix/posix.py: QlOsPosix, QlFileDes |
Hooks, argument dispatch, identity/network configuration and fd table |
| posix/syscall/, posix/syscall/abi/ | Common handlers, syscall-register conventions and return encodings |
linux/linux.py: QlOsLinux; linux/thread.py, linux/futex.py, linux/procfs.py |
Linux traps, cooperative guest threads, futex state and virtual procfs |
| freebsd/, macos/, qnx/ | OS-specific maps, syscalls, structures, kernel APIs and messages |
test_posix.py, test_elf.py, test_elf_multithread.py, tests/ test_elf_ko.py, test_android.py, test_qnx.py, test_macho*.py, test_tendaac15_httpd.py |
Syscalls, programs, threads and platform integration |
examples/src/ linux/, freebsd/, macos/, qnx/; profiles/ |
Guest fixture sources and consumed OS settings |
Local Conventions
Use root conventions. Common
handlers are ql_syscall_<name>(ql, ...); ordinary positional parameter
names/counts matter because dispatcher introspection reads guest arguments.
OS-specific handlers precede common POSIX implementations. Keep per-OS
layouts and error semantics; do not unify superficially similar handlers.
Fixture Makefiles specify cross-compilers locally; no common C standard is declared.
Contracts and Invariants
- Dispatch maps syscall ID to name, resolves CALL/ENTER/EXIT overrides by
name or number, then OS-specific/common handler. ENTER may replace args;
EXIT may replace result;
Noneleaves the return register untouched (QlOsPosix.load_syscall). Missing handlers warn and raise only whendebug_stoprequests it; automatic host forwarding is absent. - Syscall ABI owns register decoding and negative errno encoding. Function
calling conventions are separate. Hook signatures must match dispatch
introspection, particularly wrappers using only
*args. - Fds 0–2 track standard streams; descriptors are polymorphic objects. Closing/duplicating/replacing them must preserve ownership and errors.
- Linux guest threads use gevent/cooperative Unicorn contexts; this does
not imply full native Linux scheduling or signal delivery.
sched.pycan call host fork; socket handlers operate on host sockets. - Linux
/proc/selfmappings are installed only when not overridden. Profile identity and network keys affect observable guest behavior. macOS kernel and QNX message interfaces retain their own state/layouts. - Linux registers
hook_intnotraps per architecture: the syscall interrupt (viaEXCPenums on ARM/ARM64/MIPS, literals elsewhere) plus ARM/ARM64UDEFand MIPSRICPU exceptions.hook_cpu_exceptionlogs the SIGILL equivalent and callsql.stop(), so falling into non-code bytes ends emulation cleanly instead of raisingQlErrorCoreHook; no guest signal handler runs (linux/linux.py). - Syscall result structs follow
ql.arch.endian:statxselects the*EBbig-endian ctypes variants for EB guests (syscall/stat.py). Check endian handling in any handler that writes ctypes layouts.
Dependencies and Boundaries
Read OS base for memory/paths/fds, arch for syscall register contracts, loaders for process entry/auxv/driver imports, and kernel proxy for forwarded descriptors. Proxy integration must use existing hooks and fd polymorphism; it does not own dispatch. Filesystem/socket/fork operations expose host resources.
Change Guide
| Change trigger | Inspect / extend | Required docs / checks |
|---|---|---|
| New/fixed syscall | Mapping table, ABI, OS override/common handler | Update this contract; matching test_posix/ELF test and affected OS |
| Thread/futex/signal | Thread contexts, yielding, futex waiters | test_elf_multithread.py; mark unsupported semantics explicitly |
| CPU exception/trap | hook_intno registrations, hook_cpu_exception, EXCP enums |
Shellcode illegal-instruction cases; read arch for new exception codes |
| FD/path/socket | Host object lifetime, errno, guest structure layouts | OS-base checks and syscall regression; proxy checks if shared operations change |
| macOS/QNX/kernel API | Local maps/structs, loader imports | Platform-specific test and loader owner |
Verification
From tests/: python -m unittest test_elf.ELFTest.test_elf_linux_x8664 test_riscv test_qnx
and python -m unittest test_shellcode.TestShellcode.test_linux_arm64_illegal_instruction test_shellcode.TestShellcode.test_linux_mips32_illegal_instruction test_elf.ELFTest.test_linux_statx_bigendian
passed during the latest refresh. They check sample Linux/RISC-V/QNX flows,
SIGILL-style termination and big-endian statx, not every handler.
For POSIX changes run python test_posix.py (also imports ELF,
RISC-V and CLI suites), and the relevant thread/kernel/network/platform
script. Follow shared test-resource rules when
running these suites. Root Linux aggregate is the broader CI gate; its fixtures, extracted
kernel sample and network/host requirements apply. Full aggregate was not run.
Known Gaps
macOS CI is commented out. Some thread classes are unset for RISC-V/PPC;
signal syscall state is not proof of full delivery. CPU-exception hooks
exist only for ARM/ARM64/MIPS; x86, RISC-V and PPC undefined instructions
still surface as QlErrorCoreHook. Existing kernel-module
archives need fixture preparation. TODO.md hybrid phases are plans; proxy
Phase 0 implementation is documented separately. Current representative
checks do not establish kernel fidelity or host isolation.