linux pid1 init in golang panic

119 views
Skip to first unread message

Hannes Stauss

unread,
Feb 17, 2025, 1:53:06 PM2/17/25
to golang-nuts
Dear
I have an empty go program that I would like to run as pid1 from the initramfs embedded into the kernel after the linux kernel booted (a real init would for sure do more than just looping forever):
package main

func main() {
for {
}
}


Any ideas where to follow to narrow down the issue? Many thanks in advance.

I can get it running without panic when I call the go program from a c program that first mounts dev filesystem:
int main()
{
// Mount the devtmpfs filesystem to /dev
mount("devtmpfs", "/dev", "devtmpfs", 0, NULL);

// run the main program
execl("/main", "/main", (char *)NULL);
exit(EXIT_FAILURE);
}

When calling the go program without first mounting dev filesystem I get again a kernel panic.

I seems the go runtime somehow needs a mounted dev filesystem in order to initialize properly.

My test platform is aarch64 running in qemu with following command:
qemu-system-aarch64 \
-machine virt \
-cpu cortex-a57 \
-smp 2 -m 2048 \
-kernel linux/arch/arm64/boot/Image \
-append "console=ttyAMA0" \
-nographic


Axel Wagner

unread,
Feb 17, 2025, 2:14:05 PM2/17/25
to Hannes Stauss, golang-nuts
I would recommend looking at what gokrazy does:
I believe the entrypoint of their pid1 is this generated Go code:
You might use that to see what kinds of initialization it does to cooperate with the kernel.

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/896b8411-77e5-4741-b283-5d401286e820n%40googlegroups.com.

Hannes Stauss

unread,
Feb 17, 2025, 7:28:47 PM2/17/25
to golang-nuts
Thank you Axel for the pointer, very interesting project :-)

It turned out that when in Kconfig automounting of devtmpfs is configured this would not apply for the initramfs, i.e., devtmpfs is not mounted in initramfs automatically. kernel_init in init/main.c of kernel code calls kernel_init_freeable calls console_on_rootfs to setup stdio. When the /dev/console node is missing in initramfs, console_on_rootfs cannot open /dev/console and hence does not open stdio files 0, 1, 2. 

It seems the go runtime exits with an error code when stdio is not open, however, I do not have exact evidence for that yet. Anyway, the go program terminates for any reason and when it does, the kernel eventually panics - init must not return.

The fix is not to rely on automounting of devtmpfs but creating the required device nodes in the initramfs setup manually (see also https://www.kernel.org/doc/Documentation/filesystems/ramfs-rootfs-initramfs.txt) . 

On the other hand it can be questioned if the go runtime should exit when stdio is not open because it could easily be opened and correctly redirected in main.
Reply all
Reply to author
Forward
0 new messages