]> git.ipfire.org Git - thirdparty/systemd.git/blobdiff - src/nspawn/nspawn.c
macro: introduce TAKE_PTR() macro
[thirdparty/systemd.git] / src / nspawn / nspawn.c
index 71b14e23029dd97a894009e6b782f22eaf1dd0f2..384b1ea5df174144fb6522c2d8cc02bac9190970 100644 (file)
@@ -1175,8 +1175,7 @@ static int parse_argv(int argc, char *argv[]) {
                  * accept this here, and silently make "--ephemeral --template=" equivalent to "--ephemeral
                  * --directory=". */
 
-                arg_directory = arg_template;
-                arg_template = NULL;
+                arg_directory = TAKE_PTR(arg_template);
         }
 
         if (arg_template && !(arg_directory || arg_machine)) {
@@ -1313,13 +1312,14 @@ static int userns_lchown(const char *p, uid_t uid, gid_t gid) {
 
 static int userns_mkdir(const char *root, const char *path, mode_t mode, uid_t uid, gid_t gid) {
         const char *q;
+        int r;
 
         q = prefix_roota(root, path);
-        if (mkdir(q, mode) < 0) {
-                if (errno == EEXIST)
-                        return 0;
-                return -errno;
-        }
+        r = mkdir_errno_wrapper(q, mode);
+        if (r == -EEXIST)
+                return 0;
+        if (r < 0)
+                return r;
 
         return userns_lchown(q, uid, gid);
 }
@@ -1599,8 +1599,10 @@ static int setup_pts(const char *dest) {
 
         /* Mount /dev/pts itself */
         p = prefix_roota(dest, "/dev/pts");
-        if (mkdir(p, 0755) < 0)
-                return log_error_errno(errno, "Failed to create /dev/pts: %m");
+        r = mkdir_errno_wrapper(p, 0755);
+        if (r < 0)
+                return log_error_errno(r, "Failed to create /dev/pts: %m");
+
         r = mount_verbose(LOG_ERR, "devpts", p, "devpts", MS_NOSUID|MS_NOEXEC, options);
         if (r < 0)
                 return r;
@@ -1846,12 +1848,13 @@ static int setup_journal(const char *directory) {
                 /* don't create parents here — if the host doesn't have
                  * permanent journal set up, don't force it here */
 
-                if (mkdir(p, 0755) < 0 && errno != EEXIST) {
+                r = mkdir_errno_wrapper(p, 0755);
+                if (r < 0 && r != -EEXIST) {
                         if (try) {
-                                log_debug_errno(errno, "Failed to create %s, skipping journal setup: %m", p);
+                                log_debug_errno(r, "Failed to create %s, skipping journal setup: %m", p);
                                 return 0;
                         } else
-                                return log_error_errno(errno, "Failed to create %s: %m", p);
+                                return log_error_errno(r, "Failed to create %s: %m", p);
                 }
 
         } else if (access(p, F_OK) < 0)
@@ -2159,8 +2162,11 @@ static int determine_names(void) {
 
                         if (!arg_ephemeral)
                                 arg_read_only = arg_read_only || i->read_only;
-                } else
-                        arg_directory = get_current_dir_name();
+                } else {
+                        r = safe_getcwd(&arg_directory);
+                        if (r < 0)
+                                return log_error_errno(r, "Failed to determine current directory: %m");
+                }
 
                 if (!arg_directory && !arg_image) {
                         log_error("Failed to determine path, please use -D or -i.");
@@ -2226,10 +2232,8 @@ static int chase_symlinks_and_update(char **p, unsigned flags) {
         if (r < 0)
                 return log_error_errno(r, "Failed to resolve path %s: %m", *p);
 
-        free(*p);
-        *p = chased;
-
-        return 0;
+        free_and_replace(*p, chased);
+        return r; /* r might be an fd here in case we ever use CHASE_OPEN in flags */
 }
 
 static int determine_uid_shift(const char *directory) {
@@ -2318,10 +2322,15 @@ static int inner_child(
                       arg_uid_shift,
                       arg_uid_range,
                       arg_selinux_apifs_context);
-
         if (r < 0)
                 return r;
 
+        if (!arg_network_namespace_path && arg_private_network) {
+                r = unshare(CLONE_NEWNET);
+                if (r < 0)
+                        return log_error_errno(errno, "Failed to unshare network namespace: %m");
+        }
+
         r = mount_sysfs(NULL, arg_mount_settings);
         if (r < 0)
                 return r;
@@ -2336,7 +2345,7 @@ static int inner_child(
         if (arg_use_cgns && cg_ns_supported()) {
                 r = unshare(CLONE_NEWCGROUP);
                 if (r < 0)
-                        return log_error_errno(errno, "Failed to unshare cgroup namespace");
+                        return log_error_errno(errno, "Failed to unshare cgroup namespace: %m");
                 r = mount_cgroups(
                                 "",
                                 arg_unified_cgroup_hierarchy,
@@ -2563,7 +2572,6 @@ static int outer_child(
         ssize_t l;
         int r;
         _cleanup_close_ int fd = -1;
-        bool create_netns;
 
         assert(barrier);
         assert(directory);
@@ -2577,23 +2585,15 @@ static int outer_child(
                 return log_error_errno(errno, "PR_SET_PDEATHSIG failed: %m");
 
         if (interactive) {
-                close_nointr(STDIN_FILENO);
-                close_nointr(STDOUT_FILENO);
-                close_nointr(STDERR_FILENO);
-
-                r = open_terminal(console, O_RDWR);
-                if (r != STDIN_FILENO) {
-                        if (r >= 0) {
-                                safe_close(r);
-                                r = -EINVAL;
-                        }
+                int terminal;
 
-                        return log_error_errno(r, "Failed to open console: %m");
-                }
+                terminal = open_terminal(console, O_RDWR);
+                if (terminal < 0)
+                        return log_error_errno(terminal, "Failed to open console: %m");
 
-                if (dup2(STDIN_FILENO, STDOUT_FILENO) != STDOUT_FILENO ||
-                    dup2(STDIN_FILENO, STDERR_FILENO) != STDERR_FILENO)
-                        return log_error_errno(errno, "Failed to duplicate console: %m");
+                r = rearrange_stdio(terminal, terminal, terminal); /* invalidates 'terminal' on success and failure */
+                if (r < 0)
+                        return log_error_errno(r, "Failed to move console to stdin/stdout/stderr: %m");
         }
 
         r = reset_audit_loginuid();
@@ -2814,11 +2814,8 @@ static int outer_child(
         if (fd < 0)
                 return fd;
 
-        create_netns = !arg_network_namespace_path && arg_private_network;
-
         pid = raw_clone(SIGCHLD|CLONE_NEWNS|
                         arg_clone_ns_flags |
-                        (create_netns ? CLONE_NEWNET : 0) |
                         (arg_userns_mode != USER_NAMESPACE_NO ? CLONE_NEWUSER : 0));
         if (pid < 0)
                 return log_error_errno(errno, "Failed to fork inner child: %m");
@@ -3512,9 +3509,11 @@ static int run(int master,
         }
 
         /* Wait for the outer child. */
-        r = wait_for_terminate_and_warn("namespace helper", *pid, NULL);
-        if (r != 0)
-                return r < 0 ? r : -EIO;
+        r = wait_for_terminate_and_check("(sd-namespace)", *pid, WAIT_LOG_ABNORMAL);
+        if (r < 0)
+                return r;
+        if (r != EXIT_SUCCESS)
+                return -EIO;
 
         /* And now retrieve the PID of the inner child. */
         l = recv(pid_socket_pair[0], pid, sizeof *pid, 0);
@@ -3616,14 +3615,16 @@ static int run(int master,
                  * case PID 1 will send us a friendly RequestStop signal, when it is asked to terminate the
                  * scope. Let's hook into that, and cleanly shut down the container, and print a friendly message. */
 
-                r = sd_bus_add_match(bus, NULL,
-                                     "type='signal',"
-                                     "sender='org.freedesktop.systemd1',"
-                                     "interface='org.freedesktop.systemd1.Scope',"
-                                     "member='RequestStop'",
-                                     on_request_stop, PID_TO_PTR(*pid));
+                r = sd_bus_match_signal_async(
+                                bus,
+                                NULL,
+                                "org.freedesktop.systemd1",
+                                NULL,
+                                "org.freedesktop.systemd1.Scope",
+                                "RequestStop",
+                                on_request_stop, NULL, PID_TO_PTR(*pid));
                 if (r < 0)
-                        return log_error_errno(r, "Failed to install request stop match: %m");
+                        return log_error_errno(r, "Failed to request RequestStop match: %m");
         }
 
         if (arg_register) {
@@ -4052,14 +4053,14 @@ int main(int argc, char *argv[]) {
                         goto finish;
                 }
 
-                r = dissect_image(
+                r = dissect_image_and_warn(
                                 loop->fd,
+                                arg_image,
                                 arg_root_hash, arg_root_hash_size,
                                 DISSECT_IMAGE_REQUIRE_ROOT,
                                 &dissected_image);
                 if (r == -ENOPKG) {
-                        log_error_errno(r, "Could not find a suitable file system or partition table in image: %s", arg_image);
-
+                        /* dissected_image_and_warn() already printed a brief error message. Extend on that with more details */
                         log_notice("Note that the disk image needs to\n"
                                    "    a) either contain only a single MBR partition of type 0x83 that is marked bootable\n"
                                    "    b) or contain a single GPT partition of type 0FC63DAF-8483-4772-8E79-3D69D8477DE4\n"
@@ -4068,22 +4069,8 @@ int main(int argc, char *argv[]) {
                                    "in order to be bootable with systemd-nspawn.");
                         goto finish;
                 }
-                if (r == -EADDRNOTAVAIL) {
-                        log_error_errno(r, "No root partition for specified root hash found.");
-                        goto finish;
-                }
-                if (r == -EOPNOTSUPP) {
-                        log_error_errno(r, "--image= is not supported, compiled without blkid support.");
-                        goto finish;
-                }
-                if (r == -EPROTONOSUPPORT) {
-                        log_error_errno(r, "Device is loopback block device with partition scanning turned off, please turn it on.");
-                        goto finish;
-                }
-                if (r < 0) {
-                        log_error_errno(r, "Failed to dissect image: %m");
+                if (r < 0)
                         goto finish;
-                }
 
                 if (!arg_root_hash && dissected_image->can_verity)
                         log_notice("Note: image %s contains verity information, but no root hash specified! Proceeding without integrity checking.", arg_image);