mirror of
https://github.com/domcyrus/rustnet.git
synced 2026-05-06 12:00:13 -05:00
Bundle vmlinux.h files to eliminate network dependency during builds (#41)
* feat: bundle vmlinux.h files to eliminate network dependency during builds - Add bundled vmlinux.h for x86, aarch64, and arm (~3MB total) - Remove network download code from build.rs - Remove ureq dependency and transitive deps - Update Dockerfile to copy bundled headers - Remove obsolete vmlinux_min.h - Update documentation to reflect bundled approach Fixes #38
This commit is contained in:
Generated
+390
-665
File diff suppressed because it is too large
Load Diff
@@ -75,7 +75,6 @@ windows = { version = "0.59", features = [
|
||||
|
||||
[target.'cfg(target_os = "linux")'.build-dependencies]
|
||||
libbpf-cargo = "0.25"
|
||||
ureq = { version = "2.10", default-features = false, features = ["tls"] }
|
||||
|
||||
[features]
|
||||
default = []
|
||||
|
||||
@@ -24,6 +24,9 @@ COPY Cargo.toml Cargo.lock ./
|
||||
# Copy build script for eBPF compilation
|
||||
COPY build.rs ./
|
||||
|
||||
# Copy bundled eBPF vmlinux headers (required for eBPF compilation)
|
||||
COPY resources/ebpf/vmlinux ./resources/ebpf/vmlinux
|
||||
|
||||
# Copy source code
|
||||
COPY src ./src
|
||||
COPY assets/services ./assets/services
|
||||
|
||||
+101
-200
@@ -4,29 +4,94 @@ This document explains how to work with eBPF kernel headers in this project.
|
||||
|
||||
## Current Setup
|
||||
|
||||
We use a **minimal vmlinux header** (`vmlinux_min.h`) instead of the full kernel headers. This approach has trade-offs that should be considered:
|
||||
The project bundles **architecture-specific vmlinux.h files** from the [libbpf/vmlinux.h](https://github.com/libbpf/vmlinux.h) repository. This eliminates network dependencies during builds and ensures reproducible builds.
|
||||
|
||||
**Benefits of minimal vmlinux_min.h:**
|
||||
### Bundled vmlinux.h Files
|
||||
|
||||
- **Small size**: 5.5KB (203 lines) vs 3.4MB (100K+ lines) full vmlinux.h
|
||||
- **Git-friendly**: Small file size, manageable diffs, easier to review
|
||||
- **Portable**: Works across kernel versions with CO-RE/BTF
|
||||
- **Clear dependencies**: Shows exactly which kernel structures we depend on
|
||||
Pre-downloaded vmlinux.h files (based on Linux kernel 6.14) are included in the repository at:
|
||||
- `resources/ebpf/vmlinux/x86/vmlinux.h` (for x86_64, ~1.1MB)
|
||||
- `resources/ebpf/vmlinux/aarch64/vmlinux.h` (for aarch64, ~1.0MB)
|
||||
- `resources/ebpf/vmlinux/arm/vmlinux.h` (for armv7, ~981KB)
|
||||
|
||||
**Drawbacks of minimal vmlinux_min.h:**
|
||||
These files are automatically used during the build process based on the target architecture. **No network access is required** during compilation.
|
||||
|
||||
- **Manual maintenance**: Need to update when adding new eBPF features that access different kernel structures
|
||||
- **Potential for missing definitions**: Easy to forget required types when extending functionality
|
||||
- **Development overhead**: Requires understanding of kernel internals to extract correct definitions
|
||||
**Benefits:**
|
||||
- **Zero network dependency**: Works in restricted build environments (COPR, Fedora build systems, etc.)
|
||||
- **Reproducible builds**: Same headers every time, no external dependencies
|
||||
- **Complete kernel definitions**: All kernel structures available, no missing types
|
||||
- **No manual maintenance**: Auto-generated from kernel BTF
|
||||
- **Cross-kernel compatibility**: CO-RE/BTF ensures portability across kernel versions
|
||||
|
||||
**Alternative approach (full vmlinux.h):**
|
||||
**Trade-offs:**
|
||||
- Repository size: ~3MB total for all architectures (acceptable for modern git)
|
||||
- Not immediately clear which kernel structures are actually used by the code
|
||||
|
||||
- **Pros**: Complete kernel definitions, auto-generated, no manual maintenance, never missing types
|
||||
- **Cons**: Very large file (3.4MB), but can be gitignored and generated during build process
|
||||
## Updating Bundled vmlinux.h Files
|
||||
|
||||
## How to Generate Full vmlinux.h (if needed)
|
||||
The bundled vmlinux.h files are based on kernel 6.14 from the libbpf repository. To update them to a newer kernel version:
|
||||
|
||||
If you need to generate a complete vmlinux.h file for your kernel:
|
||||
```bash
|
||||
# Update all architectures at once
|
||||
for arch in x86 aarch64 arm; do
|
||||
# Get the symlink target (e.g., vmlinux_6.14.h)
|
||||
target=$(curl -sL "https://raw.githubusercontent.com/libbpf/vmlinux.h/main/include/${arch}/vmlinux.h")
|
||||
|
||||
# Download the actual file
|
||||
curl -sL "https://raw.githubusercontent.com/libbpf/vmlinux.h/main/include/${arch}/${target}" \
|
||||
-o "resources/ebpf/vmlinux/${arch}/vmlinux.h"
|
||||
|
||||
echo "Updated ${arch} to ${target}"
|
||||
done
|
||||
```
|
||||
|
||||
Or update a single architecture:
|
||||
|
||||
```bash
|
||||
# Example: Update x86 only
|
||||
arch="x86"
|
||||
target=$(curl -sL "https://raw.githubusercontent.com/libbpf/vmlinux.h/main/include/${arch}/vmlinux.h")
|
||||
curl -sL "https://raw.githubusercontent.com/libbpf/vmlinux.h/main/include/${arch}/${target}" \
|
||||
-o "resources/ebpf/vmlinux/${arch}/vmlinux.h"
|
||||
```
|
||||
|
||||
After updating, commit the changes to the repository.
|
||||
|
||||
## Building with eBPF Support
|
||||
|
||||
To build rustnet with eBPF support on Linux:
|
||||
|
||||
```bash
|
||||
# Install build dependencies
|
||||
sudo apt-get install libelf-dev clang llvm # Debian/Ubuntu
|
||||
sudo yum install elfutils-libelf-devel clang llvm # RedHat/CentOS/Fedora
|
||||
|
||||
# Build with eBPF feature
|
||||
cargo build --release --features ebpf
|
||||
|
||||
# The bundled vmlinux.h files will be used automatically
|
||||
# No network access required!
|
||||
```
|
||||
|
||||
## Testing eBPF Functionality
|
||||
|
||||
After building with eBPF support, test that it works correctly:
|
||||
|
||||
```bash
|
||||
# Option 1: Run with sudo (always works)
|
||||
sudo cargo run --features ebpf
|
||||
|
||||
# Option 2: Set capabilities (Linux only, see README.md Permissions section)
|
||||
sudo setcap 'cap_net_raw,cap_net_admin,cap_sys_admin,cap_bpf,cap_perfmon+eip' ./target/release/rustnet
|
||||
./target/release/rustnet
|
||||
|
||||
# Check the TUI Statistics panel to verify it shows "Process Detection: eBPF + procfs"
|
||||
```
|
||||
|
||||
**Note**: eBPF kprobe programs require specific Linux capabilities. See the main [README.md Permissions section](README.md#permissions) for detailed capability requirements. The required capabilities may vary by kernel version.
|
||||
|
||||
## Generating vmlinux.h from Your Local Kernel (Optional)
|
||||
|
||||
If you need to generate a vmlinux.h file for your specific kernel (e.g., for debugging or custom kernel builds):
|
||||
|
||||
```bash
|
||||
# Method 1: Using bpftool (requires root/CAP_BPF)
|
||||
@@ -43,198 +108,34 @@ make scripts_gdb
|
||||
bpftool btf dump file vmlinux format c > vmlinux.h
|
||||
```
|
||||
|
||||
## How to Create Minimal Headers from Full vmlinux.h
|
||||
|
||||
### 1. Identify Required Structures
|
||||
|
||||
First, analyze your eBPF program to find which kernel structures you access:
|
||||
|
||||
```bash
|
||||
# Find all struct references in your eBPF code
|
||||
grep -E "struct [a-zA-Z_]+" socket_tracker.bpf.c
|
||||
|
||||
# Find BPF_CORE_READ usage to see field accesses
|
||||
grep -E "BPF_CORE_READ.*\\..*" socket_tracker.bpf.c
|
||||
|
||||
# Common structures for socket tracking:
|
||||
# - struct sock (contains __sk_common)
|
||||
# - struct sock_common (network fields)
|
||||
# - struct msghdr (for sendmsg calls)
|
||||
# - struct sockaddr_in (IPv4 addresses)
|
||||
# - struct pt_regs (kprobe context)
|
||||
```
|
||||
|
||||
### 2. Extract Definitions from Full vmlinux.h
|
||||
|
||||
Use these commands to extract specific structures:
|
||||
|
||||
```bash
|
||||
# Extract a specific struct (e.g., sock_common)
|
||||
awk '/^struct sock_common {/,/^}/' vmlinux.h
|
||||
|
||||
# Extract type definitions
|
||||
grep "typedef.*__u[0-9]*\|typedef.*__be[0-9]*" vmlinux.h
|
||||
|
||||
# Extract multiple related structures
|
||||
grep -A 50 "struct sock_common {" vmlinux.h
|
||||
grep -A 20 "struct sock {" vmlinux.h
|
||||
grep -A 10 "struct msghdr {" vmlinux.h
|
||||
```
|
||||
|
||||
### 3. Create Minimal Header
|
||||
|
||||
Create a new header file with:
|
||||
|
||||
1. **Header guards and CO-RE pragma**:
|
||||
```c
|
||||
#ifndef __VMLINUX_MIN_H__
|
||||
#define __VMLINUX_MIN_H__
|
||||
|
||||
#ifndef BPF_NO_PRESERVE_ACCESS_INDEX
|
||||
#pragma clang attribute push (__attribute__((preserve_access_index)), apply_to = record)
|
||||
#endif
|
||||
```
|
||||
|
||||
2. **Basic types** (only what you need):
|
||||
```c
|
||||
typedef unsigned char __u8;
|
||||
typedef unsigned int __u32;
|
||||
typedef __u32 __be32;
|
||||
// etc.
|
||||
```
|
||||
|
||||
3. **Required structures** with **only the fields you access**:
|
||||
```c
|
||||
struct sock_common {
|
||||
// Only include fields accessed by BPF_CORE_READ
|
||||
__be32 skc_daddr;
|
||||
__be32 skc_rcv_saddr;
|
||||
__be16 skc_dport;
|
||||
__u16 skc_num;
|
||||
// ... other fields you actually use
|
||||
};
|
||||
```
|
||||
|
||||
4. **Footer**:
|
||||
```c
|
||||
#ifndef BPF_NO_PRESERVE_ACCESS_INDEX
|
||||
#pragma clang attribute pop
|
||||
#endif
|
||||
#endif
|
||||
```
|
||||
|
||||
### 4. Automated Extraction Script
|
||||
|
||||
For complex projects, you can create a script to automate extraction:
|
||||
|
||||
```bash
|
||||
#!/bin/bash
|
||||
# extract_minimal_vmlinux.sh
|
||||
|
||||
FULL_VMLINUX="vmlinux.h"
|
||||
OUTPUT="vmlinux_min.h"
|
||||
BPF_SOURCE="socket_tracker.bpf.c"
|
||||
|
||||
# Find structs used in BPF program
|
||||
STRUCTS=$(grep -oE "struct [a-zA-Z_]+" "$BPF_SOURCE" | sort -u | cut -d' ' -f2)
|
||||
|
||||
echo "Extracting structures: $STRUCTS"
|
||||
|
||||
# Start minimal header
|
||||
cat > "$OUTPUT" << 'EOF'
|
||||
#ifndef __VMLINUX_MIN_H__
|
||||
#define __VMLINUX_MIN_H__
|
||||
|
||||
#ifndef BPF_NO_PRESERVE_ACCESS_INDEX
|
||||
#pragma clang attribute push (__attribute__((preserve_access_index)), apply_to = record)
|
||||
#endif
|
||||
|
||||
/* Basic types */
|
||||
EOF
|
||||
|
||||
# Extract basic types
|
||||
grep "typedef.*__u[0-9]*\|typedef.*__be[0-9]*\|typedef.*__kernel" "$FULL_VMLINUX" | head -20 >> "$OUTPUT"
|
||||
|
||||
echo "" >> "$OUTPUT"
|
||||
echo "/* Network structures */" >> "$OUTPUT"
|
||||
|
||||
# Extract each required struct
|
||||
for struct in $STRUCTS; do
|
||||
echo "Extracting struct $struct..."
|
||||
awk "/^struct $struct \{/,/^}/" "$FULL_VMLINUX" >> "$OUTPUT"
|
||||
echo "" >> "$OUTPUT"
|
||||
done
|
||||
|
||||
# Close header
|
||||
cat >> "$OUTPUT" << 'EOF'
|
||||
|
||||
#ifndef BPF_NO_PRESERVE_ACCESS_INDEX
|
||||
#pragma clang attribute pop
|
||||
#endif
|
||||
|
||||
#endif /* __VMLINUX_MIN_H__ */
|
||||
EOF
|
||||
|
||||
echo "Minimal vmlinux header created: $OUTPUT"
|
||||
```
|
||||
|
||||
## Testing Your Minimal Header
|
||||
|
||||
After creating your minimal header:
|
||||
|
||||
```bash
|
||||
# Test compilation
|
||||
cargo build --features ebpf
|
||||
|
||||
# If compilation fails, check for missing definitions
|
||||
# and add them to your minimal header
|
||||
|
||||
# Verify eBPF program loads
|
||||
# Option 1: Run with sudo (always works)
|
||||
sudo cargo run --features ebpf
|
||||
|
||||
# Option 2: Set capabilities (Linux only, see README.md Permissions section)
|
||||
sudo setcap 'cap_net_raw,cap_net_admin,cap_sys_admin,cap_bpf,cap_perfmon+eip' ./target/debug/rustnet
|
||||
cargo run --features ebpf
|
||||
|
||||
# Check the TUI Statistics panel to verify it shows "Process Detection: eBPF + procfs"
|
||||
```
|
||||
|
||||
**Note**: eBPF kprobe programs require specific Linux capabilities. See the main [README.md Permissions section](README.md#permissions) for detailed capability requirements. The required capabilities may vary by kernel version.
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Start minimal**: Only include structures and fields you actually access
|
||||
2. **Use CO-RE**: Always include the preserve_access_index pragma for portability
|
||||
3. **Document sources**: Note which kernel version/source your definitions came from
|
||||
4. **Test across kernels**: Verify your program works on different kernel versions
|
||||
5. **Keep synchronized**: Update minimal headers when your eBPF program changes
|
||||
This is typically not needed since the bundled headers work across kernel versions thanks to CO-RE/BTF.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Compilation Errors
|
||||
|
||||
- **Missing struct definition**: Add the struct to your minimal header
|
||||
- **Missing field**: Include the specific field in your struct definition
|
||||
- **Type errors**: Ensure all referenced types are defined
|
||||
**"Bundled vmlinux.h not found"**:
|
||||
- Ensure the `resources/ebpf/vmlinux/` directory exists
|
||||
- Verify you've cloned the full repository (not a partial checkout)
|
||||
- Check that the vmlinux.h file exists for your target architecture
|
||||
|
||||
**Missing build dependencies**:
|
||||
- Install clang, llvm, and libelf-dev
|
||||
- Ensure rustfmt is installed: `rustup component add rustfmt`
|
||||
|
||||
### Runtime Errors
|
||||
|
||||
- **BTF verification failed**: Check that field names match kernel structures
|
||||
- **Access violations**: Ensure you're accessing fields that exist in target kernel
|
||||
**"BTF verification failed"**:
|
||||
- Your kernel may not have BTF support enabled
|
||||
- Linux kernel 4.19+ with BTF support is recommended
|
||||
- Check if BTF is available: `ls /sys/kernel/btf/vmlinux`
|
||||
|
||||
### Field Access Issues
|
||||
**"Permission denied" when loading eBPF**:
|
||||
- See the [README.md Permissions section](README.md#permissions) for capability setup
|
||||
- Required capabilities: `CAP_NET_RAW`, `CAP_NET_ADMIN`, `CAP_BPF`, `CAP_PERFMON`
|
||||
- Some kernels may also require `CAP_SYS_ADMIN`
|
||||
|
||||
- **Wrong offset**: Make sure struct layout matches target kernel
|
||||
- **Missing CO-RE relocations**: Verify preserve_access_index pragma is present
|
||||
|
||||
## Why Not Use Full vmlinux.h?
|
||||
|
||||
While using the full vmlinux.h works, it has downsides:
|
||||
|
||||
- **Huge file size** (3+ MB): Slows down compilation and git operations
|
||||
- **Unclear dependencies**: Hard to see what your program actually needs
|
||||
- **Kernel-specific**: Generated for one specific kernel version
|
||||
- **Review complexity**: Impossible to review 100K+ lines in PRs
|
||||
|
||||
The minimal approach gives you the benefits of vmlinux.h (CO-RE support, exact field layouts) without the downsides.
|
||||
**eBPF fails to load, falls back to procfs**:
|
||||
- This is expected behavior when eBPF can't load
|
||||
- Check the TUI Statistics panel to see which detection method is active
|
||||
- Common reasons: insufficient capabilities, incompatible kernel, BTF not available
|
||||
|
||||
@@ -24,13 +24,11 @@ The experimental eBPF support provides efficient process identification but has
|
||||
### Current Limitations
|
||||
- **Process Names Limited to 16 Characters**: Uses kernel `comm` field, causing truncation (e.g., "Firefox" → "Socket Thread")
|
||||
- **Thread Names vs Process Names**: Shows thread command names instead of full executable names
|
||||
- **Minimal vmlinux.h Maintenance**: Current approach requires manual updates when adding new kernel structure access
|
||||
|
||||
### Planned Improvements
|
||||
- **Hybrid eBPF + Procfs Approach**: Use eBPF for connection tracking, selectively lookup full process names via procfs for better accuracy
|
||||
- **Full Executable Path Resolution**: Investigate accessing full process executable path from eBPF programs
|
||||
- **Better Process-Thread Mapping**: Improve mapping from thread IDs to parent process information
|
||||
- **vmlinux.h Strategy**: Consider switching to full auto-generated vmlinux.h for easier maintenance vs current minimal approach
|
||||
- **Enhanced BTF Support**: Better compatibility across different kernel versions and distributions
|
||||
- **Performance Optimizations**: Reduce eBPF map lookups and improve connection-to-process matching efficiency
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ fn main() -> Result<()> {
|
||||
|
||||
println!("cargo:rerun-if-changed=src/network/platform/linux_ebpf/programs/");
|
||||
println!("cargo:rerun-if-changed=src/cli.rs");
|
||||
println!("cargo:rerun-if-changed=resources/ebpf/vmlinux/");
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -149,70 +150,22 @@ fn download_windows_npcap_sdk() -> Result<()> {
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "linux", feature = "ebpf"))]
|
||||
fn download_vmlinux_header(arch: &str) -> Result<PathBuf> {
|
||||
use std::fs;
|
||||
use std::io::{Read, Write};
|
||||
fn get_vmlinux_header(arch: &str) -> Result<PathBuf> {
|
||||
// Use bundled vmlinux.h from resources directory
|
||||
let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR")?);
|
||||
let bundled_dir = manifest_dir.join("resources/ebpf/vmlinux").join(arch);
|
||||
let bundled_file = bundled_dir.join("vmlinux.h");
|
||||
|
||||
// Cache directory in OUT_DIR
|
||||
let out_dir = PathBuf::from(env::var("OUT_DIR")?);
|
||||
let cache_dir = out_dir.join("vmlinux_headers").join(arch);
|
||||
let vmlinux_file = cache_dir.join("vmlinux.h");
|
||||
|
||||
// Return cached version if it exists
|
||||
if vmlinux_file.exists() {
|
||||
println!("cargo:warning=Using cached vmlinux.h for {}", arch);
|
||||
return Ok(cache_dir);
|
||||
if bundled_file.exists() {
|
||||
println!("cargo:warning=Using bundled vmlinux.h for {}", arch);
|
||||
Ok(bundled_dir)
|
||||
} else {
|
||||
Err(anyhow::anyhow!(
|
||||
"Bundled vmlinux.h not found for architecture '{}'. Expected at: {}",
|
||||
arch,
|
||||
bundled_file.display()
|
||||
))
|
||||
}
|
||||
|
||||
// Download from libbpf/vmlinux.h repository
|
||||
// Note: vmlinux.h is a symlink, so we first download it to get the target filename
|
||||
let symlink_url = format!(
|
||||
"https://raw.githubusercontent.com/libbpf/vmlinux.h/main/include/{}/vmlinux.h",
|
||||
arch
|
||||
);
|
||||
|
||||
println!("cargo:warning=Downloading vmlinux.h for {} from {}", arch, symlink_url);
|
||||
|
||||
// Create cache directory
|
||||
fs::create_dir_all(&cache_dir)?;
|
||||
|
||||
// Download the symlink to get the actual filename
|
||||
let response = ureq::get(&symlink_url)
|
||||
.call()
|
||||
.map_err(|e| anyhow::anyhow!("Failed to download vmlinux.h symlink: {}", e))?;
|
||||
|
||||
let mut symlink_content = String::new();
|
||||
response.into_reader()
|
||||
.read_to_string(&mut symlink_content)
|
||||
.map_err(|e| anyhow::anyhow!("Failed to read symlink: {}", e))?;
|
||||
|
||||
// The symlink content is just the target filename, e.g. "vmlinux_6.14.h"
|
||||
let target_filename = symlink_content.trim();
|
||||
|
||||
// Download the actual vmlinux header file
|
||||
let actual_url = format!(
|
||||
"https://raw.githubusercontent.com/libbpf/vmlinux.h/main/include/{}/{}",
|
||||
arch, target_filename
|
||||
);
|
||||
|
||||
println!("cargo:warning=Following symlink to {}", target_filename);
|
||||
|
||||
let response = ureq::get(&actual_url)
|
||||
.call()
|
||||
.map_err(|e| anyhow::anyhow!("Failed to download {}: {}", target_filename, e))?;
|
||||
|
||||
let mut content = Vec::new();
|
||||
response.into_reader()
|
||||
.read_to_end(&mut content)
|
||||
.map_err(|e| anyhow::anyhow!("Failed to read response: {}", e))?;
|
||||
|
||||
// Write to cache
|
||||
let mut file = fs::File::create(&vmlinux_file)?;
|
||||
file.write_all(&content)?;
|
||||
|
||||
println!("cargo:warning=Downloaded and cached vmlinux.h for {}", arch);
|
||||
|
||||
Ok(cache_dir)
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "linux", feature = "ebpf"))]
|
||||
@@ -240,9 +193,9 @@ fn compile_ebpf_programs() {
|
||||
_ => ("-D__TARGET_ARCH_x86", "x86"), // fallback
|
||||
};
|
||||
|
||||
// Download architecture-specific vmlinux.h if not cached
|
||||
let vmlinux_include_path = download_vmlinux_header(vmlinux_arch)
|
||||
.expect("Failed to download vmlinux.h");
|
||||
// Get bundled architecture-specific vmlinux.h
|
||||
let vmlinux_include_path = get_vmlinux_header(vmlinux_arch)
|
||||
.expect("Failed to locate bundled vmlinux.h");
|
||||
|
||||
SkeletonBuilder::new()
|
||||
.source(src)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,243 +0,0 @@
|
||||
#ifndef __VMLINUX_MIN_H__
|
||||
#define __VMLINUX_MIN_H__
|
||||
|
||||
/*
|
||||
* Minimal vmlinux.h with only the kernel structures needed for our eBPF socket tracker.
|
||||
* This replaces the full vmlinux.h (3.4MB) with just the essential definitions.
|
||||
*
|
||||
* Generated for Linux kernel structures used in socket tracking.
|
||||
* See EBPF_BUILD.md for instructions on how to regenerate or customize.
|
||||
*/
|
||||
|
||||
/* Define this to trigger kernel field names in bpf_tracing.h */
|
||||
#define __VMLINUX_H__
|
||||
|
||||
#ifndef BPF_NO_PRESERVE_ACCESS_INDEX
|
||||
#pragma clang attribute push (__attribute__((preserve_access_index)), apply_to = record)
|
||||
#endif
|
||||
|
||||
/* Basic kernel types */
|
||||
typedef unsigned char __u8;
|
||||
typedef unsigned short __u16;
|
||||
typedef unsigned int __u32;
|
||||
typedef unsigned long long __u64;
|
||||
typedef signed char __s8;
|
||||
typedef signed short __s16;
|
||||
typedef signed int __s32;
|
||||
typedef signed long long __s64;
|
||||
typedef __u16 __be16;
|
||||
typedef __u32 __be32;
|
||||
typedef __u64 __be64;
|
||||
typedef __u32 __wsum;
|
||||
typedef __u16 __kernel_sa_family_t;
|
||||
typedef _Bool bool;
|
||||
|
||||
/* Additional type definitions needed for kernel structures */
|
||||
typedef __u64 __addrpair;
|
||||
typedef __u32 __portpair;
|
||||
typedef struct { __s64 counter; } atomic64_t;
|
||||
typedef struct { __s32 counter; } atomic_t;
|
||||
|
||||
/* BPF map types and flags */
|
||||
enum {
|
||||
BPF_MAP_TYPE_HASH = 1,
|
||||
};
|
||||
|
||||
enum {
|
||||
BPF_ANY = 0,
|
||||
};
|
||||
|
||||
/* Network address structures */
|
||||
struct in_addr {
|
||||
__be32 s_addr;
|
||||
};
|
||||
|
||||
struct in6_addr {
|
||||
union {
|
||||
__u8 u6_addr8[16];
|
||||
__be16 u6_addr16[8];
|
||||
__be32 u6_addr32[4];
|
||||
} in6_u;
|
||||
};
|
||||
|
||||
/* Socket address structures */
|
||||
struct sockaddr_in {
|
||||
__kernel_sa_family_t sin_family;
|
||||
__be16 sin_port;
|
||||
struct in_addr sin_addr;
|
||||
unsigned char __pad[8];
|
||||
};
|
||||
|
||||
/* Forward declarations for complex types we don't need to fully define */
|
||||
struct proto;
|
||||
struct sk_buff_head;
|
||||
|
||||
/* Simple structures we need defined */
|
||||
struct hlist_node {
|
||||
struct hlist_node *next, **pprev;
|
||||
};
|
||||
|
||||
struct iov_iter {
|
||||
/* We don't access fields, just need size/layout for msghdr */
|
||||
void *__opaque[8]; /* Approximate size, CO-RE will handle differences */
|
||||
};
|
||||
|
||||
/* Minimal possible_net_t - we don't access its internals */
|
||||
typedef struct {
|
||||
void *net; /* We don't dereference this, just need the field present */
|
||||
} possible_net_t;
|
||||
|
||||
/* Socket common structure - core networking fields */
|
||||
struct sock_common {
|
||||
/* Address pair for IPv4 */
|
||||
union {
|
||||
__addrpair skc_addrpair; /* We don't use this directly */
|
||||
struct {
|
||||
__be32 skc_daddr; /* destination IPv4 address */
|
||||
__be32 skc_rcv_saddr; /* source IPv4 address */
|
||||
};
|
||||
};
|
||||
|
||||
/* Hash - we don't use this but it's part of the layout */
|
||||
union {
|
||||
unsigned int skc_hash;
|
||||
__u16 skc_u16hashes[2];
|
||||
};
|
||||
|
||||
/* Port pair */
|
||||
union {
|
||||
__portpair skc_portpair; /* We don't use this directly */
|
||||
struct {
|
||||
__be16 skc_dport; /* destination port */
|
||||
__u16 skc_num; /* source port */
|
||||
};
|
||||
};
|
||||
|
||||
/* Basic socket properties */
|
||||
short unsigned int skc_family;
|
||||
volatile unsigned char skc_state;
|
||||
unsigned char skc_reuse: 4;
|
||||
unsigned char skc_reuseport: 1;
|
||||
unsigned char skc_ipv6only: 1;
|
||||
unsigned char skc_net_refcnt: 1;
|
||||
int skc_bound_dev_if;
|
||||
|
||||
/* Hash table linkage - we don't use these but they're part of layout */
|
||||
union {
|
||||
struct hlist_node skc_bind_node;
|
||||
struct hlist_node skc_portaddr_node;
|
||||
};
|
||||
|
||||
/* Protocol and network namespace */
|
||||
struct proto *skc_prot;
|
||||
possible_net_t skc_net;
|
||||
|
||||
/* IPv6 addresses - these come after the above fields */
|
||||
struct in6_addr skc_v6_daddr;
|
||||
struct in6_addr skc_v6_rcv_saddr;
|
||||
|
||||
/* Socket cookie for identification */
|
||||
atomic64_t skc_cookie;
|
||||
|
||||
/* Additional fields exist but we don't need them for CO-RE access */
|
||||
};
|
||||
|
||||
/* Main socket structure - we only need the common part */
|
||||
struct sock {
|
||||
struct sock_common __sk_common;
|
||||
/*
|
||||
* Many more fields exist here, but we only access __sk_common
|
||||
* CO-RE will handle the field relocations regardless of what
|
||||
* other fields are present in different kernel versions
|
||||
*/
|
||||
};
|
||||
|
||||
/* Message header for sendmsg syscalls */
|
||||
struct msghdr {
|
||||
void *msg_name; /* Socket name (sockaddr_in* for UDP) */
|
||||
int msg_namelen; /* Length of socket name */
|
||||
int msg_inq; /* Bytes in receive queue */
|
||||
struct iov_iter msg_iter; /* Data payload iterator */
|
||||
|
||||
/* Control messages - we don't use these but they're part of layout */
|
||||
union {
|
||||
void *msg_control;
|
||||
void *msg_control_user;
|
||||
};
|
||||
bool msg_control_is_user: 1;
|
||||
bool msg_get_inq: 1;
|
||||
/* Additional fields may exist but we only need msg_name */
|
||||
};
|
||||
|
||||
/* FRED (Flexible Return and Event Delivery) support structures */
|
||||
struct fred_cs {
|
||||
__u64 cs: 16;
|
||||
__u64 sl: 2;
|
||||
__u64 wfe: 1;
|
||||
};
|
||||
|
||||
struct fred_ss {
|
||||
__u64 ss: 16;
|
||||
__u64 sti: 1;
|
||||
__u64 swevent: 1;
|
||||
__u64 nmi: 1;
|
||||
int: 13;
|
||||
__u64 vector: 8;
|
||||
short: 8;
|
||||
__u64 type: 4;
|
||||
char: 4;
|
||||
__u64 enclave: 1;
|
||||
};
|
||||
|
||||
/*
|
||||
* Architecture-specific pt_regs for kprobe context
|
||||
* x86_64 specific - for PT_REGS_PARM1/PT_REGS_PARM2 macros
|
||||
* Field names must match kernel exactly for CO-RE relocations
|
||||
*/
|
||||
struct pt_regs {
|
||||
/*
|
||||
* C ABI says these regs are callee-preserved. They aren't saved on kernel entry
|
||||
* unless syscall needs a complete, fully filled "struct pt_regs".
|
||||
*/
|
||||
long unsigned int r15;
|
||||
long unsigned int r14;
|
||||
long unsigned int r13;
|
||||
long unsigned int r12;
|
||||
long unsigned int bp; /* Must match kernel BTF field names */
|
||||
long unsigned int bx; /* Must match kernel BTF field names */
|
||||
/* These regs are callee-clobbered. Always saved on kernel entry. */
|
||||
long unsigned int r11;
|
||||
long unsigned int r10;
|
||||
long unsigned int r9;
|
||||
long unsigned int r8;
|
||||
long unsigned int ax; /* Must match kernel BTF field names */
|
||||
long unsigned int cx; /* Must match kernel BTF field names */
|
||||
long unsigned int dx; /* Must match kernel BTF field names */
|
||||
long unsigned int si; /* Must match kernel BTF field names */
|
||||
long unsigned int di; /* Must match kernel BTF field names */
|
||||
/*
|
||||
* On syscall entry, this is syscall#. On CPU exception, this is error code.
|
||||
* On hw interrupt, it's IRQ number:
|
||||
*/
|
||||
long unsigned int orig_ax;
|
||||
/* Return frame for iretq */
|
||||
long unsigned int ip; /* Must match kernel BTF field names */
|
||||
union {
|
||||
__u16 cs;
|
||||
__u64 csx;
|
||||
struct fred_cs fred_cs;
|
||||
};
|
||||
long unsigned int flags; /* Must match kernel BTF field names */
|
||||
long unsigned int sp; /* Must match kernel BTF field names */
|
||||
union {
|
||||
__u16 ss;
|
||||
__u64 ssx;
|
||||
struct fred_ss fred_ss;
|
||||
};
|
||||
};
|
||||
|
||||
#ifndef BPF_NO_PRESERVE_ACCESS_INDEX
|
||||
#pragma clang attribute pop
|
||||
#endif
|
||||
|
||||
#endif /* __VMLINUX_MIN_H__ */
|
||||
Reference in New Issue
Block a user