目录
问题来源:恶意程序检测
最近,主要由于在研讨一些关于LINUX被恶意程序ROOT后,可能会被修改代码段中的数据。为了防止代码段被修改,采用几种特殊的机制来保护代码段的数据不被篡改,当有恶意程序试图修改代码段或只读数据段中的数据,特殊保护机制会自动忽略这种恶意操作,并追溯该操作的PC地址,栈指针,进程号等,从而找到恶意程序的源头,从而处理恶意程序。
问题就是来源这种特殊的保护机制启动后,当安装一些官方验证后的APK后,我们发现保护机制居然真的报警了,这意味着有程序在修改代码段。起初我们怀疑该APK自带ROOT工具,但是后来通过特殊机制进行回追出错的地址,回溯栈指针,发现是由于LINUX系统引入了Static_Keys机制,该机制中的部分函数的实现利用了代码段修改来实现的,而不是每次都是通过变量判断,从而直接改变代码段。而修改代码段的工作就交给了一个函数就是DO_ONCE中的__do_once_done中,那么我们就先来分析一下代码。
DO_ONCE函数解析
DO_ONCE机制想法很简单,有些函数只应该调用一次,那么这些函数调用一次后,如果下次再调用就应该直接返回。以前我们要实现这种功能总是需要判断一个变量,而使用DO_ONCE机制,自动帮你完成判断,保证函数只会在第一次调用的时候被执行,以后都直接返回。很自然,DO_ONCE机制就采用了Static_Keys来实现。使用static_key外 ,另一个关键在__do_once_done中。
#define DO_ONCE(func, ...) \
({ \
bool ___ret = false; \
static bool ___done = false; \
static DEFINE_STATIC_KEY_TRUE(___once_key); \
if (static_branch_unlikely(&___once_key)) { \
unsigned long ___flags; \
___ret = __do_once_start(&___done, &___flags); \
if (unlikely(___ret)) { \
func(__VA_ARGS__); \
__do_once_done(&___done, &___once_key, \
&___flags); \
} \
} \
___ret; \
})
如果有一个func只能被调用一次,例如初始化函数的话,则可以用这个宏,如下例所示foo这个函数即使被调用两次,也只会运行一次:
/* Call a function exactly once. The idea of DO_ONCE() is to perform
* a function call such as initialization of random seeds, etc, only
* once, where DO_ONCE() can live in the fast-path. After @func has
* been called with the passed arguments, the static key will patch
* out the condition into a nop. DO_ONCE() guaran