由于工作需要,我将内核版本字符串及其长度从64个字符扩展到了128个字符,以添加构建日期,提交信息和一些其他对我们工作信息很重要的信息。内核版本为3.4.112,仅对设备进行了一些修改。此后,在内核崩溃的引导结束时,内核无法加载:
[ 38.181594] IP-Config: Complete:
[ 38.184853] device=eth0, addr=192.168.7.2, mask=255.255.248.0, gw=255.255.255.255
[ 38.192849] host=192.168.7.2, domain=, nis-domain=(none)
[ 38.198636] bootserver=192.168.3.12, rootserver=192.168.3.12, rootpath=
[ 38.206047]
[ 38.207554] initramfs file system not in use. details in main.c
[ 38.215749] VFS: Mounted root (ext2 filesystem) readonly on device 31:2.
[ 38.227813] Freeing init memory: 140K
[ 38.370775] mv643xx_eth_port mv643xx_eth_port.0: eth0: link up, 1000 Mb/s, full duplex, flow control disabled
[ 38.429568] Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
[ 38.429581]
[ 38.438796] [<c000dfc4>] (unwind_backtrace+0x0/0x108) from [<c03412cc>] (panic+0x9c/0x1f8)
[ 38.447126] [<c03412cc>] (panic+0x9c/0x1f8) from [<c005f940>] (do_exit+0x7ec/0x818)
[ 38.454836] [<c005f940>] (do_exit+0x7ec/0x818) from [<c005f9b4>] (do_group_exit+0x48/0xd8)
[ 38.463161] [<c005f9b4>] (do_group_exit+0x48/0xd8) from [<c006c4b0>] (get_signal_to_deliver+0x344/0x5d4)
[ 38.472705] [<c006c4b0>] (get_signal_to_deliver+0x344/0x5d4) from [<c000b154>] (do_notify_resume+0x88/0x520)
[ 38.482599] [<c000b154>] (do_notify_resume+0x88/0x520) from [<c0009014>] (work_pending+0x24/0x28)
我在以下位置更改了内核源代码:
--- a/apps/linux-3.4/src/Makefile
+++ b/apps/linux-3.4/src/Makefile
@@ -995,7 +995,7 @@ prepare: prepare0
# KERNELRELEASE can change from a few different places, meaning version.h
# needs to be updated, so this check is forced on all builds
-uts_len := 64
+uts_len := 128
define filechk_utsrelease.h
if [ `echo -n "$(KERNELRELEASE)" | wc -c ` -gt $(uts_len) ]; then \
echo '"$(KERNELRELEASE)" exceeds $(uts_len) characters' >&2; \
和
--- a/apps/linux-3.4/src/include/linux/utsname.h
+++ b/apps/linux-3.4/src/include/linux/utsname.h
@@ -11,14 +11,15 @@ struct oldold_utsname {
char machine[9];
};
+#define __OLD_UTS_LEN 128
-#define __NEW_UTS_LEN 64
+#define __NEW_UTS_LEN 128
struct old_utsname {
- char sysname[65];
- char nodename[65];
- char release[65];
- char version[65];
- char machine[65];
+ char sysname[__OLD_UTS_LEN + 1];
+ char nodename[__OLD_UTS_LEN + 1];
+ char release[__OLD_UTS_LEN + 1];
+ char version[__OLD_UTS_LEN + 1];
+ char machine[__OLD_UTS_LEN + 1];
};
和
--- a/apps/linux-3.4/src/kernel/sys.c
+++ b/apps/linux-3.4/src/kernel/sys.c
@@ -1210,7 +1210,7 @@ static int override_release(char __user *release, size_t len)
if (current->personality & UNAME26) {
const char *rest = UTS_RELEASE;
- char buf[65] = { 0 };
+ char buf[__NEW_UTS_LEN + 1] = { 0 };
int ndots = 0;
unsigned v;
size_t copy;
通过printk
调试,我建立了引起内核恐慌的代码-它是arch/arm/kernel/sys_arm.c
中的ASM代码:
asm( "add r0, %0, %1\n\t"
"mov r1, %2\n\t"
"mov r2, %3\n\t"
"bl memmove\n\t" /* copy regs to top of stack */
"mov r8, #0\n\t" /* not a syscall */
"mov r9, %0\n\t" /* thread structure */
"mov sp, r0\n\t" /* reposition stack pointer */
"b ret_to_user"
:
: "r" (current_thread_info()),
"Ir" (THREAD_START_SP - sizeof(regs)),
"r" (®s),
"Ir" (sizeof(regs))
: "r0", "r1", "r2", "r3", "r8", "r9", "ip", "lr", "memory");
我对ASM和内核编程不是很熟悉,因此非常感谢您的帮助。
答案 0 :(得分:3)
您通过中断init
系统调用的内核/用户ABI(通过更改结构大小/布局)来进行uname(2)
段错误。
其退出代码0xb为11,这是SIGSEGV的信号编号。 Attempted to kill init!
是引起恐慌的原因,而不是症状或副作用。
@RossRidge说in a comment:
_UTSNAME_LENGTH
的1024数字仅用于uname
的存根实现,用于不支持此系统调用的系统。您需要使用修改后的Linux内核标头重建glibc,然后使用此自定义版本的glibc重建正在使用的init。
Dmitry确认将_UTSNAME_LENGTH
从65更改为129
glibc-2.11.3/sysdeps/unix/sysv/linux/bits/utsname.h
在重建根fs之后解决了该问题。
一种比较宽松的通用解决方案是针对更新后的内核标头真正重建glibc。