- 论坛徽章:
- 0
|
由于工作需要,这两天在学习《Linux内核情景分析》里文件系统部分的章节,看到通过mount安装文件系统的时候,本来是对
copy_mount_options()这个函数中的两句代码不理解,结果在google上却查到了一片相关的文章,如下,指出了其中一个潜在的可以使
kernel崩溃的bug:
I have experienced rare kernel crashs when
mounting a filesystem with busybox-mount. After
digging deeper into the matter, i found out the
following:
Bug Analysis
============
In file linux-2.4.x/fs/namespace.c in
function copy_mount_options(), you can read
----- 8 PAGE_SIZE)
size = PAGE_SIZE;
i = size - copy_from_user((void *)page, data, size);
----- >8 -----
where TASK_SIZE is defined as 0xf0000000.
In this case, "data" will be always located in physical
RAM (i.e. ranging from i.e. 0x0 to 0x3fffff on an MCF5272C3
board). Unless you have 3.75 GByte of physical RAM :-), it is
quite obvious that
size = TASK_SIZE - (unsigned long)data
while always be bigger than PAGE_SIZE, finaly resulting in
size = PAGE_SIZE
Means, whereever "data" is stored, you will have to ensure
that at least 4096 bytes are subsequently readable from
this location.
So far, so good, but when now looking at file
user/busybox/mount.c in function mount_one(),
you can read
----- 88 -----
where "buf" will be equal to the location of "data" described above.
Means: "buf/data" is allocated somewhere on the task stack.
When the stack accidently gets allocated at the
last page(s) of the physical ram (i.e. at the top of 4MB), then
there is a good chance that "buf/data" equals something like 0x3fffa0.
Consequence: copy_mount_options() tries to copy the area
from 0x3fffa0 to 0x400f9f (with memcpy), and this doesn't work
on MCF5272, because the kernel segfaults when trying
to access the non-mapped memory regions beyond 0x3fffff.
Solutions
=========
One solution would be to change the line
size = TASK_SIZE - (unsigned long)data;
in copy_mount_options() in linux-2.4.x/fs/namespace.c to
somewhat like
size = "END_OF_PHYSICAL_MEMORY" - (unsigned long)data;
But i don't know how to determine "END_OF_PHYSICAL_MEMORY"
for all platforms. Maybe you know it and can tell me :-)
The other solution is to introduce a statically allocated
buffer of 4096 bytes to bb-mount rather than
the stack-allocated 255 bytes buffer (see patch attached).
this is IMHO not the best solution, because the
kernel-bug still remains!
best regards
Bernhard
--
Bernhard Kuhn, Software Engineer, Lineo Inc. (Where Open Meets Smart)
--- mount.c.orig Mon Jan 14 03:17:25 2002
+++ mount.c Mon Jan 14 03:07:23 2002
@@ -233,6 +233,9 @@
}
}
+
+static char fstbuf[4096];
+
static int
mount_one(char *blockDevice, char *directory, char *filesystemType,
unsigned long flags, char *string_flags, int useMtab, int fakeIt,
@@ -244,10 +247,9 @@
static const char *noauto_array[] = { "tmpfs", "shm", "proc", "ramfs", "devpts", "devfs", 0 };
const char **noauto_fstype;
const int num_of_filesystems = sysfs(3, 0, 0);
- char buf[255];
int i=0;
- filesystemType=buf;
+ filesystemType=fstbuf;
while(i bkuhn@lineo.com[/email]
)
上边的大概意思是说, 在copy_mount_option()代码中的
size = TASK_SIZE - (unsigned long)data
这一句, 在特殊的情况下可能会使内存访问越界,而导致系统崩溃, 我看了一下,这个问题确实很有可能发生,尤其是在嵌入式的环境下.可根据上文中提到的方法修改一下,我准备选择第一种.
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u/6609/showart_102498.html |
|