Summary: | linprocfs(4) - /proc/fd is weird | ||
---|---|---|---|
Product: | Base System | Reporter: | Edward Tomasz Napierala <trasz> |
Component: | kern | Assignee: | Edward Tomasz Napierala <trasz> |
Status: | Closed FIXED | ||
Severity: | Affects Only Me | CC: | netchild |
Priority: | --- | ||
Version: | CURRENT | ||
Hardware: | Any | ||
OS: | Any | ||
Bug Depends on: | |||
Bug Blocks: | 247219 |
Description
Edward Tomasz Napierala
2019-09-23 12:04:52 UTC
So, the way it works right now is that for current process - and that process only - linprocfs provides a symlink from /proc/self/fd to /dev/fd. Making this work properly would require adding file descriptor knowledge to procfs itself; possibly to pseudofs. The current behaviour breaks tty(1) and a recent screen(1). Okay, so after another afternoon spent debugging this stuff, here's how it looks: First, glibc (namely gettyname()) requires contents of /proc/self/fd/ to be symlinks. Turns out it's trivial to make it work, and it's even documented: just mount fdescfs with 'linrdlnk' option. I'll make /etc/rc.d/linux default to it soon. Problem is: it doesn't work when you chroot into your Linux root (eg /compat/linux). For some reason glibc tries to be very, _very_ careful with the name it got from /proc/self/fd/0; it calls stat(2) on fd 0, and then on the symlink target, and compares st_dev. When chrooted to /compat/linux, your stdin is on /dev, while /proc/self/fd/0 (really /compat/linux/proc/self/fd/0) points to /dev/fd/0 (really /compat/linux/dev/fd/0); since /dev and /compat/linux/dev have different fsids, and thus stat(2) returns different st_dev, the glibc check fails. Workaround: run sshd inside your linux chroot and ssh into localhost. Meh. Forgot a crucial point: if anyone has an idea on how to make it work without ssh, please tell. Using ssh to access your own machine is just silly. Even though it fixes some other problems with chrooting into linux, eg wrong (for Linux) shell variables. A commit references this bug: Author: trasz Date: Sat Jul 4 18:01:29 UTC 2020 New revision: 362935 URL: https://svnweb.freebsd.org/changeset/base/362935 Log: Make the linux rc script use linrdlnk by default. This fixes Linux gettyname(3), with caveats (see PR). PR: kern/240767 MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D25558 Changes: head/libexec/rc/rc.d/linux head/share/man/man4/linux.4 1. chrooting into /compat/linux is not supposed to work. /compat linux is used by linux_base ports, and linux_base ports are designed for fall-through to FreeBSD config files (where applicable / compatible). The linux-dist ports were used in the past for this, but right now we don't have a linux-dist port. 2. what about redirecting stdin on a cheroot to the fd inside the chroot, does this work? If yes, I would suggest to document it somewhere sensible (linux(4)?). 1. I know, but for this particular purpose it does (or should) work, since /compat/linux already has its own devfs mount, for /dev/shm/ and /dev/fdescfs/, like any Linux jail would. And it makes it easy to figure out what's inside that directory. 2. Hm, it could work. But I eventually figured out how to make it work out of the box, see the kernel patch at https://reviews.freebsd.org/D25559. A commit references this bug: Author: trasz Date: Sat Jul 11 13:08:17 UTC 2020 New revision: 363093 URL: https://svnweb.freebsd.org/changeset/base/363093 Log: Make linux stat(2) return the same st_dev for every devfs instance. The reason for this is to work around an idiosyncrasy of glibc getttynam(3) implementation: it checks whether st_dev returned for fd 0 is the same as st_dev returned for the target of /proc/self/fd/0 symlink, and with linux chroots having their own devfs instance, the check will fail if you chrooted into it. PR: kern/240767 Reviewed by: kib MFC after: 2 weeks Sponsored by: The FreeBSD Foundation Differential Revision: https://reviews.freebsd.org/D25559 Changes: head/sys/compat/linux/linux_stats.c A commit references this bug: Author: trasz Date: Sun Aug 23 22:23:19 UTC 2020 New revision: 364572 URL: https://svnweb.freebsd.org/changeset/base/364572 Log: MFC r363093: Make linux stat(2) return the same st_dev for every devfs instance. The reason for this is to work around an idiosyncrasy of glibc getttynam(3) implementation: it checks whether st_dev returned for fd 0 is the same as st_dev returned for the target of /proc/self/fd/0 symlink, and with linux chroots having their own devfs instance, the check will fail if you chrooted into it. PR: kern/240767 Sponsored by: The FreeBSD Foundation Changes: _U stable/12/ stable/12/sys/compat/linux/linux_stats.c A commit references this bug: Author: trasz Date: Thu Aug 27 19:42:53 UTC 2020 New revision: 364884 URL: https://svnweb.freebsd.org/changeset/base/364884 Log: MFC r362935: Make the linux rc script use linrdlnk by default. This fixes Linux gettyname(3), with caveats (see PR). PR: kern/240767 Sponsored by: The FreeBSD Foundation Changes: _U stable/12/ stable/12/libexec/rc/rc.d/linux stable/12/share/man/man4/linux.4 |