[FAQ18285]如何用MMU保护slub?
来源:互联网 发布:java写界面 编辑:程序博客网 时间:2024/05/14 09:13
[DESCRIPTION]
看过[FAQ14614]如何用MMU保护buddy system?就知道如果踩到空洞就会直接崩溃,是检测和解决问题的最好方法,不过踩坏不一定就落在空洞,这也导致了调试难度。
在quick start里有专题讲解踩内存问题:
- MediaTek On-Line> Quick Start> 踩内存专题分析
kernel里大范围使用的是slub,如果slub被踩坏,不一定会落在空洞。有没有将slub隔离开来呢?如果可以,那么slub踩坏被抓到的机会就更大了。
对于32位kernel来说,不太可能了,因为4G虚拟空间,kernel占1G,能用的实在太小了。而对于64位kernel来说,512G的虚拟空间,足够我们保护slub。下面讲解方法。
[SOLUTION]
只应用于64bit kernel
1. 在slub找buddy system申请内存后,将page映射到隔离的地址上:
[C/C++]hide
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <linux/vmalloc.h> /* 添加这个头文件 */
static
struct
page *allocate_slab(
struct
kmem_cache *s, gfp_t flags,
int
node)
{
......
if
(flags&__GFP_WAIT) {
/* 添加如下代码 */
if
(page) {
const
int
num = 1 << oo_order(oo);
struct
vm_struct tmp_area;
struct
page *pages[num];
int
i;
//extern int set_memory_invalid(unsigned long addr, int numpages);
//set_memory_invalid((unsigned long)lowmem_page_address(page), num); /* 如果有开启MMU保护buddy system([FAQ14614]如何用MMU保护buddy system?),则添加这行代码!!! */
__SetPagePrivate(page);
__SetPageSlab(page);
tmp_area.addr = page_address(page);
tmp_area.size = num * PAGE_SIZE + PAGE_SIZE;
for
(i = 0; i < num; i++) {
pages[i] = &page[i];
}
map_vm_area(&tmp_area, PAGE_KERNEL, pages);
}
/* 添加结束 */
local_irq_disable();
}
if
(!page)
return
NULL;
......
}
2. slub释放内存归还给buddy system时,需要撤销映射:
[C/C++]hide
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
static
void
__free_slab(
struct
kmem_cache *s,
struct
page *page)
{
......
mod_zone_page_state(page_zone(page), (s->flags & SLAB_RECLAIM_ACCOUNT) ? NR_SLAB_RECLAIMABLE : NR_SLAB_UNRECLAIMABLE, -pages);
/* 添加如下代码 */
if
(PagePrivate(page)) {
unmap_kernel_range((unsigned
long
)page_address(page), (1 << order) * PAGE_SIZE);
ClearPagePrivate(page);
}
/* 添加结束 */
__ClearPageSlabPfmemalloc(page);
__ClearPageSlab(page);
......
}
3. slub.c里定义__phys_to_virt(),完成slub隔离:
[C/C++]hide
1
2
3
4
5
6
7
8
9
10
11
12
13
unsigned
long
__phys_to_virt(phys_addr_t phys)
{
if
(slab_is_available() && (compound_head(phys_to_page(phys))->flags&((1UL << PG_slab)|(1UL << PG_private))) == ((1UL << PG_slab)|(1UL << PG_private))) {
return
(unsigned
long
)(phys - PHYS_OFFSET + PAGE_OFFSET)|SLUB_ADDR_FLAG;
}
return
(unsigned
long
)(phys - PHYS_OFFSET + PAGE_OFFSET);
}
4. kernel-3.18/arch/arm64/include/asm/memory.h调整__virt_to_phys():
[C/C++]hide
1
2
3
#define __virt_to_phys(x) (((phys_addr_t)(x) - PAGE_OFFSET + PHYS_OFFSET))
#define __phys_to_virt(x) ((unsigned long)((x) - PHYS_OFFSET + PAGE_OFFSET))
修改为:
[C/C++]hide
1
2
3
4
5
6
7
8
9
10
11
#define SLUB_ADDR_FLAG 0x400000000UL /* 8G shift */
#define __virt_to_phys(x) (((phys_addr_t)(x)&~SLUB_ADDR_FLAG) - PAGE_OFFSET + PHYS_OFFSET)
#ifndef __ASSEMBLY__
unsigned
long
__phys_to_virt(phys_addr_t phys);
#endif
特征:
- 从slub申请的内存(kmalloc等)地址大于0xffffffc400000000。
- 0xffffffc400000000起始的内存和0xffffffc000000000的内存映射的是同一物理地址。
- 只有slub从buddy system申请的内存才会映射到0xffffffc400000000起始的内存。
0 0
- [FAQ18285]如何用MMU保护slub?
- [FAQ14614]如何用MMU保护buddy system?
- [FAQ19108]如何用MMU增强保护buddy system?
- 如何用代码对Excel的指定区域实行保护
- 人在江湖:如何用代码保护好自己
- 如何用DLL最简单地保护您的工程代码
- Linux:多进程访问同一文件,如何用文件锁进行保护, fcntl()详解
- 如何用2.0发信?
- 想知道socket如何用
- 如何用英语杀价?
- 如何用C画图
- 问如何用文件
- 如何用JSP编程
- 如何用PS切图
- ssl如何用
- 如何用FreeType写字
- 如何用计算机发财
- 如何用JAVA 对象?
- CSS制作加盟表(课后4)
- ubuntu中mysql5.7表名区分大小写解决方案
- [小技巧] cat /proc/modules 显示的地址为 0
- 下载youtube视频
- Cloudera NTP 配置
- [FAQ18285]如何用MMU保护slub?
- ART运行时垃圾收集(GC)过程分析
- 餐厅广告代码
- 创建和销毁对象 第二条:遇到多个构造器参数时要考虑用建构器
- Kotlin - 运算符重载
- [iOS 读取Txt] 从文件读取数据并做轮询
- 新手教你学Spring MVC4.0+MyBatis+MySQL5.0实现简单用户注册登录程序(二)
- HTML 第4章 课后4
- Py第十问 Django使用问题集