kafel
Author: Ludovic HENRY ludovic.henry@qti.qualcomm.com
Date: 2026-06-17
Scope: RISC-V (riscv64/linux) support status for kafel
Audience: Technical leadership, resource allocation strategy
Verification policy: Every claim is cross-referenced to a primary upstream source. Items that could not be verified against a second source are marked [NEEDS VERIFICATION].
1. Project Overview
Kafel is a C library and domain-specific language for expressing Linux seccomp-BPF syscall filter policies. It compiles human-readable policy text into BPF bytecode suitable for use with prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, ...). The primary known consumer is nsjail, a lightweight Linux process isolation tool.
The project is hosted under the google GitHub organization at github.com/google/kafel and licensed under Apache-2.0. The README explicitly states: “This is NOT an official Google product.” There is no foundation affiliation, no OWNERS or CODEOWNERS file, and no formal governance document.
Maintainers:
- Wiktor Garbacz (wiktorg@google.com, GitHub: happyCoder92) - Google engineer, 73 of 112 total commits (~65%), historical primary driver.
- Robert Swiecki (robert@swiecki.net, GitHub: robertswiecki) - independent security researcher and nsjail author, 18 commits, most recent activity including 2025-2026 riscv64 work.
Google LLC is a Premier Member of the RISE Project. Kafel itself is not listed as a RISE project and no RISE blog posts, wheel builder entries, or GitHub repositories reference kafel.
Community stance on new ports is informal and open. The riscv64 port was accepted from an external contributor with no documented review policy. Patches are accepted via GitHub pull request.
2. Port History and Upstreaming Timeline
All riscv64 work is fully merged to the main branch. There is no tracking issue and no pending work.
| Date | Event | Source |
|---|---|---|
| 2021-10-11 | PR #31 merged: “add riscv64 platform” - adds KAFEL_TARGET_ARCH_RISCV64 enum, arch detection in common.h, AUDIT_ARCH_RISCV64 registration in syscall.c, and riscv64_syscalls.c syscall table. Triggered by a user building nsjail on RISC-V hardware hitting #error "Unsupported architecture". |
commit 21b96af0 |
| 2021-10-11 | commit 862f8f33: “Fix RISCV syscall table” - syscall table correction landed same day as PR #31. | commit 862f8f33 |
| 2021-10-27 | PR #32 merged: “Fix riscv64 judgment” - tightens arch detection from #ifdef __riscv (matches any RISC-V variant) to defined(__riscv) && __riscv_xlen == 64. |
commit 362ac7b6 |
| 2021-10-27 | PR #33 merged: “Modify riscv_len to riscv_xlen” - renames a constant to use standard RISC-V terminology (XLEN = integer register width). | commit fdc1d644 |
| 2023-10-04 | Release 20231004 published - the first release containing all three riscv64 PRs. Release 20200831 predates all riscv64 work. |
GitHub Releases |
| 2025-09-22 | commit c13ce1fc: “riscv64: vibecoded missing syscalls” - direct push by Robert Swiecki adding 390 lines to riscv64_syscalls.c, covering Linux 5.x-6.x additions (io_uring 425-427, landlock 444-446, futex_wake/wait/requeue 454-456, lsm_* 459-461, file_getattr/setattr 468-469, and others up to syscall 469). Commit message indicates AI-assisted generation. |
commit c13ce1fc |
Key contributors to riscv64 work:
- IEAST (w1031791815@gmail.com) - external community contributor, no identified corporate affiliation. Authored PRs #31, #32, #33.
- happyCoder92 (Wiktor Garbacz, Google) - merged all three PRs and landed the same-day syscall table fix.
- robertswiecki (Robert Swiecki) - September 2025 syscall update.
The port is fully upstream. No downstream patches, no forks carrying riscv64-specific changes, no pending PRs.
3. Upstream Support Tier
Kafel has no formal tier policy and no PLATFORMS.md or equivalent document. riscv64 is listed alongside x86_64, x86, arm, aarch64, mips64, and m68k in README.md as a supported target architecture, with no distinction in support level.
Support is maintained on an ad-hoc basis. There is no release-blocking CI for any architecture, no official riscv64 binaries, and no documented test coverage policy.
Architecture comparison (support tier evidence):
| Criterion | amd64 | arm64 | riscv64 |
|---|---|---|---|
| Listed in README as supported | Yes | Yes | Yes |
| Syscall table exists | Yes | Yes | Yes |
| Syscall entry count | 382 | 321 | 320 |
| Arch detection macro | Yes | Yes | Yes |
| Public API enum value | Yes | Yes | Yes |
| CI coverage | None | None | None |
| Official prebuilt binaries | None | None | None |
| Packaged in Debian/Ubuntu | No | No | No |
All architectures are on equal informal footing - there is no tiered support model. riscv64 is effectively at parity with arm64 by every available metric.
4. Technical Architecture and RISC-V-Specific Subsystems
Kafel is a seccomp-BPF policy compiler. Its output is BPF bytecode; it does not generate native machine code. This means there is no JIT backend, no SIMD dispatch, no crypto implementation, no native assembly, and no GC to instrument. RISC-V support requires only two things: an architecture detection macro and a syscall descriptor table.
RISC-V-specific components:
| Component | File | Lines / Size | ISA Extensions | Quality | Status |
|---|---|---|---|---|---|
| Arch detection macro | src/common.h |
~5 lines | None | Scalar C preprocessor | Complete |
| Syscall descriptor table | src/syscalls/riscv64_syscalls.c |
2,236 lines / 46,731 bytes | None | Statically defined C struct array | Complete |
| Runtime registration | src/syscall.c |
~8 lines | None | Guarded by #ifdef AUDIT_ARCH_RISCV64 |
Complete |
| Public API enum | include/kafel.h |
1 line | None | KAFEL_TARGET_ARCH_RISCV64 = 1 << 7 |
Complete |
No ISA extensions (RVV, Zba, Zbb, Zbc, Zbs, or any SIMD) are used or needed. There are no hand-tuned assembly paths for any architecture. The library is pure portable C throughout.
Architecture comparison:
| Component | amd64 | arm64 | riscv64 |
|---|---|---|---|
| Arch detection macro | Yes | Yes | Yes |
| Syscall table | 382 entries / 53,192 bytes | 321 entries / 46,885 bytes | 320 entries / 46,731 bytes |
| Runtime registration | Yes | Yes | Yes |
| Public API enum | Yes | Yes | Yes |
| SIMD / ISA-extension code | None | None | None |
| JIT backend | None | None | None |
Assembly (.S files) |
None | None | None |
riscv64’s 320 entries vs arm64’s 321 reflects the leaner riscv64 Linux ABI, which has no legacy syscalls and no 32-bit compatibility layer. This is expected and not a gap.
5. Build System, Cross-Compilation, and Toolchain
Build system: GNU Make only. There is no CMake, no autoconf, no configure script, and no CMakeLists.txt in the repository.
Native riscv64 build (on a riscv64 host):
make
The arch detection in src/common.h uses defined(__riscv) && __riscv_xlen == 64 which triggers automatically when compiled by a riscv64 compiler.
Cross-compile from x86_64:
make CC=riscv64-linux-gnu-gcc \
LD=riscv64-linux-gnu-ld \
AR=riscv64-linux-gnu-ar \
OBJCOPY=riscv64-linux-gnu-objcopy \
OBJDUMP=riscv64-linux-gnu-objdump
To force the default target arch when cross-compiling without a riscv64 compiler that sets __riscv:
make CFLAGS="-DKAFEL_DEFAULT_TARGET_ARCH=KAFEL_TARGET_ARCH_RISCV64"
Required tools:
flex- generateslexer.c/lexer.hfromlexer.l. Pure host tool; cross-compilation is unaffected.bison>= 3.7.5 (a 3.7.5 regression was fixed in the kafel build in 2021; 3.8+ works). Pure host tool.objcopy,objdump,ar- from binutils, used for static library symbol localization.- C compiler supporting
-std=gnu11(GCC 4.8+ or Clang 3.3+). [NEEDS VERIFICATION] - no minimum version is documented upstream.
Build outputs: libkafel.so (dynamic) and libkafel.a (static) in the repo root.
Build flags:
CFLAGS += -std=gnu11 -I${PROJECT_ROOT}include -Wall -Wextra -Werror
make DEBUG=1 adds -g -ggdb -gdwarf-4. make ASAN=1 enables AddressSanitizer. No feature-toggle flags exist.
Testing under QEMU: The test binary (test/tests) invokes real seccomp syscalls via prctl(PR_SET_SECCOMP, ...). Cross-built binaries require QEMU user-mode emulation:
qemu-riscv64 -L /usr/riscv64-linux-gnu ./test/tests
No Dockerfile, no .ci/ directory, and no .github/workflows/ directory exist in the repository. There are no documented known build failures on riscv64.
Kernel header requirement: AUDIT_ARCH_RISCV64 must be present in <linux/audit.h>. This requires Linux 4.19+ kernel headers. The syscall table compiles unconditionally; only runtime registration is guarded by #ifdef AUDIT_ARCH_RISCV64. On headers older than 4.19, the riscv64 table compiles but is never registered.
6. Feature Coverage and Gap Analysis vs arm64 and amd64
| Feature | amd64 | arm64 | riscv64 | Gap |
|---|---|---|---|---|
| Compile and link | Yes | Yes | Yes | None |
| Syscall table coverage | 382 entries | 321 entries | 320 entries | 1 entry vs arm64; reflects ABI, not a bug |
| Arch name lookup (“riscv64”, “rv64”) | N/A | N/A | Yes | None |
kafel_set_target_archs(KAFEL_TARGET_ARCH_RISCV64) |
Yes | Yes | Yes | None |
| BPF policy generation for riscv64 target | Yes | Yes | Yes | None |
ON riscv64 arch guard in policy language |
N/A | N/A | Yes (added 2025-11-22) [NEEDS VERIFICATION] | None |
| Test suite coverage (arch guard tests) | Yes | Yes | No | Tests in test/basic.c cover x86_64 and ARM arch guards; no riscv64-specific test cases |
| SIMD / hardware acceleration | None | None | None | Not applicable |
| Security hardening beyond libc | None | None | None | Not applicable |
Functional gaps: The test suite has no riscv64-specific test cases for arch guard policies. This is a test coverage gap, not a functional one - the policy compiler itself is architecture-agnostic in its BPF generation logic.
Performance gaps: Data not available: no benchmark suite exists for kafel on any architecture, and the project is a policy compiler whose runtime cost is the kernel BPF JIT, not kafel itself.
Floating-point semantics: Not applicable. kafel does not process floating-point data.
7. CI/CD Infrastructure
The repository has no CI configuration of any kind. There is no .github/workflows/ directory (GitHub API returns 404 for the path), no .gitlab-ci.yml, no Jenkinsfile, and no .cirrus.yml. This was confirmed by direct API queries.
CI comparison:
| Criterion | amd64 | arm64 | riscv64 |
|---|---|---|---|
| CI exists | No | No | No |
| Build tested in CI | No | No | No |
| Test suite run in CI | No | No | No |
| RISE runner available | No | No | No |
| Hardware tested | Unknown | Unknown | Unknown |
The absence of CI is a project-wide policy gap, not an riscv64-specific deficiency. No architecture has automated testing.
8. Distribution and Release Status
Official releases: Two GitHub releases exist - 20231004 (2023-10-04) and 20200831 (2020-08-31). Both carry zero binary assets. The GitHub Releases API confirms [0, 0] asset counts. There are no prebuilt binaries for any architecture on any platform.
Package availability:
| Channel | riscv64 Status | Notes |
|---|---|---|
| GitHub Releases | No binaries | Zero assets on all releases |
| PyPI | Not published (HTTP 404) | kafel is not a Python package |
| Debian | Not packaged (HTTP 404 on tracker) | No riscv64 build record |
| Ubuntu 24.04 Noble | Not packaged | Search returns no results |
| Arch Linux RISC-V | Not present | archriscv.felixc.at returns no results |
| RISE wheel builder | Not listed | kafel is not in RISE’s 80+ package index |
What a user must do to get a working riscv64 binary:
- Clone the repository:
git clone https://github.com/google/kafel.git - Install build dependencies:
flex,bison, a riscv64 C compiler - Run
makeon a riscv64 host or cross-compile with explicit toolchain overrides - Link
libkafel.soorlibkafel.ainto the consumer application
This is the only path for all architectures, not just riscv64.
9. Dependencies
Kafel is a pure C library with no third-party runtime dependencies. Its dependency surface is minimal.
Dependency summary:
| Dependency | Role | riscv64 Build | riscv64 Test | riscv64 Release | Notes |
|---|---|---|---|---|---|
| flex | Build-time: generates lexer.c/lexer.h from lexer.l |
Yes | N/A (host tool) | Packaged in Debian/Ubuntu/Fedora riscv64 | Pure host tool; cross-compilation unaffected |
| bison | Build-time: generates parser.c/parser.h from parser.y |
Yes | N/A (host tool) | Packaged in Debian/Ubuntu/Fedora riscv64 | Pure host tool; bison >=3.7.5 required |
Linux kernel headers (linux/audit.h, linux/seccomp.h, linux/filter.h) |
Compile-time: provides AUDIT_ARCH_RISCV64, struct sock_filter, SECCOMP_RET_* constants |
Yes (Linux 4.19+ required for AUDIT_ARCH_RISCV64) |
N/A (headers only) | Included in linux-headers packages for riscv64 | #ifdef guard means graceful degradation on old headers |
libc / POSIX (sys/queue.h, stdlib.h, string.h) |
Runtime: TAILQ/SLIST macros, memory allocation, string ops | Yes (glibc, musl) | Standard | Standard | No riscv64-specific issues |
There are no JIT backends, SIMD libraries, crypto dependencies, numerics libraries, or compression libraries in kafel’s dependency tree. Recursive analysis is not warranted.
Note on libseccomp: libseccomp is a separate library in the same problem domain, not a kafel dependency. It is often co-deployed by consumers. libseccomp has had full riscv64 support since v2.5.0 (2020-07-20) and v2.6.1 was released 2026-07-01 with riscv64 included. See project-reports/libseccomp.md for its full status.
11. Known Bugs and Active Issues
Closed riscv64-specific issues/PRs:
| ID | Title | Status | Severity | Notes |
|---|---|---|---|---|
| PR #31 | add riscv64 platform | Merged 2021-10-11 | N/A | Initial port |
| PR #32 | Fix riscv64 judgment | Merged 2021-10-27 | Correctness | __riscv matched any RISC-V variant; fixed to __riscv_xlen == 64 |
| PR #33 | Modify riscv_len to riscv_xlen | Merged 2021-10-27 | Minor | Naming correction |
Open issues (not riscv64-specific):
| ID | Title | Status | Severity | riscv64 Impact |
|---|---|---|---|---|
| #19 | __X32_SYSCALL_BIT not checked | Open since 2019 | Low | None - x32 ABI gap only |
| #20 | Reduce libkafel.so size | Open since 2019 | Low | None - unrelated to correctness |
| #41 | More open-source examples in Kafei | Open 2025-10-08 | Low | None - documentation request |
| #43 | Release a new version | Open 2026-03-05 | Low | None - release logistics |
Closed correctness bug of note:
Issue #39 (closed 2025-09-24): “Assertion failure in kafel_set_target_archs caused by incorrect KAFEL_TARGET_ARCHS_ALL mask.” KAFEL_TARGET_ARCHS_ALL was defined as (1<<8)-1 instead of (1<<9)-1, causing an assertion failure when KAFEL_TARGET_ARCH_M68K (value 1<<8 = 256) was passed. Found via automated fuzzing. Fixed by PR #40 same day (2025-09-24). This is not riscv64-specific, but the same class of off-by-one in the arch bitmask was in principle a risk for any architecture near a boundary. The fix is confirmed merged. KAFEL_TARGET_ARCH_RISCV64 = 1 << 7 is within the corrected mask.
Zero open riscv64-specific issues or bugs exist as of the research date.
12. Objections and Upstream Blockers
Technical blockers: None. The riscv64 port is complete, fully merged, and at parity with arm64 by every available metric.
Organizational blockers: None. The project is informally maintained with an open acceptance policy for architecture ports. The riscv64 port was merged same-day from an external contributor.
Stated objections: None found in issue tracker or PR comments.
Acceptance probability for future riscv64 patches: High. The precedent of accepting a 1,770-line riscv64 addition from an unaffiliated external contributor with no review comments establishes that the project will accept well-formed riscv64 work.
Ongoing maintenance risk: The project has no CI. Any regression in riscv64 support would go undetected unless a user reported it. The September 2025 “vibecoded” syscall update - AI-assisted generation of 390 lines of syscall entries with no CI validation - carries a non-zero correctness risk for syscall argument descriptors. However, incorrect argument descriptors produce incorrect BPF policies, not compiler crashes, so the failure mode is detectable by end-to-end testing of consumer policies.
13. Investment Analysis
RISE has no involvement with kafel. The riscv64 port is already complete. No functional enablement work is needed.
13.1 Functional Enablement
No work required. riscv64 support is complete: arch detection, full 320-entry syscall table, runtime registration, public API enum, all merged upstream.
The one functional gap is the test suite: test/basic.c has arch-guard tests for x86_64 and ARM but none for riscv64. Adding riscv64 arch-guard test cases would verify the policy compiler correctly generates riscv64-targeted BPF. Estimated effort: 1-2 person-days.
13.2 Performance Optimization
Data not available: no benchmark suite exists for kafel on any architecture. Performance optimization is not applicable - kafel is a policy compiler whose output is BPF bytecode; it has no SIMD, no JIT, and no hot path that benefits from RISC-V ISA extensions.
13.3 CI/CD Infrastructure
The project has no CI on any architecture. Adding riscv64 CI would require adding the project’s first-ever CI configuration. The simplest path is a GitHub Actions workflow using QEMU user-mode emulation for riscv64, building and running test/tests. This is a low-complexity addition that would benefit all architectures simultaneously.
Estimated effort: 1-2 person-days.
13.4 Ecosystem Enablement
Kafel is a C library distributed source-only. It has no Python, npm, Maven, or OCI package ecosystem. No ecosystem enablement work applies.
13.5 Summary Table
| Area | Work Item | Effort (person-weeks) | Owner | Priority |
|---|---|---|---|---|
| Functional | Add riscv64 arch-guard test cases to test/basic.c |
0.25 | External contributor / community | Low |
| CI/CD | Add GitHub Actions workflow for build + test on riscv64 via QEMU | 0.25 | External contributor / community | Medium |
| Performance | No work applicable | - | - | - |
| Ecosystem | No work applicable | - | - | - |
Total investment required for production-ready riscv64 status: approximately 0.5 person-weeks, covering test coverage and CI only. The core port is complete and no investment is needed for functional correctness.
14. Updates
No updates yet - initial report dated 2026-06-17.
15. References
- kafel repository (google/kafel)
- PR #31: add riscv64 platform
- PR #32: Fix riscv64 judgment
- PR #33: Modify riscv_len to riscv_xlen
- commit 21b96af0: add riscv64 platform (merge)
- commit 862f8f33: Fix RISCV syscall table
- commit 362ac7b6: Fix riscv64 judgment (merge)
- commit fdc1d644: Modify riscv_len to riscv_xlen (merge)
- commit c13ce1fc: riscv64: vibecoded missing syscalls
- Issue #19: __X32_SYSCALL_BIT not checked
- Issue #20: Reduce libkafel.so size
- Issue #39: Assertion failure in kafel_set_target_archs (closed)
- Issue #41: More open-source examples in Kafei
- Issue #43: Release a new version
- kafel GitHub Releases
- RISE Project member list
- RISE wheel builder package index