- 论坛徽章:
- 0
|
5可用积分
自己写的网卡驱动代码里,总有一些skb越界操作的问题。
skb是slab分配出来的,所以给内核配置了CONFIG_DEBUG_SLAB,
但是这个选项只是给slab对象的前后加了红区(red zone),以及在刚分配slab对象前,将其poison,
这两个方案都只能检查事后内存被改的情况。
为了抓到第一现场,封装了string.c里的类C库接口。
以memcpy为例,假设驱动代码里有一句memcpy(dest,src,len), 那么就会检测区间
[dest,dest+len] 是否覆盖掉了别人的slab对象区间。
场景:假设系统中此时通过slab分配出来的对象集合有:
[a1,b1] [a2,b2] ... [an,bn]
检测越界时,如果发现[dest,dest+len] 与 [ai,bi]有重叠,并且不是[ai,bi]的子区间,那说明[dest,dest+len]这次memcpy是一次非法的越界拷贝。
即满足(dest <ai )&& (dest+len >ai) && (dest+len <bi] (前重叠)
(dest >ai) && (dest <bi ) && (dest +len >bi) (后重叠)
就是一次越界memcpy。
|ai----------------------------------bi| //某个slab对象区间
|dest-----------dest+len| //前重叠
|dest-------------------------dest+len| //后重叠
slab对象区间,以ai(对象虚拟地址)为主key、bi为辅助信息,保存在红黑树中;
每次memcpy时,以dest为key去查找红黑树里大于dest的第一个节点,再判断dest_len是否小于bi,有的话就是前覆盖;
如果没有,则再以dest为key去查找红黑树里小于dest的第一个节点,再判断dest_len是否大于bi,有的话就是后覆盖。
因此最坏情况下,可能要遍历两次红黑树才能判断是否存在越界。
当系统处于高负载时,有大量slab对象的分配和释放,这个检测机制运行起来后系统非常慢。
再加上红黑树可能有许多的树旋转操作,导致比较耗时。
从上面的流程可以看出,如果通过一次搜索,能找到大于dest和小于dest的两个节点,那么效率就会提升一倍。
不知道哪种结构可以满足不? 大家有没有其他的方案和思路可以逮到越界第一现场?
|
|