0x1:基本概念
- 当应用tracepoint的时候,函数参数如何确认?
cat /sys/kernel/debug/tracing/events/syscalls/xxx/format. xxx为要跟踪的函数,在这里有函数参数定义。
0x2:注意事项
- 写构造体的时候肯定要留神内存对齐,避免被编译器优化填充。
应用 LLVM 内置的函数做内存操作
#ifndef memset# define memset(dest, chr, n) __builtin_memset((dest), (chr), (n))#endif#ifndef memcpy# define memcpy(dest, src, n) __builtin_memcpy((dest), (src), (n))#endif#ifndef memmove# define memmove(dest, src, n) __builtin_memmove((dest), (src), (n))#endif
指针被操作过后,就得再次申明,不然会被禁止拜访
struct iphdr *ip4 = (struct iphdr *) skb->data + ETH_HLEN; //第一次赋值skb_store_bytes(skb, l3_off + offsetof(struct iphdr, saddr), &new_saddr, 4, 0); //skb被操作了 因而ip4的值不可信,此时如果操作ip4会被回绝ip4 = (struct iphdr *) skb->data + ETH_HLEN; //再获取一次if (ip4->protocol == IPPROTO_TCP) { //能力失常应用 // do something}
0x3:常见报错
- R2 min value is negative, either use unsigned or 'var &= const'
第二个变量须要保障非负。 逻辑运算0xFFFFFFFF。
R2 unbounded memory access, use 'var &= const' or 'if (var < const)'
bpf验证器有限度 #define BPF_MAX_VAR_SIZ (1 << 29)if (reg->umax_value >= BPF_MAX_VAR_SIZ) { verbose(env, "R%d unbounded memory access, use 'var &= const' or 'if (var < const)'\n", regno); return -EACCES;}
invalid stack type R1 off=-72 access_size=536870911
相似的问题,须要进行逻辑运算保障变量的范畴。off = reg->off + reg->var_off.value;if (off >= 0 || off < -MAX_BPF_STACK || off + access_size > 0 || access_size < 0 || (access_size == 0 && !zero_size_allowed)) { verbose(env, "invalid stack type R%d off=%d access_size=%d\n", regno, off, access_size); return -EACCES;}
- 从map中lookup进去的指针,不能间接update回去,在eBPF代码中更新值之后不再须要从新update,因为拿到了援用.
- 字符串拷贝能够应用编译器内置的 __builtin_memcpy
- 一个bpf程序不能申请太多的栈空间,目前限度512Byte,多了就会报错:Looks like the BPF stack limit of 512 bytes is exceeded.。例如在程序中申请了两个数组char arr1[256];char arr2[256];程序就会报错了
程序蕴含无奈执行到的指令
unreachable insn 1
程序读取未初始化的寄存器
0: (bf) r0 = r2R2 !read_ok
程序退出前未设置 R0 寄存器
0: (bf) r2 = r11: (95) exitR0 !read_ok
程序拜访超出栈空间
0: (7a) *(u64 *)(r10 +8) = 0invalid stack off=8 size=8
未初始化栈内元素,就传递该栈地址
0: (bf) r2 = r101: (07) r2 += -82: (b7) r1 = 0x03: (85) call 1invalid indirect read from stack off -8+0 size 8
程序未查看 map_lookup_elem() 的返回值是否为空就开始应用
0: (7a) *(u64 *)(r10 -8) = 01: (bf) r2 = r102: (07) r2 += -83: (b7) r1 = 0x04: (85) call 15: (7a) *(u64 *)(r0 +0) = 0R0 invalid mem access 'map_value_or_null'
本文由博客一文多发平台 OpenWrite 公布!