Draft
Conversation
✅ Deploy Preview for aya-rs-docs ready!Built without sensitive environment variables
To edit notification comments on pull requests, go to your Netlify project configuration. |
1a4cbc1 to
51c4fa0
Compare
Add an integration test that verifies bpf_printk correctly passes various integer types (u8, u16, u32, u64, i32) to the kernel's bpf_trace_printk helper. The test: - Attaches a uprobe that triggers bpf_printk calls with known values - Reads from /sys/kernel/debug/tracing/trace to verify output - Checks that all values are printed correctly (not garbage) This test exposes a bug in the current PrintkArg implementation where using [u8; 8] instead of u64 causes incorrect values to be passed to the variadic bpf_trace_printk function due to C ABI differences.
Change PrintkArg from wrapping [u8; 8] to wrapping u64 directly. The C ABI for variadic functions handles arrays differently than scalar types. When PrintkArg([u8; 8]) is passed to the variadic bpf_trace_printk helper, the array may be passed incorrectly (e.g., as a pointer or with wrong register usage), resulting in garbage values being printed. Using u64 directly ensures the value is passed by value in a register, matching what bpf_trace_printk expects for its %d, %u, %x, %lx format specifiers. This was discovered when real-world HID-BPF programs printed values like 846018776 instead of 0, or 937211784 instead of the expected small integers.
Add support for parsing `struct_ops/` and `struct_ops.s/` ELF section names as program sections. This enables loading BPF struct_ops programs such as those used by HID-BPF and sched_ext. The `StructOps` variant includes a `sleepable` field to distinguish between regular and sleepable struct_ops programs (the latter use the `struct_ops.s/` section prefix). Refs: aya-rs#967
Add the `StructOps` program type for loading BPF struct_ops programs. Struct_ops programs implement kernel interfaces like `hid_bpf_ops` for HID device handling or `sched_ext_ops` for custom schedulers. The `load()` method takes the struct type name (e.g., "hid_bpf_ops") and BTF information to resolve the struct type ID needed by the kernel. Refs: aya-rs#967
Add `StructOpsContext` for struct_ops programs and the `#[struct_ops]`
attribute macro for marking functions as struct_ops callbacks.
The macro supports:
- `name` parameter to override the callback name (defaults to function name)
- `sleepable` flag for sleepable programs
Example usage:
```rust
#[struct_ops]
fn my_callback(ctx: StructOpsContext) -> i32 {
0
}
```
Refs: aya-rs#967
Parse struct_ops maps from ELF with all necessary metadata: - btf_vmlinux_value_type_id for kernel type resolution - Kernel wrapper struct size for map creation - data_offset for program data placement - Member name extraction from section name - expected_attach_type set to member index - func_info population from relocations This enables the loader to properly create struct_ops maps that match the kernel's expectations for the BPF struct_ops subsystem. struct_ops: set expected_attach_type to member index For struct_ops programs, expected_attach_type must be the member index in the struct (e.g., 4 for hid_rdesc_fixup), not BPF_STRUCT_OPS (44). The kernel uses this to know which callback slot the program implements. - Add Btf::struct_member_index() to look up member index by name - Update StructOps::load() to take member_name parameter and look up index - Update Ebpf::load_struct_ops() to pass prog_name as member_name struct_ops: populate func_info from relocations and add load_struct_ops - Parse relocations in struct_ops section to find program function pointers and their offsets in the struct - Add Ebpf::load_struct_ops() method that: 1. Loads struct_ops programs with their struct name and BTF 2. Fills program FDs into struct_ops map data at correct offsets - This is required because libbpf skeleton fills prog FDs before calling bpf_map_update_elem for struct_ops registration
Add test eBPF program and integration tests for struct_ops program type: - struct_ops_test.rs: minimal eBPF callback program - tests/struct_ops.rs: tests for parsing and program type verification Note: Running these tests requires bpf-linker to be installed.
Add support for BPF_PROG_TYPE_SYSCALL programs which can be invoked directly via the bpf() syscall. This is used for HID-BPF probe functions that determine whether to attach to a HID device. - Add ProgramSection::Syscall variant in aya-obj/obj.rs - Add "syscall" section name parsing - Add syscall.rs with Syscall program type - Add Program::Syscall variant and all required method implementations - Handle ProgramSection::Syscall in bpf.rs program creation
Extracts the link type definitions and conversions from define_link_wrapper! into a separate define_link_types! macro. This allows programs like StructOps (where the link is created via StructOpsMap::attach() rather than a program method) to reuse the same link type infrastructure. define_link_wrapper! now calls define_link_types! internally and only adds the detach() and take_link() methods that require a program type parameter.
Adds comprehensive unit tests for StructOpsMap covering: - Construction and type validation (try_from_ok, try_from_wrong_map) - Accessor methods (func_info, type_name, is_link) - Field setting with bounds checking and data_offset handling - Registration and attachment with mocked syscalls Also extracts helper functions to improve testability: - write_bytes_at_offset() in maps/struct_ops.rs for DRY field setting - write_struct_ops_fd() in bpf.rs for FD writing with bounds checking These tests address the review feedback about zero test coverage for struct_ops functionality.
Add comprehensive safe Rust abstractions for HID-BPF programming: - HidBpfData<'a>: Bounds-checked buffer access with get(), set(), copy_from_slice(), and starts_with() methods. Tied to context lifetime. - AllocatedContext: RAII guard for hid_bpf_allocate_context that auto- releases on drop, preventing resource leaks on early returns. - HidBpfContext: Enhanced with safe data() method returning HidBpfData instead of raw pointers. - kfunc module: Low-level kernel function bindings using inline assembly for reliable kfunc invocation. Includes hid_bpf_get_data, hid_bpf_allocate_context, hid_bpf_release_context, hid_bpf_hw_request. - HidReportType/HidClassRequest enums: Type-safe report and request types. This enables writing HID-BPF programs with zero unsafe blocks in callback bodies - all memory safety is enforced at compile time through the wrapper types.
Add a test program demonstrating the HID-BPF macros for device event, report descriptor fixup, and hardware request handlers.
The previous implementation used `std::mem::transmute` to store a struct member index (u32) in the `expected_attach_type` field, which is typed as `bpf_attach_type`. This created an invalid enum value, which is undefined behavior in Rust. This commit introduces an `ExpectedAttachType` enum that explicitly distinguishes between: - `AttachType(bpf_attach_type)` for normal program types - `StructOpsMemberIndex(u32)` for struct_ops member indices The enum provides type safety within Rust while the `as_raw()` method extracts the plain u32 value for kernel syscalls. The kernel never sees the enum - only the extracted integer value.
Replace the hardcoded 0x2000 value with the BPF_F_LINK constant from the generated kernel bindings for better maintainability and clarity.
Previously, when a kfunc (external kernel function) could not be resolved in the kernel BTF, the code would silently log a debug message and leave the instruction unresolved. This would later cause a confusing kernel verifier error at program load time. Now the code returns a clear `RelocationError::UnknownKfunc` error that identifies the problematic kfunc by name, making it easier to diagnose issues like missing kernel functions or incorrect BTF.
Expand the struct_ops integration tests to be more meaningful: - Add multiple struct_ops callbacks to test multi-program parsing - Add test for renamed callbacks using the name attribute - Add test for sleepable struct_ops sections - Verify program type detection works for all variants - Verify member_name() returns the section suffix correctly - Add BTF availability tests to verify kernel support - Add BTF member lookup tests for struct_ops type resolution - Add error handling test for non-existent types These tests verify the struct_ops parsing, program extraction, and BTF integration work correctly, even without full kernel struct_ops support.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds support for HID-BPF programs, allowing BPF programs to intercept and modify HID device events.
HidBpfContextfor HID-BPF programshid_bpf_get_data,hid_bpf_hw_request, etc.)bpf_printkto pass args by value instead of by pointerDependencies
This PR depends on #1444 (struct_ops support) and should be merged after it.
Test plan
test/integration-test/src/tests/hid_bpf.rs)This change is