]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/sysupdate/sysupdate-resource.c
tree-wide: use FORK_REARRANGE_STDIO and FORK_CLOSE_ALL_FDS
[thirdparty/systemd.git] / src / sysupdate / sysupdate-resource.c
index bf521980e26638bd4e8731241eed06dc0777f1bd..6c05d245f8c473d52114e08b3126ac15a9924ac9 100644 (file)
@@ -8,6 +8,7 @@
 #include "blockdev-util.h"
 #include "chase-symlinks.h"
 #include "device-util.h"
+#include "devnum-util.h"
 #include "dirent-util.h"
 #include "env-util.h"
 #include "fd-util.h"
@@ -241,7 +242,7 @@ static int download_manifest(
                 size_t *ret_size) {
 
         _cleanup_free_ char *buffer = NULL, *suffixed_url = NULL;
-        _cleanup_(close_pairp) int pfd[2] = { -1, -1 };
+        _cleanup_(close_pairp) int pfd[2] = PIPE_EBADF;
         _cleanup_fclose_ FILE *manifest = NULL;
         size_t size = 0;
         pid_t pid;
@@ -263,7 +264,11 @@ static int download_manifest(
         log_info("%s Acquiring manifest file %s%s", special_glyph(SPECIAL_GLYPH_DOWNLOAD),
                  suffixed_url, special_glyph(SPECIAL_GLYPH_ELLIPSIS));
 
-        r = safe_fork("(sd-pull)", FORK_RESET_SIGNALS|FORK_DEATHSIG|FORK_LOG, &pid);
+        r = safe_fork_full("(sd-pull)",
+                           (int[]) { -EBADF, pfd[1], STDERR_FILENO },
+                           NULL, 0,
+                           FORK_RESET_SIGNALS|FORK_CLOSE_ALL_FDS|FORK_DEATHSIG|FORK_REARRANGE_STDIO|FORK_LOG,
+                           &pid);
         if (r < 0)
                 return r;
         if (r == 0) {
@@ -279,14 +284,6 @@ static int download_manifest(
                         NULL
                 };
 
-                pfd[0] = safe_close(pfd[0]);
-
-                r = rearrange_stdio(-1, pfd[1], STDERR_FILENO);
-                if (r < 0) {
-                        log_error_errno(r, "Failed to rearrange stdin/stdout: %m");
-                        _exit(EXIT_FAILURE);
-                }
-
                 (void) unsetenv("NOTIFY_SOCKET");
                 execv(pull_binary_path(), (char *const*) cmdline);
                 log_error_errno(errno, "Failed to execute %s tool: %m", pull_binary_path());
@@ -525,10 +522,14 @@ int resource_resolve_path(
         assert(rr);
 
         if (rr->path_auto) {
+                struct stat orig_root_stats;
 
-                /* NB: we don't actually check the backing device of the root fs "/", but of "/usr", in order
-                 * to support environments where the root fs is a tmpfs, and the OS itself placed exclusively
-                 * in /usr/. */
+                /* NB: If the root mount has been replaced by some form of volatile file system (overlayfs),
+                 * the original root block device node is symlinked in /run/systemd/volatile-root. Let's
+                 * follow that link here. If that doesn't exist, we check the backing device of "/usr". We
+                 * don't actually check the backing device of the root fs "/", in order to support
+                 * environments where the root fs is a tmpfs, and the OS itself placed exclusively in
+                 * /usr/. */
 
                 if (rr->type != RESOURCE_PARTITION)
                         return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP),
@@ -546,10 +547,19 @@ int resource_resolve_path(
                         return log_error_errno(SYNTHETIC_ERRNO(EPERM),
                                                "Block device is not allowed when using --root= mode.");
 
-                r = get_block_device_harder("/usr/", &d);
+                r = stat("/run/systemd/volatile-root", &orig_root_stats);
+                if (r < 0) {
+                        if (errno == ENOENT) /* volatile-root not found */
+                                r = get_block_device_harder("/usr/", &d);
+                        else
+                                return log_error_errno(r, "Failed to stat /run/systemd/volatile-root: %m");
+                } else if (!S_ISBLK(orig_root_stats.st_mode)) /* symlink was present but not block device */
+                        return log_error_errno(SYNTHETIC_ERRNO(ENOTBLK), "/run/systemd/volatile-root is not linked to a block device.");
+                else /* symlink was present and a block device */
+                        d = orig_root_stats.st_rdev;
 
         } else if (rr->type == RESOURCE_PARTITION) {
-                _cleanup_close_ int fd = -1, real_fd = -1;
+                _cleanup_close_ int fd = -EBADF, real_fd = -EBADF;
                 _cleanup_free_ char *resolved = NULL;
                 struct stat st;