Bug 240767 - linprocfs(4) - /proc/fd is weird
Summary: linprocfs(4) - /proc/fd is weird
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: CURRENT
Hardware: Any Any
: --- Affects Only Me
Assignee: freebsd-emulation (Nobody)
URL:
Keywords:
Depends on:
Blocks: 247219
  Show dependency treegraph
 
Reported: 2019-09-23 12:04 UTC by Edward Tomasz Napierala
Modified: 2020-07-08 21:04 UTC (History)
1 user (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Edward Tomasz Napierala freebsd_committer 2019-09-23 12:04:52 UTC
Linux apps, such as ps(1), expects stuff in /proc/fd/ to be symlinks.  I'm not sure how to fix it, because I'm not sure how that part of linprocfs actually works - it _somehow_ redirects /proc/fd to /dev/fd/.
Comment 1 Edward Tomasz Napierala freebsd_committer 2020-01-13 12:51:45 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).
Comment 2 Edward Tomasz Napierala freebsd_committer 2020-07-03 22:33:56 UTC
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.
Comment 3 Edward Tomasz Napierala freebsd_committer 2020-07-03 22:38:04 UTC
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.
Comment 4 Edward Tomasz Napierala freebsd_committer 2020-07-03 23:42:15 UTC
https://reviews.freebsd.org/D25559
Comment 5 commit-hook freebsd_committer 2020-07-04 18:01:54 UTC
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
Comment 6 Alexander Leidinger freebsd_committer 2020-07-07 10:51:02 UTC
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)?).
Comment 7 Edward Tomasz Napierala freebsd_committer 2020-07-08 21:04:42 UTC
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.