All of lore.kernel.org
 help / color / mirror / Atom feed
* [Buildroot] [git commit] fs/cpio/init: unbreak ttyname_r() on glibc after dropping /dev/console exec
@ 2020-08-29 14:32 Yann E. MORIN
  0 siblings, 0 replies; only message in thread
From: Yann E. MORIN @ 2020-08-29 14:32 UTC (permalink / raw)
  To: buildroot

commit: https://git.buildroot.net/buildroot/commit/?id=b9026e83f9c7610526f045f2fc1135b45a26305f
branch: https://git.buildroot.net/buildroot/commit/?id=refs/heads/master

Commit 98a6f1fc02e41 (fs/cpio: make initramfs init script survive 'console='
kernel argument) dropped the explicit /dev/console execs for fd 0,1,2, as
they fail when booted with console= and aren't really needed as the kernel
will setup fd 0,1,2 from /dev/console before executing the initramfs anyway.

Not doing this unfortunately confuses glibc's ttyname_r(3) implementation
(used by E.G.  busybox/coreutils 'tty'), causing it to fail with ENOENT as
it does a fstat on fd 0 and tries to match up st_ino / st_dev against the
entries in /dev (since glibc 2.26):

 commit 15e9a4f378c8607c2ae1aa465436af4321db0e23
 Author: Christian Brauner <christian.brauner@canonical.com>
 Date:   Fri Jan 27 15:59:59 2017 +0100

    linux ttyname and ttyname_r: do not return wrong results

    If a link (say /proc/self/fd/0) pointing to a device, say /dev/pts/2, in a
    parent mount namespace is passed to ttyname, and a /dev/pts/2 exists (in a
    different devpts) in the current namespace, then it returns /dev/pts/2.
    But /dev/pts/2 is NOT the current tty, it is a different file and device.

    Detect this case and return ENODEV.  Userspace can choose to take this as a hint
    that the fd points to a tty device but to act on the fd rather than the link.

    Signed-off-by: Serge Hallyn <serge@hallyn.com>
    Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>

The reason it fails is that we manually mount devtmpfs on /dev in /init, so
the /dev/console used by the kernel (in rootfs) is not the same file as
/dev/console at runtime (in devtmpfs).

Notice: Once logged in, tty does work correctly.  Presumably login reopens
stdin/stdout/stderr.

To fix this, re-add the exec of /dev/console for fd 0,1,2, but only do so if
possible.  Because of the above mentioned shell behaviour (specified by
POSIX [0]), perform this check in a subshell.

[0] https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_20_01

Signed-off-by: Peter Korsgaard <peter@korsgaard.com>
Signed-off-by: Yann E. MORIN <yann.morin.1998@free.fr>
---
 fs/cpio/init | 11 +++++++++++
 1 file changed, 11 insertions(+)

diff --git a/fs/cpio/init b/fs/cpio/init
index b0af18b67a..f74ef7e15f 100755
--- a/fs/cpio/init
+++ b/fs/cpio/init
@@ -1,4 +1,15 @@
 #!/bin/sh
 # devtmpfs does not get automounted for initramfs
 /bin/mount -t devtmpfs devtmpfs /dev
+
+# use the /dev/console device node from devtmpfs if possible to not
+# confuse glibc's ttyname_r().
+# This may fail (E.G. booted with console=), and errors from exec will
+# terminate the shell, so use a subshell for the test
+if (exec 0</dev/console) 2>/dev/null; then
+    exec 0</dev/console
+    exec 1>/dev/console
+    exec 2>/dev/console
+fi
+
 exec /sbin/init "$@"

^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2020-08-29 14:32 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-08-29 14:32 [Buildroot] [git commit] fs/cpio/init: unbreak ttyname_r() on glibc after dropping /dev/console exec Yann E. MORIN

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.