Managing code maps in FEXServer rather than in FEXInterpreter makes it
easier to handle multiple concurrent processes sharing code caches for
the main executable and libraries.
The sender might provide all requested message bytes but no FD. The receiver
interface has no simple way of indicating this scenario yet, so just assert
out for now to ensure it never happens in the first place.
If needed, this can be changed to return a new error code to indicate partial
read in the future.
Use getuid() instead of geteuid() when determining FEXServer socket names.
Ensures setuid binaries (like chrome-sandbox from Discord) connect to their parent
user's FEXServer instance instead of trying to spawn a separate server.
Fixes connection errors when running applications that spawn setuid children.
Still creates a copy of FEXInterpreter from FEX for downstream projects
to have some time to get off the old name. Creating a symlink is kind of
a pain in cmake so just doing an install copy is easy.
We can reduce includes, such as logging by specifying a concrete size for logging levels,
allowing the enum to be forward declared. We can also move FillHeader into the cpp file,
allowing the syscalls header to be removed.
Newer fuse releases changed how they are waiting on child processes to
exit. Setting the signal action to SIG_IGN would cause
erofsfuse/squashfuse to inherit the ignored action and cause their
internal `wait4` syscalls to fail with ECHLD.
Set the action back to default inside the FEXServer because our original
reasoning for setting the ignoring is no longer valid. FEXInterpreter
still ignores SIGCHLD while launching FEXServer.
Maybe fixes the muvm thing people have been complaining about.
Also fixes accidental comma delimiter usage.
Instead of keeping the vlaue as a string array in the MetaLayer, convert
the value to its final type once.
Improves performance in some hotpaths that were doing config based
string conversion in a relatively high frequency.
The problem here is that the pipe we used for telling FEXInterpreter
that the FEXServer is ready to accept connections was inherited by
erofsfuse or squashfuse. So the closing of the pipe from the FEXServer
side would leave a reference open in squashfuse or erofsfuse.
Fix this by setting FD_CLOEXEC on the pipe, but also pass the pipe FD
through an argument instead of scanning for all pipes.
Then once we execve the squashfuse/erofsfuse application, the FD isn't
inherited.
Fixes#4329
Abstract sockets have one limitation: they are bound to a network
namespace. Chromium/CEF sandboxes using a new netns, which breaks
connecting to the FEXServer.
To work around this, use and try *both* abstract and named sockets. As
long as either the filesystem or the network is unsandboxed, things will
work. If both are sandboxed, there isn't much we can do... but at that
point we shouldn't be reinitializing the FEXServer connection anyway
since the FS should be available on FEXInterpreter startup.
Using the server mount folder works most of the time, but when running
under pressure-vessel this stacks directories in a weird way because the
mount folder has some tricks applied to it.
Expose the temp folder being used directly instead.
This option was disabled a few months ago when we switched the server
socket from a filesystem unix socket to an abstract socket.
This partially broke our chroot scripts which relied on this option
existing.
Readds support for an explicitly named abstract socket named from
config.
This is a workaround for dealing with chroots that change users.
They end up changing a user while doing operations and then can't
connect to the FEXServer anymore because environment variables have been
wiped away.
When FEXServer is daemonizing through an instance of FEXLoader or
FEXInterpreter, it would leave a zombie process which was waiting for us
to read the process status.
Since we don't care about the child status and don't want to get blocked
by waitpid, just ignore the signal.
This tells the kernel that we don't care about the signal and will kill
the zombie process immediately.
Didn't notice this before since FEXServer started failing to daemonize.
On first FEXInterpreter execution, it is expected that `ConnectToServer`
will fail with `ECONNREFUSED` because FEXServer won't be running.
Skip printing this first messaage to stderr if configured.
If it is some other error message then ensure it is still printed.
Two changes here.
- Make the mount path follow server temp folder requirements.
- Will be mounted in `/tmp/` or `$XDG_RUNTIME_DIR/` now
- Switch the FEXServer socket to an "abstract" AF_UNIX socket.
- If the socket is in `/tmp/` then systemd will put the service in a
private `/tmp` folder that only exists for the service.
- If the socket is in `$XDG_RUNTIME_DIR` then pressure-vessel can't
chroot anymore since they make their own runtime directory.
- If it is in `$HOME/.fex-emu/` then it breaks usage where the
filesystem is a mount that doesn't support AF_UNIX like sshfs.
The only reasonable thing to do is to switch over to `abstract` sockets
which will work in all cases.
Tested with pressure-vessel and systemd and now it works in all
situations.
In the case of a platform enabling PrivateTmp then the FEXServer and
FEXInterpreter won't have a tmp folder that shares the socket location.
The runtime directory is a perfect place to share these across
processes.
This is necessary for the fexserver to function correctly when chrooting
in to our rootfs and doing things.
Requires independent rootfs script modifications which will come with
the next rootfs update.
Problem comes down to a chroot supporting multiple users, where our
typical use case is only one user. Bind the server file to a single
server for the entire chroot session regardless of users, solving this
problem inside the chroot.
Fixes apt-get inside of chroot, which runs as user _apt.
pressure-vessel overrides our rootfs when it does a pivot_root.
Since we are still communicating to the FEXServer we were pulling the
configured rootfs.
Instead check if we are in pressure vessel and avoid doing that.
This fixes FEX running under pressure-vessel.
(There may be some implications to this down the road with code caching
but let's worry about that later)
It can be useful to know in tooling when the current active FEXServer
has exited.
Two things can happen when this command is run.
No FEXServer is active, returns immediately.
A FEXServer is active, we query for a pidfd from the active server, then
we wait until it exits.
Both instances of this is valid to use.
This is a relatively invasive change since multiple things needed to
happen at once.
* Socket based logging is removed
* Logging has been replaced to only support stdout, stderr, and server
* Server is now default and replaces what FEXLogServer did
* Server logging now uses a pipe instead of a socket
* Can be faster than stderr and stdout since the application doesn't
need to wait on terminal output
* FEXMountDaemon has been removed
* Functionality has been merged in to FEXServer
* FEXServer is always executed on FEX initialization time
* Similar in behaviour to Wine's wineserver
* Can explicitly start this before using FEX for logging purposes
* Stays around until all instances of FEX exit
* Will stick around for a short amount of time in case of spurious
execution
* FEXServer will soon be extended to do more than logging and squashfs
mounting
* FEX rootfs scripts will need to be updated to support this path
* Just means rbinding the /tmp folder and forcing a FEXServer instance
to be alive
* Pressure-vessel works fine in this case since FEXServer will already
be running
* It already rbinds the host /tmp folder which is why this works