[PATCH 2/2] init: ensure that /dev/null is (nearly) always available in initramfs

Askar Safin posted 2 patches 1 month, 1 week ago
[PATCH 2/2] init: ensure that /dev/null is (nearly) always available in initramfs
Posted by Askar Safin 1 month, 1 week ago
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
Re: [PATCH 2/2] init: ensure that /dev/null is (nearly) always available in initramfs
Posted by Rob Landley 1 month, 1 week ago
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
Re: [PATCH 2/2] init: ensure that /dev/null is (nearly) always available in initramfs
Posted by Askar Safin 1 month, 1 week ago
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
Re: [PATCH 2/2] init: ensure that /dev/null is (nearly) always available in initramfs
Posted by David Disseldorp 1 month, 1 week ago
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
Re: [PATCH 2/2] init: ensure that /dev/null is (nearly) always available in initramfs
Posted by Askar Safin 1 month, 1 week ago
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