标题:
内核相关问题:kill init和内核结构的释放(2)
[打印本页]
作者:
yuyang911220
时间:
2017-6-7 10:25
标题:
内核相关问题:kill init和内核结构的释放(2)
仅此而已,操作task_struct的字段了吗?没有,实际上 task_struct还是那个task_struct,一点没变,内核要想取该task_struct的某个字段,照取不误,还是原来的地址(内核的前 896m与物理内存一一对应),只是操作了slab的指针。因此进程依旧完好运行,那为何一旦ps就崩溃了呢?或者ls也崩溃。我们知道,你执行ps或 ls以及任何一个命令的时候,shell都要fork出一个新进程,而fork要分配一个task_struct,该task_struct当然在 slab分配,我们看看分配代码:
static
inline
void
* __cache_alloc (kmem_cache_t *cachep,
int
flags)
{
unsigned
long
save_flags;
void
* objp;
struct
array_cache *ac;
cache_alloc_debugcheck_before(cachep, flags);
local_irq_save(save_flags);
ac = ac_data(cachep);
if
(likely(ac->avail)) {
STATS_INC_ALLOCHIT(cachep);
ac->touched = 1;
objp = ac_entry(ac)[--ac->avail];
}
else
{
STATS_INC_ALLOCMISS(cachep);
objp = cache_alloc_refill(cachep, flags);
}
local_irq_restore(save_flags);
objp = cache_alloc_debugcheck_after(cachep, flags, objp, __builtin_return_address(0));
return
objp;
}
看看这个--ac->avail,再对 比一下前面释放时的ac->avail++,这里最新分配的task_struct就是最新被释放的task_struct,而这个 task_struct就是那个我的模块中被变态释放的task_struct了,于是新进程一产生,原来的被释放的进程的task_struct的所有 字段几乎都要被重置,如果我敲入了ps,那么那个while循环进程的task_struct将和ps的task_struct一样,因此乱套崩溃在情理 之中,为何乱套?最简单的例子,内核要调度while,切出while循环,但是他们的task_struct一样,如果你是内核你该咋办,绝对崩溃,要 你放下一个桔子拿起另一个桔子,而这两个桔子是一个桔子,你难道不崩溃吗?呵呵。
因此,我认为因该在slab对象初始化时只初始化公共部分,只要释放一个slab对象到slab中,那么就把非公共部分清零,这样才安全,把一切清零,不 要什么工公共部分更安全,当然这样slab的ctor构造函数也就没有必要了,不过这样的效率会小低一些,仅仅小低一些。还是为了简单,我写下如下模块, 释放后随即将整个结构清零,不保留任何公共部分:
#include <linux/init.h>
#include <linux/module.h>
static
__init
int
test_init(
void
)
{
task_t *task=find_task_by_pid(1824);
free_task(task);
memset(task,0,
sizeof
(task_t));
//将task_struct清零,实际上就是将其内部的字段清零,包括指针变量,由此消除了野指针
return
0;
}
static
__exit
void
test_exit(
void
)
{
return
;
}
module_init(test_init);
module_exit(test_exit);
MODULE_LICENSE(
"Dual BSD/GPL"
);
MODULE_AUTHOR(
"Zhaoya"
);
MODULE_DESCRIPTION(
"zero task"
);
MODULE_VERSION(
"Ver 0.1"
);
还 是以上面的while循环作试验,加载模块后,内核立即崩溃,达到了目的。但是内核是怎么崩溃的呢?很简单,典型的有两个时机,一个是时钟中断,一个是调 度,当然还有别的很多,只是这两个更具有典型性,在这两个时机场景的处理时候会用到current,而它就是被释放那的task_struct,字段全是 0,这样很容易就崩溃了,可能访问了0指针也就是空指针,也可能是别的。在应用程序设计时,我们大谈特谈野指针的危害,内核中也要关注它,不过不必像用户 空间那么过分关注它,毕竟内核中做的事情应该形成一种约定,这样就不用浪费资源去验证这验证那了,内核做的事情要少而有效,最重要的是保证安全。
task_struct来自slab,而slab有ctor构造函数和dtor析构函数,dtor我们想想实际上是没有什么用的,于是在最新的内核中就去掉了,不再为slab对象提供析构函数了(参考slub)。
欢迎光临 电子技术论坛_中国专业的电子工程师学习交流社区-中电网技术论坛 (http://bbs.eccn.com/)
Powered by Discuz! 7.0.0