/src/capstonev5/arch/BPF/BPFDisassembler.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Capstone Disassembly Engine */ |
2 | | /* BPF Backend by david942j <david942j@gmail.com>, 2019 */ |
3 | | |
4 | | #ifdef CAPSTONE_HAS_BPF |
5 | | |
6 | | #include <string.h> |
7 | | #include <stddef.h> // offsetof macro |
8 | | |
9 | | #include "BPFConstants.h" |
10 | | #include "BPFDisassembler.h" |
11 | | #include "BPFMapping.h" |
12 | | #include "../../cs_priv.h" |
13 | | |
14 | | static uint16_t read_u16(cs_struct *ud, const uint8_t *code) |
15 | 38.2k | { |
16 | 38.2k | if (MODE_IS_BIG_ENDIAN(ud->mode)) |
17 | 20.2k | return (((uint16_t)code[0] << 8) | code[1]); |
18 | 17.9k | else |
19 | 17.9k | return (((uint16_t)code[1] << 8) | code[0]); |
20 | 38.2k | } |
21 | | |
22 | | static uint32_t read_u32(cs_struct *ud, const uint8_t *code) |
23 | 12.9k | { |
24 | 12.9k | if (MODE_IS_BIG_ENDIAN(ud->mode)) |
25 | 6.88k | return ((uint32_t)read_u16(ud, code) << 16) | read_u16(ud, code + 2); |
26 | 6.05k | else |
27 | 6.05k | return ((uint32_t)read_u16(ud, code + 2) << 16) | read_u16(ud, code); |
28 | 12.9k | } |
29 | | |
30 | | ///< Malloc bpf_internal, also checks if code_len is large enough. |
31 | | static bpf_internal *alloc_bpf_internal(size_t code_len) |
32 | 28.7k | { |
33 | 28.7k | bpf_internal *bpf; |
34 | | |
35 | 28.7k | if (code_len < 8) |
36 | 466 | return NULL; |
37 | 28.3k | bpf = cs_mem_malloc(sizeof(bpf_internal)); |
38 | 28.3k | if (bpf == NULL) |
39 | 0 | return NULL; |
40 | | /* default value */ |
41 | 28.3k | bpf->insn_size = 8; |
42 | 28.3k | return bpf; |
43 | 28.3k | } |
44 | | |
45 | | ///< Fetch a cBPF structure from code |
46 | | static bpf_internal* fetch_cbpf(cs_struct *ud, const uint8_t *code, |
47 | | size_t code_len) |
48 | 9.91k | { |
49 | 9.91k | bpf_internal *bpf; |
50 | | |
51 | 9.91k | bpf = alloc_bpf_internal(code_len); |
52 | 9.91k | if (bpf == NULL) |
53 | 145 | return NULL; |
54 | | |
55 | 9.77k | bpf->op = read_u16(ud, code); |
56 | 9.77k | bpf->jt = code[2]; |
57 | 9.77k | bpf->jf = code[3]; |
58 | 9.77k | bpf->k = read_u32(ud, code + 4); |
59 | 9.77k | return bpf; |
60 | 9.91k | } |
61 | | |
62 | | ///< Fetch an eBPF structure from code |
63 | | static bpf_internal* fetch_ebpf(cs_struct *ud, const uint8_t *code, |
64 | | size_t code_len) |
65 | 18.8k | { |
66 | 18.8k | bpf_internal *bpf; |
67 | | |
68 | 18.8k | bpf = alloc_bpf_internal(code_len); |
69 | 18.8k | if (bpf == NULL) |
70 | 321 | return NULL; |
71 | | |
72 | 18.5k | bpf->op = (uint16_t)code[0]; |
73 | 18.5k | bpf->dst = code[1] & 0xf; |
74 | 18.5k | bpf->src = (code[1] & 0xf0) >> 4; |
75 | | |
76 | | // eBPF has one 16-byte instruction: BPF_LD | BPF_DW | BPF_IMM, |
77 | | // in this case imm is combined with the next block's imm. |
78 | 18.5k | if (bpf->op == (BPF_CLASS_LD | BPF_SIZE_DW | BPF_MODE_IMM)) { |
79 | 566 | if (code_len < 16) { |
80 | 3 | cs_mem_free(bpf); |
81 | 3 | return NULL; |
82 | 3 | } |
83 | 563 | bpf->k = read_u32(ud, code + 4) | (((uint64_t)read_u32(ud, code + 12)) << 32); |
84 | 563 | bpf->insn_size = 16; |
85 | 563 | } |
86 | 17.9k | else { |
87 | 17.9k | bpf->offset = read_u16(ud, code + 2); |
88 | 17.9k | bpf->k = read_u32(ud, code + 4); |
89 | 17.9k | } |
90 | 18.5k | return bpf; |
91 | 18.5k | } |
92 | | |
93 | 7.76k | #define CHECK_READABLE_REG(ud, reg) do { \ |
94 | 7.76k | if (! ((reg) >= BPF_REG_R0 && (reg) <= BPF_REG_R10)) \ |
95 | 7.76k | return false; \ |
96 | 7.76k | } while (0) |
97 | | |
98 | 4.87k | #define CHECK_WRITABLE_REG(ud, reg) do { \ |
99 | 4.87k | if (! ((reg) >= BPF_REG_R0 && (reg) < BPF_REG_R10)) \ |
100 | 4.87k | return false; \ |
101 | 4.87k | } while (0) |
102 | | |
103 | 7.76k | #define CHECK_READABLE_AND_PUSH(ud, MI, r) do { \ |
104 | 7.76k | CHECK_READABLE_REG(ud, r + BPF_REG_R0); \ |
105 | 7.76k | MCOperand_CreateReg0(MI, r + BPF_REG_R0); \ |
106 | 7.71k | } while (0) |
107 | | |
108 | 4.87k | #define CHECK_WRITABLE_AND_PUSH(ud, MI, r) do { \ |
109 | 4.87k | CHECK_WRITABLE_REG(ud, r + BPF_REG_R0); \ |
110 | 4.87k | MCOperand_CreateReg0(MI, r + BPF_REG_R0); \ |
111 | 4.86k | } while (0) |
112 | | |
113 | | static bool decodeLoad(cs_struct *ud, MCInst *MI, bpf_internal *bpf) |
114 | 9.04k | { |
115 | 9.04k | if (!EBPF_MODE(ud)) { |
116 | | /* |
117 | | * +-----+-----------+--------------------+ |
118 | | * | ldb | [k] | [x+k] | |
119 | | * | ldh | [k] | [x+k] | |
120 | | * +-----+-----------+--------------------+ |
121 | | */ |
122 | 3.73k | if (BPF_SIZE(bpf->op) == BPF_SIZE_DW) |
123 | 7 | return false; |
124 | 3.72k | if (BPF_SIZE(bpf->op) == BPF_SIZE_B || BPF_SIZE(bpf->op) == BPF_SIZE_H) { |
125 | | /* no ldx */ |
126 | 1.09k | if (BPF_CLASS(bpf->op) != BPF_CLASS_LD) |
127 | 9 | return false; |
128 | | /* can only be BPF_ABS and BPF_IND */ |
129 | 1.08k | if (BPF_MODE(bpf->op) == BPF_MODE_ABS) { |
130 | 598 | MCOperand_CreateImm0(MI, bpf->k); |
131 | 598 | return true; |
132 | 598 | } |
133 | 490 | else if (BPF_MODE(bpf->op) == BPF_MODE_IND) { |
134 | 486 | MCOperand_CreateReg0(MI, BPF_REG_X); |
135 | 486 | MCOperand_CreateImm0(MI, bpf->k); |
136 | 486 | return true; |
137 | 486 | } |
138 | 4 | return false; |
139 | 1.08k | } |
140 | | /* |
141 | | * +-----+----+------+------+-----+-------+ |
142 | | * | ld | #k | #len | M[k] | [k] | [x+k] | |
143 | | * +-----+----+------+------+-----+-------+ |
144 | | * | ldx | #k | #len | M[k] | 4*([k]&0xf) | |
145 | | * +-----+----+------+------+-------------+ |
146 | | */ |
147 | 2.62k | switch (BPF_MODE(bpf->op)) { |
148 | 918 | default: |
149 | 918 | break; |
150 | 948 | case BPF_MODE_IMM: |
151 | 948 | MCOperand_CreateImm0(MI, bpf->k); |
152 | 948 | return true; |
153 | 407 | case BPF_MODE_LEN: |
154 | 407 | return true; |
155 | 355 | case BPF_MODE_MEM: |
156 | 355 | MCOperand_CreateImm0(MI, bpf->k); |
157 | 355 | return true; |
158 | 2.62k | } |
159 | 918 | if (BPF_CLASS(bpf->op) == BPF_CLASS_LD) { |
160 | 574 | if (BPF_MODE(bpf->op) == BPF_MODE_ABS) { |
161 | 303 | MCOperand_CreateImm0(MI, bpf->k); |
162 | 303 | return true; |
163 | 303 | } |
164 | 271 | else if (BPF_MODE(bpf->op) == BPF_MODE_IND) { |
165 | 268 | MCOperand_CreateReg0(MI, BPF_REG_X); |
166 | 268 | MCOperand_CreateImm0(MI, bpf->k); |
167 | 268 | return true; |
168 | 268 | } |
169 | 574 | } |
170 | 344 | else { /* LDX */ |
171 | 344 | if (BPF_MODE(bpf->op) == BPF_MODE_MSH) { |
172 | 341 | MCOperand_CreateImm0(MI, bpf->k); |
173 | 341 | return true; |
174 | 341 | } |
175 | 344 | } |
176 | 6 | return false; |
177 | 918 | } |
178 | | |
179 | | /* eBPF mode */ |
180 | | /* |
181 | | * - IMM: lddw dst, imm64 |
182 | | * - ABS: ld{w,h,b,dw} [k] |
183 | | * - IND: ld{w,h,b,dw} [src+k] |
184 | | * - MEM: ldx{w,h,b,dw} dst, [src+off] |
185 | | */ |
186 | 5.31k | if (BPF_CLASS(bpf->op) == BPF_CLASS_LD) { |
187 | 3.46k | switch (BPF_MODE(bpf->op)) { |
188 | 587 | case BPF_MODE_IMM: |
189 | 587 | if (bpf->op != (BPF_CLASS_LD | BPF_SIZE_DW | BPF_MODE_IMM)) |
190 | 24 | return false; |
191 | 563 | CHECK_WRITABLE_AND_PUSH(ud, MI, bpf->dst); |
192 | 561 | MCOperand_CreateImm0(MI, bpf->k); |
193 | 561 | return true; |
194 | 1.79k | case BPF_MODE_ABS: |
195 | 1.79k | MCOperand_CreateImm0(MI, bpf->k); |
196 | 1.79k | return true; |
197 | 1.08k | case BPF_MODE_IND: |
198 | 1.08k | CHECK_READABLE_AND_PUSH(ud, MI, bpf->src); |
199 | 1.08k | MCOperand_CreateImm0(MI, bpf->k); |
200 | 1.08k | return true; |
201 | 3.46k | } |
202 | 3 | return false; |
203 | | |
204 | 3.46k | } |
205 | | /* LDX */ |
206 | 1.85k | if (BPF_MODE(bpf->op) == BPF_MODE_MEM) { |
207 | 1.83k | CHECK_WRITABLE_AND_PUSH(ud, MI, bpf->dst); |
208 | 1.83k | CHECK_READABLE_AND_PUSH(ud, MI, bpf->src); |
209 | 1.82k | MCOperand_CreateImm0(MI, bpf->offset); |
210 | 1.82k | return true; |
211 | 1.83k | } |
212 | 17 | return false; |
213 | 1.85k | } |
214 | | |
215 | | static bool decodeStore(cs_struct *ud, MCInst *MI, bpf_internal *bpf) |
216 | 2.32k | { |
217 | | /* in cBPF, only BPF_ST* | BPF_MEM | BPF_W is valid |
218 | | * while in eBPF: |
219 | | * - BPF_STX | BPF_XADD | BPF_{W,DW} |
220 | | * - BPF_ST* | BPF_MEM | BPF_{W,H,B,DW} |
221 | | * are valid |
222 | | */ |
223 | 2.32k | if (!EBPF_MODE(ud)) { |
224 | | /* can only store to M[] */ |
225 | 78 | if (bpf->op != (BPF_CLASS(bpf->op) | BPF_MODE_MEM | BPF_SIZE_W)) |
226 | 9 | return false; |
227 | 69 | MCOperand_CreateImm0(MI, bpf->k); |
228 | 69 | return true; |
229 | 78 | } |
230 | | |
231 | | /* eBPF */ |
232 | | |
233 | 2.25k | if (BPF_MODE(bpf->op) == BPF_MODE_XADD) { |
234 | 295 | if (BPF_CLASS(bpf->op) != BPF_CLASS_STX) |
235 | 2 | return false; |
236 | 293 | if (BPF_SIZE(bpf->op) != BPF_SIZE_W && BPF_SIZE(bpf->op) != BPF_SIZE_DW) |
237 | 3 | return false; |
238 | | /* xadd [dst + off], src */ |
239 | 290 | CHECK_READABLE_AND_PUSH(ud, MI, bpf->dst); |
240 | 288 | MCOperand_CreateImm0(MI, bpf->offset); |
241 | 288 | CHECK_READABLE_AND_PUSH(ud, MI, bpf->src); |
242 | 285 | return true; |
243 | 288 | } |
244 | | |
245 | 1.95k | if (BPF_MODE(bpf->op) != BPF_MODE_MEM) |
246 | 16 | return false; |
247 | | |
248 | | /* st [dst + off], src */ |
249 | 1.93k | CHECK_READABLE_AND_PUSH(ud, MI, bpf->dst); |
250 | 1.93k | MCOperand_CreateImm0(MI, bpf->offset); |
251 | 1.93k | if (BPF_CLASS(bpf->op) == BPF_CLASS_ST) |
252 | 1.17k | MCOperand_CreateImm0(MI, bpf->k); |
253 | 759 | else |
254 | 759 | CHECK_READABLE_AND_PUSH(ud, MI, bpf->src); |
255 | 1.93k | return true; |
256 | 1.93k | } |
257 | | |
258 | | static bool decodeALU(cs_struct *ud, MCInst *MI, bpf_internal *bpf) |
259 | 3.66k | { |
260 | | /* Set MI->Operands */ |
261 | | |
262 | | /* cBPF */ |
263 | 3.66k | if (!EBPF_MODE(ud)) { |
264 | 1.15k | if (BPF_OP(bpf->op) > BPF_ALU_XOR) |
265 | 1 | return false; |
266 | | /* cBPF's NEG has no operands */ |
267 | 1.15k | if (BPF_OP(bpf->op) == BPF_ALU_NEG) |
268 | 197 | return true; |
269 | 958 | if (BPF_SRC(bpf->op) == BPF_SRC_K) |
270 | 443 | MCOperand_CreateImm0(MI, bpf->k); |
271 | 515 | else /* BPF_SRC_X */ |
272 | 515 | MCOperand_CreateReg0(MI, BPF_REG_X); |
273 | 958 | return true; |
274 | 1.15k | } |
275 | | |
276 | | /* eBPF */ |
277 | | |
278 | 2.51k | if (BPF_OP(bpf->op) > BPF_ALU_END) |
279 | 2 | return false; |
280 | | /* ALU64 class doesn't have ENDian */ |
281 | | /* ENDian's imm must be one of 16, 32, 64 */ |
282 | 2.51k | if (BPF_OP(bpf->op) == BPF_ALU_END) { |
283 | 204 | if (BPF_CLASS(bpf->op) == BPF_CLASS_ALU64) |
284 | 2 | return false; |
285 | 202 | if (bpf->k != 16 && bpf->k != 32 && bpf->k != 64) |
286 | 27 | return false; |
287 | 202 | } |
288 | | |
289 | | /* - op dst, imm |
290 | | * - op dst, src |
291 | | * - neg dst |
292 | | * - le<imm> dst |
293 | | */ |
294 | | /* every ALU instructions have dst op */ |
295 | 2.48k | CHECK_WRITABLE_AND_PUSH(ud, MI, bpf->dst); |
296 | | |
297 | | /* special cases */ |
298 | 2.47k | if (BPF_OP(bpf->op) == BPF_ALU_NEG) |
299 | 142 | return true; |
300 | 2.33k | if (BPF_OP(bpf->op) == BPF_ALU_END) { |
301 | | /* bpf->k must be one of 16, 32, 64 */ |
302 | 175 | MCInst_setOpcode(MI, MCInst_getOpcode(MI) | ((uint32_t)bpf->k << 4)); |
303 | 175 | return true; |
304 | 175 | } |
305 | | |
306 | | /* normal cases */ |
307 | 2.16k | if (BPF_SRC(bpf->op) == BPF_SRC_K) { |
308 | 1.95k | MCOperand_CreateImm0(MI, bpf->k); |
309 | 1.95k | } |
310 | 209 | else { /* BPF_SRC_X */ |
311 | 209 | CHECK_READABLE_AND_PUSH(ud, MI, bpf->src); |
312 | 209 | } |
313 | 2.15k | return true; |
314 | 2.16k | } |
315 | | |
316 | | static bool decodeJump(cs_struct *ud, MCInst *MI, bpf_internal *bpf) |
317 | 3.45k | { |
318 | | /* cBPF and eBPF are very different in class jump */ |
319 | 3.45k | if (!EBPF_MODE(ud)) { |
320 | 1.43k | if (BPF_OP(bpf->op) > BPF_JUMP_JSET) |
321 | 2 | return false; |
322 | | |
323 | | /* ja is a special case of jumps */ |
324 | 1.42k | if (BPF_OP(bpf->op) == BPF_JUMP_JA) { |
325 | 203 | MCOperand_CreateImm0(MI, bpf->k); |
326 | 203 | return true; |
327 | 203 | } |
328 | | |
329 | 1.22k | if (BPF_SRC(bpf->op) == BPF_SRC_K) |
330 | 894 | MCOperand_CreateImm0(MI, bpf->k); |
331 | 332 | else /* BPF_SRC_X */ |
332 | 332 | MCOperand_CreateReg0(MI, BPF_REG_X); |
333 | 1.22k | MCOperand_CreateImm0(MI, bpf->jt); |
334 | 1.22k | MCOperand_CreateImm0(MI, bpf->jf); |
335 | 1.22k | } |
336 | 2.02k | else { |
337 | 2.02k | if (BPF_OP(bpf->op) > BPF_JUMP_JSLE) |
338 | 1 | return false; |
339 | | |
340 | | /* No operands for exit */ |
341 | 2.02k | if (BPF_OP(bpf->op) == BPF_JUMP_EXIT) |
342 | 254 | return bpf->op == (BPF_CLASS_JMP | BPF_JUMP_EXIT); |
343 | 1.77k | if (BPF_OP(bpf->op) == BPF_JUMP_CALL) { |
344 | 290 | if (bpf->op == (BPF_CLASS_JMP | BPF_JUMP_CALL)) { |
345 | 245 | MCOperand_CreateImm0(MI, bpf->k); |
346 | 245 | return true; |
347 | 245 | } |
348 | 45 | if (bpf->op == (BPF_CLASS_JMP | BPF_JUMP_CALL | BPF_SRC_X)) { |
349 | 45 | CHECK_READABLE_AND_PUSH(ud, MI, bpf->k); |
350 | 15 | return true; |
351 | 45 | } |
352 | 0 | return false; |
353 | 45 | } |
354 | | |
355 | | /* ja is a special case of jumps */ |
356 | 1.48k | if (BPF_OP(bpf->op) == BPF_JUMP_JA) { |
357 | 312 | if (BPF_SRC(bpf->op) != BPF_SRC_K) |
358 | 2 | return false; |
359 | 310 | MCOperand_CreateImm0(MI, bpf->offset); |
360 | 310 | return true; |
361 | 312 | } |
362 | | |
363 | | /* <j> dst, src, +off */ |
364 | 1.16k | CHECK_READABLE_AND_PUSH(ud, MI, bpf->dst); |
365 | 1.16k | if (BPF_SRC(bpf->op) == BPF_SRC_K) |
366 | 1.00k | MCOperand_CreateImm0(MI, bpf->k); |
367 | 157 | else |
368 | 157 | CHECK_READABLE_AND_PUSH(ud, MI, bpf->src); |
369 | 1.16k | MCOperand_CreateImm0(MI, bpf->offset); |
370 | 1.16k | } |
371 | 2.39k | return true; |
372 | 3.45k | } |
373 | | |
374 | | static bool decodeReturn(cs_struct *ud, MCInst *MI, bpf_internal *bpf) |
375 | 1.22k | { |
376 | | /* Here only handles the BPF_RET class in cBPF */ |
377 | 1.22k | switch (BPF_RVAL(bpf->op)) { |
378 | 520 | case BPF_SRC_K: |
379 | 520 | MCOperand_CreateImm0(MI, bpf->k); |
380 | 520 | return true; |
381 | 328 | case BPF_SRC_X: |
382 | 328 | MCOperand_CreateReg0(MI, BPF_REG_X); |
383 | 328 | return true; |
384 | 373 | case BPF_SRC_A: |
385 | 373 | MCOperand_CreateReg0(MI, BPF_REG_A); |
386 | 373 | return true; |
387 | 1.22k | } |
388 | 3 | return false; |
389 | 1.22k | } |
390 | | |
391 | | static bool decodeMISC(cs_struct *ud, MCInst *MI, bpf_internal *bpf) |
392 | 159 | { |
393 | 159 | uint16_t op = bpf->op ^ BPF_CLASS_MISC; |
394 | 159 | return op == BPF_MISCOP_TAX || op == BPF_MISCOP_TXA; |
395 | 159 | } |
396 | | |
397 | | ///< 1. Check if the instruction is valid |
398 | | ///< 2. Set MI->opcode |
399 | | ///< 3. Set MI->Operands |
400 | | static bool getInstruction(cs_struct *ud, MCInst *MI, bpf_internal *bpf) |
401 | 12.6k | { |
402 | 12.6k | cs_detail *detail; |
403 | | |
404 | 12.6k | detail = MI->flat_insn->detail; |
405 | | // initialize detail |
406 | 12.6k | if (detail) { |
407 | 12.6k | memset(detail, 0, offsetof(cs_detail, bpf) + sizeof(cs_bpf)); |
408 | 12.6k | } |
409 | | |
410 | 12.6k | MCInst_clear(MI); |
411 | 12.6k | MCInst_setOpcode(MI, bpf->op); |
412 | | |
413 | 12.6k | switch (BPF_CLASS(bpf->op)) { |
414 | 0 | default: /* should never happen */ |
415 | 0 | return false; |
416 | 3.08k | case BPF_CLASS_LD: |
417 | 3.82k | case BPF_CLASS_LDX: |
418 | 3.82k | return decodeLoad(ud, MI, bpf); |
419 | 619 | case BPF_CLASS_ST: |
420 | 1.08k | case BPF_CLASS_STX: |
421 | 1.08k | return decodeStore(ud, MI, bpf); |
422 | 2.33k | case BPF_CLASS_ALU: |
423 | 2.33k | return decodeALU(ud, MI, bpf); |
424 | 3.45k | case BPF_CLASS_JMP: |
425 | 3.45k | return decodeJump(ud, MI, bpf); |
426 | 492 | case BPF_CLASS_RET: |
427 | | /* eBPF doesn't have this class */ |
428 | 492 | if (EBPF_MODE(ud)) |
429 | 4 | return false; |
430 | 488 | return decodeReturn(ud, MI, bpf); |
431 | 1.43k | case BPF_CLASS_MISC: |
432 | | /* case BPF_CLASS_ALU64: */ |
433 | 1.43k | if (EBPF_MODE(ud)) |
434 | 1.33k | return decodeALU(ud, MI, bpf); |
435 | 103 | else |
436 | 103 | return decodeMISC(ud, MI, bpf); |
437 | 12.6k | } |
438 | 12.6k | } |
439 | | |
440 | | bool BPF_getInstruction(csh ud, const uint8_t *code, size_t code_len, |
441 | | MCInst *instr, uint16_t *size, uint64_t address, void *info) |
442 | 12.7k | { |
443 | 12.7k | cs_struct *cs; |
444 | 12.7k | bpf_internal *bpf; |
445 | | |
446 | 12.7k | cs = (cs_struct*)ud; |
447 | 12.7k | if (EBPF_MODE(cs)) |
448 | 7.42k | bpf = fetch_ebpf(cs, code, code_len); |
449 | 5.37k | else |
450 | 5.37k | bpf = fetch_cbpf(cs, code, code_len); |
451 | 12.7k | if (bpf == NULL) |
452 | 159 | return false; |
453 | 12.6k | if (!getInstruction(cs, instr, bpf)) { |
454 | 142 | cs_mem_free(bpf); |
455 | 142 | return false; |
456 | 142 | } |
457 | | |
458 | 12.4k | *size = bpf->insn_size; |
459 | 12.4k | cs_mem_free(bpf); |
460 | | |
461 | 12.4k | return true; |
462 | 12.6k | } |
463 | | |
464 | | #endif |