path: root/fs
diff options
authorGravatar Peter Korsgaard <peter@korsgaard.com>2020-08-29 15:09:11 +0200
committerGravatar Yann E. MORIN <yann.morin.1998@free.fr>2020-08-29 16:32:33 +0200
commitb9026e83f9c7610526f045f2fc1135b45a26305f (patch)
tree9b4596a8421fe99ca4058e44260bf7f00d939bd0 /fs
parent4c2532fc8b446e2546db946467ef590d1e77f38e (diff)
fs/cpio/init: unbreak ttyname_r() on glibc after dropping /dev/console exec
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>
Diffstat (limited to 'fs')
1 files changed, 11 insertions, 0 deletions
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 @@
# 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
exec /sbin/init "$@"