Binaries linked with bionic libc require /dev/null to be present,
otherwise they will crash before entering "main", as explained
in https://landley.net/toybox/faq.html#cross3 .
So we should put /dev/null to initramfs, but this is impossible
if we create initramfs using "cpio" and we are running as normal
user.
This problem can be solved by using gen_init_cpio.
But let's make sure instead that /dev/null is always available as
a quality-of-implementation feature. This will reduce number
of failure modes and will make it easier for developers to
get early boot right. (Early boot issues are very hard to debug.)
Signed-off-by: Askar Safin <safinaskar@gmail.com>
---
init/do_mounts.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/init/do_mounts.c b/init/do_mounts.c
index f911280a348e..3e71049b3dcf 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -525,5 +525,8 @@ void __init create_basic_rootfs(void)
WARN_ON_ONCE(init_mkdir("/dev", 0755) != 0);
WARN_ON_ONCE(init_mknod("/dev/console", S_IFCHR | 0600,
new_encode_dev(MKDEV(5, 1))) != 0);
+ WARN_ON_ONCE(init_mknod("/dev/null", S_IFCHR,
+ new_encode_dev(MKDEV(1, 3))) != 0);
+ WARN_ON_ONCE(init_chmod("/dev/null", 0666) != 0);
WARN_ON_ONCE(init_mkdir("/root", 0700) != 0);
}
--
2.47.3
On 2/19/26 15:03, Askar Safin wrote: > Binaries linked with bionic libc require /dev/null to be present, Elliott fixed that one back in 2021: http://lists.landley.net/pipermail/toybox-landley.net/2021-October/028766.html https://android-review.googlesource.com/c/platform/bionic/+/1869594 Are you saying it's reoccurred, or that you plan to run a 5 year old userspace with a current kernel? > otherwise they will crash before entering "main", as explained > in https://landley.net/toybox/faq.html#cross3 . Oops, my documentation is out of date. Sorry. Added to the todo heap. (Although I can't say I've regression tested an init task statically linked against bionic launching itself in an empty chroot recently either. last I checked I still hadn't convinced the android guys to use initramfs at all, and then they had those 12k layoffs (apparently copying twitter's mass layoffs) and I largely gave up on the idea of turning Android into a self-hosting development environment any time soon.) > So we should put /dev/null to initramfs, but this is impossible > if we create initramfs using "cpio" and we are running as normal > user. You could just automount devtmpfs using the existing plumbing (and touching far fewer files, and having common behavior between the static and initrd loader codepaths). I've been using this trick since 2015: https://landley.net/notes-2015.html#01-01-2015 And first submitted it to linux-kernel in 2016: https://lkml.org/lkml/2016/6/22/686 And resubmitted a half-dozen times since then. I linked to my most recent one (tested against 6.17) last message, it's generally at https://landley.net/bin/mkroot/latest/linux-patches/ Debian had a bug back in something like 2017 (when its initramfs script's attempt to mount devtmpfs on /dev failed -- because it was already there -- the untested error path would rm -rf everything) but they said they were fixing it ~8 years ago, so... I added workarounds to my reposts for a while (so new kernels could work with old debians): https://lkml.org/lkml/2020/5/14/1584 I don't remember if there's a newer post to this list than https://lkml.iu.edu/2201.2/00174.html but nobody else ever seemed to care. Oh well. I've posted new ones on my website every mkroot release, regression tested against the then-current kernel. It would be great if I didn't have to worry about https://github.com/landley/toybox/commit/0b2d5c2bb3f1 again, but special case code instead of using an existing generic mechanism? Eh, I suppose that _is_ the modern Linux way... Rob
On Mon, Feb 23, 2026 at 4:15 AM Rob Landley <rob@landley.net> wrote: > Are you saying it's reoccurred, or that you plan to run a 5 year old > userspace with a current kernel? I was not aware about this. Okay, I agree that /dev/null is not needed. > (Although I can't say I've regression tested an init task statically > linked against bionic launching itself in an empty chroot recently > either. I tested current Android NDK LTS. I found that if stdin/stdout/stderr already opened, then bionic binary will not crash if /dev/null is absent. It will not crash even if PID is not 1 (so chroot should work). But I didn't test what happens if stdin/stdout/stderr are closed. So, assuming you already somehow got /dev/console, then /dev/null is not needed. According to code, bionic binary should work even if stdin/stdout/stderr are closed, assuming that PID is 1. -- Askar Safin
On Thu, 19 Feb 2026 21:03:12 +0000, Askar Safin wrote: > Binaries linked with bionic libc require /dev/null to be present, > otherwise they will crash before entering "main", as explained > in https://landley.net/toybox/faq.html#cross3 . It looks as though Bionic has extra logic to handle missing /dev/null during early boot, although it's dependent on !is_AT_SECURE: https://cs.android.com/android/platform/superproject/main/+/main:bionic/libc/bionic/libc_init_common.cpp;drc=a7637a8f06f103c53d61a400a6b66f48f2da32be;l=400 I think this would be better addressed via documentation (e.g. in Bionic or ramfs-rootfs-initramfs.rst). Thanks, David
David Disseldorp <ddiss@suse.de>: > It looks as though Bionic has extra logic to handle missing /dev/null > during early boot, although it's dependent on !is_AT_SECURE: > https://cs.android.com/android/platform/superproject/main/+/main:bionic/libc/bionic/libc_init_common.cpp;drc=a7637a8f06f103c53d61a400a6b66f48f2da32be;l=400 > > I think this would be better addressed via documentation (e.g. in Bionic > or ramfs-rootfs-initramfs.rst). Okay, I see, current bionic behavior is good. Okay, I agree that this /dev/null patch is not necessary. -- Askar Safin
© 2016 - 2026 Red Hat, Inc.