Due to work needs I've expanded kernel version string and length of it from 64 to 128 characters to add build date, commit info and some other important for our work info. Kernel version is 3.4.112 with few device specific modifications. After that kernel fails to load at the end of booting with kernel panic:
[ 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)
I've changed kernel source code in following places:
--- 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; \
and
--- 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];
};
and
--- 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;
With printk
debugging I've founded code which causes kernel panic - it is piece of ASM code from arch/arm/kernel/sys_arm.c
:
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");
I'm not very familiar with ASM and with kernel programming, so I 'll be very thankful for help.
You made init
segfault by breaking the kernel / user ABI for the uname(2)
system call (by changing the struct size/layout).
Its exit code of 0xb is 11, which is the signal number for SIGSEGV. Attempted to kill init!
was the cause of the panic, not a symptom or side-effect.
As @RossRidge said in a comment:
The 1024 number for
_UTSNAME_LENGTH
is only used for the stub implementation ofuname
for systems that don't support this system call. You'll need to rebuild glibc using your modified Linux kernel headers and then rebuild the init you're using with this custom version of glibc.
Dmitry confirms that changing _UTSNAME_LENGTH
from 65 to 129 in
glibc-2.11.3/sysdeps/unix/sysv/linux/bits/utsname.h
solved the problem, after rebuilding the root fs.
A less-hacky general solution is to really rebuild glibc against the updated kernel headers.
User contributions licensed under CC BY-SA 3.0