Page MenuHomeFreeBSD

linprocfs: strip the emulator prefix from /proc/<pid>/exe
AbandonedPublic

Authored by dteske on Tue, Aug 11, 3:02 AM.
Tags
None
Referenced Files
F167120549: D58780.id183859.diff
Wed, Aug 19, 6:36 AM
F167110672: D58780.id183859.diff
Wed, Aug 19, 4:28 AM
Unknown Object (File)
Tue, Aug 18, 8:06 PM
Unknown Object (File)
Tue, Aug 18, 3:21 PM
Unknown Object (File)
Tue, Aug 18, 3:12 AM
Unknown Object (File)
Mon, Aug 17, 10:54 PM
Unknown Object (File)
Mon, Aug 17, 7:28 PM
Unknown Object (File)
Mon, Aug 17, 7:28 PM

Details

Reviewers
dchagin
adrian
emaste
Group Reviewers
Linux Emulation
Summary

proc_get_binpath() returns a FreeBSD host path. For a Linux process
whose text lives under the emulator root, linprocfs filled the exe
symlink with e.g. /compat/linux/usr/bin/foo. That is not the
executable's name in the Linux namespace: the Linux ABI resolves
absolute paths from compat.linux.emul_path, so following the symlink
looked up /compat/linux/compat/linux/usr/bin/foo and failed with
ENOENT, and readlink consumers that compare or derive paths from the
result saw a host configuration detail that Linux never exposes.

Strip the emul_path prefix when present so /proc/<pid>/exe names the
executable in the Linux namespace (readlink, stat, execve), matching
Linux. With this fix the common case -- Linux binaries installed
under the emulator root -- works on a default Linuxulator setup, with
no mounts beyond those made by rc.d/linux.

Text outside the emulator root (e.g. Linux binaries that ports
install under ${PREFIX}, such as www/linux-brave) already reports the
correct host path; following it relies on namei restarting the lookup
in the native namespace and therefore requires procfs(5) mounted at
/proc. That is a configuration and documentation matter, not
addressed here.

PR: 297426
MFC after: 2 weeks

Diff Detail

Repository
rG FreeBSD src repository
Lint
Lint Skipped
Unit
Tests Skipped
Build Status
Buildable 75512
Build 72395: arc lint + arc unit

Event Timeline

arrowd added inline comments.
sys/compat/linprocfs/linprocfs.c
1215

Linuxulator first resolves against /, then in case of failure - against /compat/linux.

Have you tested the impact with ports like:

games/linux-steam-utils
www/linux-widevine-cdm
emulators/wine-proton
emulators/libc6-shim

By testing I mean that steam should still run,
Games that was running with wine-proton before should still works, games that was running with either lsu chroot option should still works if they were working before.
For widevine, drm content should still be playable after this patch.
For libc6-shim, I guess that it is already tested with steam, but I would assume that if cuda was working before, it should still works after.

Have you tested the impact with ports like:

games/linux-steam-utils
www/linux-widevine-cdm
emulators/wine-proton
emulators/libc6-shim

By testing I mean that steam should still run,
Games that was running with wine-proton before should still works, games that was running with either lsu chroot option should still works if they were working before.
For widevine, drm content should still be playable after this patch.
For libc6-shim, I guess that it is already tested with steam, but I would assume that if cuda was working before, it should still works after.

I have been testing extensively

  1. games/linux-steam-utils does not install inside the emul_path (/compat/linux) and is therefore unaffected by this patch
  2. www/linux-widevine-cdm likewise does not install into the emul_path -- regardless, I am running (checks) Discovery+, DISH anywhere, Disney+, Hulu, Netflix, Pandora, Amazon Prime Video, and Apple TV web, all working wonderfully in linux-brave (which also does not install into the emul_path)
  3. emulators/wine-proton -- also not in the emul_path
  4. emulators/libc6-shim -- same, not in the emul_path

This patch only covers one half of the issue. The issue is that linprocfs does Linux programs dirty by responding with a /proc/self/exe path that leaks the emulator's prefix (if this were a jail, people would be up in arms for security reasons).

This patch does nothing for programs outside the emul_path (the effective "jail root dir" if this were a jail -- the emulation layer's prefix, aka emul_path, is likewise not to be revealed to Linux emulated programs). That being said, there are two sides to the coin -- programs inside the emul_path and programs outside the emul_path. This patch only addresses the former and I left solving the latter up for a later date.

All the programs you listed are unaffected, and tested to be so, nothing changes for them with this patch. Nothing at all. Their problem is kicked down the road for a later date and all those programs will continue relying on procfs and cannot survive on linprocfs alone.

Ideally, we would be loading Linux programs into /compat/linux/opt but we don't -- we allow them to be splat all over the disk. Right now, I opted to solve just for programs hosted inside /compat/linux

sys/compat/linprocfs/linprocfs.c
1215

That is true in general, but there's nuance involved in absolute symlink lookup:

if (*(cnp->cn_nameptr) == '/') {
        /*
         * For ABI-root lookups, preserve the ABI root while
         * following absolute symlinks during the first lookup.
         *
         * Only force the real root after the ABI lookup has
         * already failed and namei() has restarted in the
         * native namespace.  Otherwise absolute symlinks inside
         * /compat/linux, including the ELF interpreter symlink,
         * incorrectly escape to the native root (PR 289739).
         */
        if ((cnp->cn_flags & ISRESTARTED) != 0)
                ndp->ni_rootdir = pwd->pwd_rdir;
        vrele(dp);
        error = namei_handle_root(ndp, &dp);
        if (error != 0)
                goto out;
}

Leaning toward abandoning this in favor of a namei fix for the absolute-symlink fallback (same PR). Write-up shortly.

https://reviews.freebsd.org/D58855 is up and it fixes not only this problem but fontconfig and other symlink issues