1- //! Classic BPF (cBPF) 解释器与验证器。
1+ //! Classic BPF (cBPF) interpreter and verifier.
22//!
3- //! 本模块只实现 cBPF 机器模型、结构验证和输入协议。packet 与 seccomp
4- //! 的字节序、逻辑偏移和 ancillary 语义由各自的输入实现负责。
3+ //! This module only implements the cBPF machine model, structural validation,
4+ //! and the input protocol. Byte order, logical offsets, and ancillary semantics
5+ //! for packet and seccomp are handled by their respective input implementations.
56
67use alloc:: vec:: Vec ;
78use system_error:: SystemError ;
@@ -10,7 +11,7 @@ use crate::syscall::user_access::UserBufferReader;
1011
1112// ============ Sock Filter / Sock Fprog ============
1213
13- /// Classic BPF 指令(对应 Linux `struct sock_filter`,8 字节)
14+ /// Classic BPF instruction (corresponds to Linux `struct sock_filter`, 8 bytes)
1415#[ repr( C ) ]
1516#[ derive( Debug , Clone , Copy ) ]
1617pub struct SockFilter {
@@ -20,9 +21,9 @@ pub struct SockFilter {
2021 pub k : u32 ,
2122}
2223
23- /// `struct sock_fprog` —— 用户空间传入的 filter 容器。
24+ /// `struct sock_fprog` — userspace filter container.
2425///
25- /// 布局: `{ u16 len; u8 _pad[6]; u64 filter; }`(共 16 字节)。
26+ /// Layout: `{ u16 len; u8 _pad[6]; u64 filter; }` ( 16 bytes total).
2627#[ repr( C ) ]
2728#[ derive( Debug , Clone , Copy ) ]
2829pub struct SockFprog {
@@ -31,10 +32,10 @@ pub struct SockFprog {
3132 pub filter : u64 ,
3233}
3334
34- // ============ BPF 指令常量 ============
35- // 参考 Linux include/uapi/linux/filter.h
35+ // ============ BPF Instruction Constants ============
36+ // Reference: Linux include/uapi/linux/filter.h
3637
37- /// 指令类( code & 0x07)
38+ /// Instruction class ( code & 0x07)
3839pub const BPF_LD : u16 = 0x00 ;
3940pub const BPF_LDX : u16 = 0x01 ;
4041pub const BPF_ST : u16 = 0x02 ;
@@ -44,27 +45,27 @@ pub const BPF_JMP: u16 = 0x05;
4445pub const BPF_RET : u16 = 0x06 ;
4546pub const BPF_MISC : u16 = 0x07 ;
4647
47- /// 加载宽度( code & 0x18,仅对 LD/LDX 有意义)
48+ /// Load width ( code & 0x18, meaningful only for LD/LDX)
4849pub const BPF_W : u16 = 0x00 ;
4950pub const BPF_H : u16 = 0x08 ;
5051pub const BPF_B : u16 = 0x10 ;
5152
52- /// 寻址模式( code & 0xe0,仅对 LD/LDX 有意义)
53+ /// Addressing mode ( code & 0xe0, meaningful only for LD/LDX)
5354pub const BPF_IMM : u16 = 0x00 ;
5455pub const BPF_ABS : u16 = 0x20 ;
5556pub const BPF_IND : u16 = 0x40 ;
5657pub const BPF_MEM : u16 = 0x60 ;
5758pub const BPF_LEN : u16 = 0x80 ;
58- /// BPF_MSH:仅用于 `LDX|BPF_B|BPF_MSH`,提取 IP 头长度
59- /// ( `x = (data[k] & 0xf) << 2`)。
59+ /// BPF_MSH: only used for `LDX|BPF_B|BPF_MSH`, extracts IP header length
60+ /// ( `x = (data[k] & 0xf) << 2`).
6061pub const BPF_MSH : u16 = 0xa0 ;
6162
62- /// 数据源( code & 0x08,仅对 ALU/JMP 有意义)
63+ /// Data source ( code & 0x08, meaningful only for ALU/JMP)
6364pub const BPF_K : u16 = 0x00 ;
6465pub const BPF_X : u16 = 0x08 ;
6566pub const BPF_A : u16 = 0x10 ;
6667
67- /// ALU 操作( code & 0xf0)
68+ /// ALU operation ( code & 0xf0)
6869pub const BPF_ADD : u16 = 0x00 ;
6970pub const BPF_SUB : u16 = 0x10 ;
7071pub const BPF_MUL : u16 = 0x20 ;
@@ -77,24 +78,24 @@ pub const BPF_NEG: u16 = 0x80;
7778pub const BPF_MOD : u16 = 0x90 ;
7879pub const BPF_XOR : u16 = 0xa0 ;
7980
80- /// JMP 操作( code & 0xf0)
81+ /// JMP operation ( code & 0xf0)
8182pub const BPF_JA : u16 = 0x00 ;
8283pub const BPF_JEQ : u16 = 0x10 ;
8384pub const BPF_JGT : u16 = 0x20 ;
8485pub const BPF_JGE : u16 = 0x30 ;
8586pub const BPF_JSET : u16 = 0x40 ;
8687
87- /// MISC 操作( code & 0xf8)
88+ /// MISC operation ( code & 0xf8)
8889pub const BPF_TAX : u16 = 0x00 ;
8990pub const BPF_TXA : u16 = 0x80 ;
9091
91- /// BPF 程序最大指令数( Linux 限制)
92+ /// Maximum BPF program instruction count ( Linux limit)
9293pub const BPF_MAXINSNS : usize = 4096 ;
9394
94- /// BPF 记忆体大小(16 个 u32 字)
95+ /// BPF memory size (16 u32 words)
9596pub const BPF_MEMWORDS : usize = 16 ;
9697
97- /// Linux socket filter ancillary 偏移。
98+ /// Linux socket filter ancillary offset.
9899pub const SKF_AD_OFF : u32 = ( -0x1000i32 ) as u32 ;
99100pub const SKF_AD_PROTOCOL : u32 = 0 ;
100101pub const SKF_AD_PKTTYPE : u32 = 4 ;
@@ -122,7 +123,7 @@ pub enum BpfWidth {
122123 Byte ,
123124}
124125
125- /// cBPF 的调用域输入。实现必须自行定义普通加载的字节序和负偏移语义。
126+ /// cBPF call-domain input. Implementations must define their own byte order and negative offset semantics for normal loads.
126127pub trait ClassicBpfInput {
127128 fn len ( & self ) -> u32 ;
128129
@@ -157,26 +158,26 @@ impl ClassicBpfInput for [u8] {
157158 }
158159}
159160
160- // ============ cBPF 解释器 ============
161+ // ============ cBPF Interpreter ============
161162
162- /// 运行 classic BPF 程序。
163+ /// Run a classic BPF program.
163164///
164- /// cBPF 寄存器模型:
165- /// - A (u32): 累加器
166- /// - X (u32): 索引寄存器
167- /// - pc: 程序计数器
168- /// - mem\[16\]: 记忆体
165+ /// cBPF register model:
166+ /// - A (u32): accumulator
167+ /// - X (u32): index register
168+ /// - pc: program counter
169+ /// - mem\[16\]: scratch memory
169170///
170- /// # 加载语义
171- /// - `BPF_LD|BPF_W/H/B|BPF_ABS`: 由 input 按调用域语义加载
172- /// - `BPF_LD|*|BPF_IND`: 同上,但 offset = X + k
173- /// - 越界读取( offset + size > data.len()):立即返回 0
171+ /// # Load semantics
172+ /// - `BPF_LD|BPF_W/H/B|BPF_ABS`: loaded by input per call-domain semantics
173+ /// - `BPF_LD|*|BPF_IND`: same as above, but offset = X + k
174+ /// - Out-of-bounds read ( offset + size > data.len()): immediately return 0
174175/// - `BPF_LEN`: A = data.len() as u32
175176///
176- /// # 返回值
177- /// - 正常返回 `RET` 指令的值(返回截断长度, 0 = 丢弃)
178- /// - `DIV`/`MOD` 除数为 0:立即返回 0
179- /// - fall -through(无 RET 结尾):返回 0(丢弃)
177+ /// # Return value
178+ /// - Normal: value of the `RET` instruction (snap length; 0 = drop)
179+ /// - `DIV`/`MOD` divisor is 0: immediately return 0
180+ /// - Fall -through (no RET at end): return 0 (drop)
180181pub fn run_cbpf < I : ClassicBpfInput + ?Sized > ( insns : & [ SockFilter ] , input : & I ) -> u32 {
181182 let mut a: u32 = 0 ;
182183 let mut x: u32 = 0 ;
@@ -317,7 +318,7 @@ pub fn run_cbpf<I: ClassicBpfInput + ?Sized>(insns: &[SockFilter], input: &I) ->
317318 pc += 1 ;
318319 }
319320
320- // fall-through:返回 0(丢弃)
321+ // fall-through: return 0 (drop)
321322 0
322323}
323324
@@ -336,18 +337,18 @@ fn is_ancillary(offset: u32) -> bool {
336337 offset >= SKF_AD_OFF
337338}
338339
339- // ============ cBPF 验证器 ============
340+ // ============ cBPF Verifier ============
340341
341- /// 验证 cBPF 程序的合法性(通用检查)。
342+ /// Validate the legality of a cBPF program (generic checks).
342343///
343- /// 检查项:
344- /// 1. 非空
344+ /// Checks:
345+ /// 1. Non-empty
345346/// 2. len <= BPF_MAXINSNS (4096)
346- /// 3. 末条指令 class == BPF_RET
347- /// 4. 跳转目标 `checked_add`(溢出 → EINVAL),且 < insns.len()
348- /// 5. ST/STX 的 k < BPF_MEMWORDS (16)
349- /// 6. ALU|DIV|K 的 k != 0; ALU|MOD|K 的 k != 0(静态拒绝)
350- /// 7. opcode class 在白名单内( LD 允许 IMM/ABS/IND/MEM/LEN; LDX 允许 IMM/MEM/LEN/MSH,其中 MSH 仅限 BPF_B 宽度)
347+ /// 3. Last instruction class == BPF_RET
348+ /// 4. Jump target `checked_add` (overflow → EINVAL), and < insns.len()
349+ /// 5. ST/STX k < BPF_MEMWORDS (16)
350+ /// 6. ALU|DIV|K k != 0; ALU|MOD|K k != 0 (statically rejected)
351+ /// 7. Opcode class is whitelisted ( LD allows IMM/ABS/IND/MEM/LEN; LDX allows IMM/MEM/LEN/MSH, where MSH is restricted to BPF_B width)
351352pub fn validate_cbpf ( insns : & [ SockFilter ] ) -> Result < ( ) , SystemError > {
352353 if insns. is_empty ( ) {
353354 return Err ( SystemError :: EINVAL ) ;
@@ -503,14 +504,14 @@ fn check_loads_and_stores(insns: &[SockFilter]) -> Result<(), SystemError> {
503504 Ok ( ( ) )
504505}
505506
506- // ============ 用户空间解析 ============
507+ // ============ Userspace Parsing ============
507508
508- /// 从 optval 字节切片解析 `sock_fprog` 结构并读取 filter 指令。
509+ /// Parse the `sock_fprog` structure from an optval byte slice and read filter instructions.
509510///
510- /// `optval` 必须精确包含一个 native `struct sock_fprog`。
511- /// 内部通过 `UserBufferReader` 安全地从用户空间读取 filter 指令数组。
511+ /// `optval` must contain exactly one native `struct sock_fprog`.
512+ /// Internally uses `UserBufferReader` to safely read the filter instruction array from userspace.
512513///
513- /// 返回已解析的 `Vec<SockFilter>`。
514+ /// Returns the parsed `Vec<SockFilter>`.
514515pub ( crate ) fn parse_sock_fprog ( optval : & [ u8 ] ) -> Result < SockFprog , SystemError > {
515516 let fprog_size = core:: mem:: size_of :: < SockFprog > ( ) ;
516517 if optval. len ( ) != fprog_size {
@@ -543,7 +544,7 @@ pub(crate) fn read_sock_fprog(optval: &[u8]) -> Result<Vec<SockFilter>, SystemEr
543544 read_sock_fprog_insns ( & fprog)
544545}
545546
546- /// 从用户空间读取 filter 指令数组。
547+ /// Read the filter instruction array from userspace.
547548fn read_filter_insns ( ptr : u64 , count : usize ) -> Result < Vec < SockFilter > , SystemError > {
548549 let insn_size = core:: mem:: size_of :: < SockFilter > ( ) ;
549550 let byte_len = count. checked_mul ( insn_size) . ok_or ( SystemError :: EINVAL ) ?;
0 commit comments