Repository navigation
Integrate scoped Linux Test Project syscall conformance #171
Description
Goal
Integrate a scoped Linux Test Project (LTP) syscall conformance suite into elfuse.
Use a pinned shallow LTP checkout, apply local patches if needed, and run a curated syscall subset through the existing make check flow.
Rules:
- Do not use git submodules.
- Do not copy LTP files into elfuse.
- Retrieve LTP with
git clone --depth=1. - Keep LTP under
build/ltp-src. - Treat LTP as a vendored test dependency and syscall semantics oracle.
- Keep elfuse-specific changes as local patches.
- Keep the default
make checkslice fast and deterministic.
Sub-tasks
1. Fetch pinned LTP with shallow clone
Add a reproducible fetch step for LTP.
Implementation:
- Add
tests/fetch-ltp.sh. - Fetch LTP into:
build/ltp-src - Use shallow clone:
git clone --depth=1 --branch <tag-or-branch> \ https://github.com/linux-test-project/ltp \ build/ltp-src
- Resolve and record the exact commit:
git -C build/ltp-src rev-parse HEAD > build/ltp-src/.ltp-ref - If
build/ltp-src/.ltp-refalready matches the requested SHA, reuse the checkout. - If it does not match, delete
build/ltp-srcand fetch again. - Expose override variables:
LTP_REF=<tag-or-branch-or-sha> LTP_URL=https://github.com/linux-test-project/ltp LTP_DIR=build/ltp-src
Considerations:
- No git submodule.
- No generated LTP build output should be committed.
- A shallow clone by SHA may need a fetch fallback because
git clone --depth=1 --branch <sha>is not portable for raw SHAs. Accept tag/branch by default, then verify resolved SHA. - Network access should happen only in explicit fetch/build targets, not every
make check. - The script should be idempotent.
Validation:
rm -rf build/ltp-src
LTP_REF=<tag-or-branch> tests/fetch-ltp.sh
test -s build/ltp-src/.ltp-ref
git -C build/ltp-src rev-parse --is-shallow-repositoryExpected:
.ltp-refexists.- checkout is shallow.
- rerunning the script reuses the checkout when the ref matches.
2. Apply elfuse-specific LTP patches
Support a small patch stack on top of the pinned LTP checkout.
Implementation:
- Add patch directory:
tests/fixtures/ltp/patches/ - Apply patches after clone:
for p in tests/fixtures/ltp/patches/*.patch; do git -C build/ltp-src apply "$p" done
- Make patch application deterministic:
- apply in lexical order,
- fail on reject,
- do not continue with a partially patched tree.
- Add a marker file after successful patching, for example:
build/ltp-src/.elfuse-patches-applied
Considerations:
- Patches may adapt build flags, skip unavailable fixtures, or make paths deterministic.
- Patches must not weaken expected Linux syscall semantics just to make elfuse pass.
- Prefer upstreamable patches where possible.
- If a case needs unsupported kernel features, classify it in the manifest rather than changing the test expectation.
- Reapplying patches should not silently double-apply; fetch script should start from a clean checkout when the patch set changes.
Validation:
rm -rf build/ltp-src
tests/fetch-ltp.sh
test -f build/ltp-src/.elfuse-patches-applied
git -C build/ltp-src status --shortExpected:
- patches apply cleanly,
- patched tree state is reproducible.
3. Define the syscall conformance scope
Keep the initial scope tight: only syscall behavior elfuse actively emulates and can run without privileged host setup.
Implementation:
- Add
tests/ltp-syscalls.tsv. - Populate it only with scoped syscall cases from LTP
runtest/syscalls. - Group rows by family:
fdpathprocesssignalidentitymemoryresourcepolltimereventsocketipc
Initial in-scope families:
Path and FD:
openatcloseclose_rangedupdup3fcntllseekreadwritepread64pwrite64readvwritevstatxnewfstatatfaccessat2renameat2unlinkatlinkatsymlinkatreadlinkatmkdiratgetdents64
Process, signal, identity:
cloneclone3forkexecveexecveatwait4waitidexit_groupkilltkilltgkillrt_sigactionrt_sigprocmaskrt_sigtimedwaitrt_sigsuspendsigaltstackgetpidgettidgetppidgetuidgeteuidgetgidgetegidgetresuidgetresgidset_tid_address
Memory and resource:
brkmmapmprotectmunmapmremapmsyncmincoremadvisegetrlimitprlimit64getrusagesysinfo
Poll, timer, event:
pollppollpselect6epoll_create1epoll_ctlepoll_pwaiteventfd2timerfd_createtimerfd_settimetimerfd_gettimesignalfd4pipe2
Fixture-light socket and IPC:
socketpairsendmsgrecvmsggetsockoptsetsockoptshutdownsemgetsemopsemtimedopsemctlshmgetshmatshmdtshmctlmsggetmsgsndmsgrcvmsgctl
Out of scope for this issue:
- namespaces
- cgroups
- BPF
- perf events
- keyrings
- module loading
- fanotify
- io_uring
- Landlock
- raw packet sockets / AF_PACKET
- raw block-device tests
- hugepage-only tests
- root-only host mutation
- broad mount/umount coverage outside existing elfuse FUSE tests
- tests requiring a real Linux
/dev, block device, network namespace, or kernel security module setup
Considerations:
- The manifest should classify cases, not silently drop them.
non-goalis only for features already documented as elfuse Non-Goals.- Implemented syscalls must not be hidden as
non-goal. - Fixture-heavy but relevant tests should be
skip-fixture, notnon-goal. - Scope can expand later after the fast path is stable.
Validation:
make check-ltp-planExpected:
- all in-scope families have manifest entries,
- out-of-scope rows include a reason,
- unclassified in-scope rows fail the check.
4. Add the LTP syscall manifest
Define exactly what runs, what skips, and why.
Implementation:
- Add:
tests/ltp-syscalls.tsv - Columns:
case family ltp_command status reason fixture make_check - Status values:
check-enabled: run inmake checkandmake test-ltpenabled: run inmake test-ltp-fullskip-fixture: relevant, but fixture unavailable by defaultskip-privileged: relevant, but needs root or unsafe host mutationknown-fail: relevant, expected to fail until elfuse implementation changesnon-goal: outside elfuse scope and documented under Non-Goalsunclassified: discovered but not triaged yet
Considerations:
make_check=trueonly for fast deterministic cases.known-failrows must point at a TODO or issue and likely source area.- Manifest rows should use LTP case names, not local aliases.
- The manifest should be reviewable by humans; avoid generating unreadable blobs.
- Updating the pinned LTP ref should surface renamed/deleted cases.
Validation:
make check-ltp-planChecks:
- every
check-enabled/enabledcase exists inruntest/syscalls, - every enabled command has a built binary/script,
- every in-scope family has at least one classified row,
- no implemented syscall maps to
non-goal, - no stale LTP case names remain after updating the pin.
5. Build only the selected LTP syscall subset
Add build support for the manifest-selected cases.
Implementation:
- Add:
make ltp-syscalls
- Depend on
tests/fetch-ltp.sh. - Configure LTP in
build/ltp-src. - Build only the cases referenced by
tests/ltp-syscalls.tsv. - Avoid installing full LTP into
/opt/ltp. - Stage runnable artifacts under:
build/ltp/ - Export required LTP runtime variables when running:
LTPROOT=$(pwd)/build/ltp PATH="$LTPROOT/testcases/bin:$PATH"
Considerations:
- Full LTP is too broad for the default path.
- Some LTP tests require helper binaries; the subset build must include those helpers.
- Some shell tests need
LTPROOTandPATH. - Build failures for skipped rows should not fail the selected subset.
- Keep cross-build flags compatible with elfuse guest binaries.
Validation:
make ltp-syscalls
test -d build/ltp/testcases/bin6. Run conformance through the existing test driver
Consolidate execution under the current test system.
Implementation:
- Add:
make test-ltp make test-ltp-full
- Add
test-ltptomake check. - Reuse:
tests/lib/test-runner.sh - Run:
check-enabledrows formake checkandmake test-ltp,enabledpluscheck-enabledrows formake test-ltp-full.
- Emit:
build/ltp-syscall-results.json - Store per-case logs under:
build/ltp/logs/
Considerations:
make checkmust remain fast enough for normal CI/CD.make test-ltpis the quick conformance gate.make test-ltp-fullis for broader compatibility verification.- Use timeout protection for every LTP case.
- Use skip code 77 for unavailable optional fixtures.
- Preserve LTP's own pass/fail/skip status when possible.
- Do not create a second unrelated test reporting format; fit into existing output conventions.
Validation:
make check
make test-ltp
make test-ltp-full7. Compare against Linux reference when available
Use QEMU AArch64 as the Linux syscall semantics reference.
Implementation:
- Support:
make test-ltp LTP_REFERENCE=qemu make test-ltp-full LTP_REFERENCE=qemu
- Run the same selected LTP case under:
- elfuse
- QEMU AArch64 Linux reference
- Compare:
- LTP result status
- exit status
- signal termination
- timeout
- child wait status where visible
- relevant stdout/stderr summary
- Store both logs.
Considerations:
- QEMU absence should skip reference comparison, not fail local
make check. - Prefer comparing LTP result status before raw output.
- Raw output can differ in harmless paths, timings, PIDs, or hostnames.
- For errno-visible failures, logs must retain enough detail to diagnose mismatch.
Validation:
make test-ltp LTP_REFERENCE=qemu8. Promote failures into actionable implementation work
Make conformance failures easy to turn into elfuse fixes.
Implementation:
- Add:
scripts/ltp-results-to-todo.py - Read:
build/ltp-syscall-results.json - Emit one TODO-ready block per unique failure.
Each block should include:
- LTP case
- syscall family
- LTP command
- elfuse result
- QEMU/Linux reference result when available
- log path
- likely elfuse owner file under
src/syscall/*.c - reproducer command
Considerations:
- Do not generate tasks for
skip-*ornon-goal. - Group duplicate failures by syscall family and likely owner file.
- Keep generated tasks small and independently fixable.
- Prefer fixing shared syscall handlers over patching individual tests.
Validation:
python3 scripts/ltp-results-to-todo.py build/ltp-syscall-results.jsonCompletion Criteria
- LTP is retrieved with
git clone --depth=1. - No git submodule is used.
- The resolved LTP commit is recorded.
- Local LTP patches, if any, apply cleanly.
tests/ltp-syscalls.tsvdefines a scoped syscall set.make check-ltp-planvalidates the manifest.make ltp-syscallsbuilds selected cases.make checkrunsmake test-ltp.make test-ltpruns the quick CI/CD conformance slice.make test-ltp-fullruns the broader compatibility suite.- QEMU comparison works when configured.
- Results are written to
build/ltp-syscall-results.json. - Failures can be promoted into actionable implementation TODOs.
Activity
[-]Integrate scoped LTP syscall conformance into make check[/-][+]Integrate scoped Linux Test Project syscall conformance[/+]jserv commentedon Jul 8, 2026
Reference: Linuxulator (Linux Emulation) from FreeBSD, using LTP.
Compatibility page contains a non-exhaustive list of games tested on FreeBSD with Linux emulation.
henrybear327 commentedon Jul 18, 2026
Initial prototyping discovered several issues blocking the integration. I will submit PRs fixing the blocker, and the initial PoC implementation in a bit.
henrybear327 commentedon Jul 18, 2026
Before #218 is merged, LTP can't produce meaningful results. Thus, I am holding on to active development for now.
henrybear327 commentedon Jul 19, 2026
#228 is also blocking LTP from executing the tests.
henrybear327 commentedon Aug 27, 2026
Ground work #339