system-helper: fix busyloop in revokefs writer process

After an unprivileged client calls GetRevokefsFd(), the `revokefs-fuse
--backend` process busyloops as follows:

    poll([{fd=3, events=POLLIN}, {fd=4, events=POLLIN}], 2, -1) = 1 ([{fd=4, revents=POLLIN}])

Here is the command line for this process:

    revokefs-fuse --backend --socket=3 --exit-with-fd=4 /var/lib/flatpak/repo/tmp/flatpak-cache-JBUHB0

The intention here is to poll() until fd 3 is readable (at which
point the writer process serves a client request and writes back a
response, synchronously) or fd 4 encounters an error. fd 4 is meant to
be one side of a pipe that the system helper holds the other end of;
when the pipe is broken, the system helper must have gone away, and the
`revokefs-fuse --backend` process treats this as a signal to exit.

However, fd 4 is not a pipe. In fact, it is the dirfd for the target directory:

    root@camille:/var/roothome# ls -l /proc/31717/fd
    total 0
    lr-x------ 1 wjt wjt 64 Nov 19 21:21 0 -> /dev/null
    lrwx------ 1 wjt wjt 64 Nov 19 21:21 1 -> /dev/pts/1
    lrwx------ 1 wjt wjt 64 Nov 19 21:21 2 -> /dev/pts/1
    lrwx------ 1 wjt wjt 64 Nov 19 21:21 3 -> 'socket:[2558007]'
    lr-x------ 1 wjt wjt 64 Nov 19 21:21 4 -> /var/lib/flatpak/repo/tmp/flatpak-cache-JBUHB0

This is because revokefs_fuse_backend_child_setup() erroneously closes
fd 4 before the `revokefs-fuse --backend` process is exec()d. This
regressed in d91660fe2a.

Fix this by only closing fds 5 and above. With this change, we see the
expected set of open file descriptors:

    root@camille:/var/roothome# ls -l /proc/32493/fd
    total 0
    lr-x------ 1 wjt wjt 64 Nov 19 21:24 0 -> /dev/null
    lrwx------ 1 wjt wjt 64 Nov 19 21:24 1 -> /dev/pts/1
    lrwx------ 1 wjt wjt 64 Nov 19 21:24 2 -> /dev/pts/1
    lrwx------ 1 wjt wjt 64 Nov 19 21:24 3 -> 'socket:[2552594]'
    lr-x------ 1 wjt wjt 64 Nov 19 21:24 4 -> 'pipe:[2552596]'
    lr-x------ 1 wjt wjt 64 Nov 19 21:24 5 -> /var/lib/flatpak/repo/tmp/flatpak-cache-JBUHB0

Fixes #2882.
This commit is contained in:
Will Thompson
2019-11-19 21:33:37 +00:00
parent 4fd9f59850
commit 8bdb2fa004

View File

@@ -1467,9 +1467,10 @@ revokefs_fuse_backend_child_setup (gpointer user_data)
{
struct passwd *passwd = user_data;
/* We use 4 instead of 3 here, because fd 3 is the inerited socket
and got dup2() into place before this by GSubprocess */
flatpak_close_fds_workaround (4);
/* We use 5 instead of 3 here, because fd 3 is the inherited SOCK_SEQPACKET
* socket and fd 4 is the --close-with-fd pipe; both were dup2()'d into place
* before this by GSubprocess */
flatpak_close_fds_workaround (5);
if (setgid (passwd->pw_gid) == -1)
{