diff --git a/revokefs/main.c b/revokefs/main.c index 401330d7..f0808f15 100644 --- a/revokefs/main.c +++ b/revokefs/main.c @@ -444,6 +444,7 @@ usage (const char *progname) " -h --help print help\n" " --socket=fd Pass in the socket fd\n" " --backend Run the backend instead of fuse\n" + " --exit-with-fd=fd With --backend, exit when the given file descriptor is closed\n" "\n", progname); } @@ -478,6 +479,7 @@ revokefs_opt_proc (void *data, struct revokefs_config { int socket_fd; + int exit_with_fd; int backend; }; @@ -485,6 +487,7 @@ struct revokefs_config { static struct fuse_opt revokefs_opts[] = { REVOKEFS_OPT ("--socket=%i", socket_fd, -1), + REVOKEFS_OPT ("--exit-with-fd=%i", exit_with_fd, -1), REVOKEFS_OPT ("--backend", backend, 1), FUSE_OPT_KEY ("-h", KEY_HELP), @@ -497,7 +500,7 @@ main (int argc, char *argv[]) { struct fuse_args args = FUSE_ARGS_INIT (argc, argv); int res; - struct revokefs_config conf = { -1 }; + struct revokefs_config conf = { -1, -1 }; res = fuse_opt_parse (&args, &conf, revokefs_opts, revokefs_opt_proc); if (res != 0) @@ -529,7 +532,7 @@ main (int argc, char *argv[]) exit (EXIT_FAILURE); } - do_writer (basefd, conf.socket_fd); + do_writer (basefd, conf.socket_fd, conf.exit_with_fd); exit (0); } @@ -559,7 +562,7 @@ main (int argc, char *argv[]) { /* writer process */ close (sockets[0]); - do_writer (basefd, sockets[1]); + do_writer (basefd, sockets[1], -1); exit (0); } diff --git a/revokefs/writer.c b/revokefs/writer.c index fc31bae7..2a297d0b 100644 --- a/revokefs/writer.c +++ b/revokefs/writer.c @@ -32,6 +32,7 @@ #include #include #include +#include #include #include @@ -759,7 +760,8 @@ request_access (int writer_socket, const char *path, int mode) void do_writer (int basefd_arg, - int fuse_socket) + int fuse_socket, + int exit_with_fd) { guchar request_buffer[MAX_REQUEST_SIZE]; RevokefsRequest *request = (RevokefsRequest *)&request_buffer; @@ -773,6 +775,27 @@ do_writer (int basefd_arg, { ssize_t data_size, size; ssize_t response_data_size, response_size, written_size; + int res; + struct pollfd pollfds[2] = { + {fuse_socket, POLLIN, 0 }, + {exit_with_fd, POLLIN, 0 }, + }; + + res = poll(pollfds, exit_with_fd >= 0 ? 2 : 1, -1); + if (res < 0) + { + perror ("Got error polling sockets: "); + exit (1); + } + + if (exit_with_fd >= 0 && (pollfds[1].revents & (POLLERR|POLLHUP)) != 0) + { + g_printerr ("Received EOF on exit-with-fd argument"); + exit (1); + } + + if (pollfds[0].revents & POLLIN == 0) + continue; size = TEMP_FAILURE_RETRY (read (fuse_socket, request_buffer, sizeof (request_buffer))); if (size == -1) diff --git a/revokefs/writer.h b/revokefs/writer.h index 46a0be17..0131eaa4 100644 --- a/revokefs/writer.h +++ b/revokefs/writer.h @@ -39,7 +39,7 @@ int request_fsync (int writer_socket, int fd); int request_close (int writer_socket, int fd); int request_access (int writer_socket, const char *path, int mode); -void do_writer (int basefd, int socket); +void do_writer (int basefd, int socket, int exit_with_fd); typedef enum { diff --git a/system-helper/flatpak-system-helper.c b/system-helper/flatpak-system-helper.c index 6cc2ac3e..f7a81e28 100644 --- a/system-helper/flatpak-system-helper.c +++ b/system-helper/flatpak-system-helper.c @@ -72,6 +72,8 @@ typedef struct uid_t uid; /* uid of the client initiating the pull */ gint client_socket; /* fd that is send back to the client for spawning revoke-fuse */ + gint backend_exit_socket; /* write end of a pipe which helps terminating revokefs backend if + system helper exits abruptly */ gchar *src_dir; /* source directory containing the actual child repo */ gchar *unique_name; @@ -131,6 +133,7 @@ ongoing_pull_free (OngoingPull *pull) g_clear_pointer (&pull->src_dir, g_free); g_clear_pointer (&pull->unique_name, g_free); close (pull->client_socket); + close (pull->backend_exit_socket); g_slice_free (OngoingPull, pull); } @@ -1497,7 +1500,7 @@ ongoing_pull_new (FlatpakSystemHelper *object, GDBusConnection *connection = g_dbus_method_invocation_get_connection (invocation); g_autoptr(OngoingPull) pull = NULL; g_autoptr(GSubprocessLauncher) launcher = NULL; - int sockets[2]; + int sockets[2], exit_sockets[2]; pull = g_slice_new0 (OngoingPull); pull->object = object; @@ -1521,17 +1524,30 @@ ongoing_pull_new (FlatpakSystemHelper *object, return NULL; } + if (pipe2 (exit_sockets, O_CLOEXEC) == -1) + { + glnx_throw_errno_prefix (error, "Failed to create a pipe"); + close (sockets[0]); + close (sockets[1]); + return NULL; + } + launcher = g_subprocess_launcher_new (G_SUBPROCESS_FLAGS_NONE); g_subprocess_launcher_set_child_setup (launcher, revokefs_fuse_backend_child_setup, passwd, NULL); g_subprocess_launcher_take_fd (launcher, sockets[0], 3); fcntl (sockets[1], F_SETFD, FD_CLOEXEC); pull->client_socket = sockets[1]; + g_subprocess_launcher_take_fd (launcher, exit_sockets[0], 4); + pull->backend_exit_socket = exit_sockets[1]; + pull->revokefs_backend = g_subprocess_launcher_spawn (launcher, error, "revokefs-fuse", "--backend", - "--socket=3", src, NULL); + "--socket=3", + "--exit-with-fd=4", + src, NULL); if (pull->revokefs_backend == NULL) return NULL;