From: Luca Boccassi Date: Fri, 30 Aug 2024 16:55:18 +0000 (+0100) Subject: portable: ensure PORTABLE_FORCE_ATTACH works even when there is a leftover unit X-Git-Tag: v257-rc1~576 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1e2d1a7202400e08a00782f32804fdc503259806;p=thirdparty%2Fsystemd.git portable: ensure PORTABLE_FORCE_ATTACH works even when there is a leftover unit Force means force, we skip checks with PID1 for existing units, but then bail out with EEXIST if the files are actually there. Overwrite everything instead. --- diff --git a/src/portable/portable.c b/src/portable/portable.c index 08e9bc01139..af7d9552da4 100644 --- a/src/portable/portable.c +++ b/src/portable/portable.c @@ -1255,8 +1255,12 @@ static int install_profile_dropin( return -ENOMEM; if (flags & PORTABLE_PREFER_COPY) { + CopyFlags copy_flags = COPY_REFLINK|COPY_FSYNC; - r = copy_file_atomic(from, dropin, 0644, COPY_REFLINK|COPY_FSYNC); + if (flags & PORTABLE_FORCE_ATTACH) + copy_flags |= COPY_REPLACE; + + r = copy_file_atomic(from, dropin, 0644, copy_flags); if (r < 0) return log_debug_errno(r, "Failed to copy %s %s %s: %m", from, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), dropin); @@ -1264,8 +1268,12 @@ static int install_profile_dropin( } else { - if (symlink(from, dropin) < 0) - return log_debug_errno(errno, "Failed to link %s %s %s: %m", from, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), dropin); + if (flags & PORTABLE_FORCE_ATTACH) + r = symlink_atomic(from, dropin); + else + r = RET_NERRNO(symlink(from, dropin)); + if (r < 0) + return log_debug_errno(r, "Failed to link %s %s %s: %m", from, special_glyph(SPECIAL_GLYPH_ARROW_RIGHT), dropin); (void) portable_changes_add(changes, n_changes, PORTABLE_SYMLINK, dropin, from); } @@ -1351,15 +1359,23 @@ static int attach_unit_file( if ((flags & PORTABLE_PREFER_SYMLINK) && m->source) { - if (symlink(m->source, path) < 0) - return log_debug_errno(errno, "Failed to symlink unit file '%s': %m", path); + if (flags & PORTABLE_FORCE_ATTACH) + r = symlink_atomic(m->source, path); + else + r = RET_NERRNO(symlink(m->source, path)); + if (r < 0) + return log_debug_errno(r, "Failed to symlink unit file '%s': %m", path); (void) portable_changes_add(changes, n_changes, PORTABLE_SYMLINK, path, m->source); } else { + LinkTmpfileFlags link_flags = LINK_TMPFILE_SYNC; _cleanup_(unlink_and_freep) char *tmp = NULL; _cleanup_close_ int fd = -EBADF; + if (flags & PORTABLE_FORCE_ATTACH) + link_flags |= LINK_TMPFILE_REPLACE; + (void) mac_selinux_create_file_prepare_label(path, m->selinux_label); fd = open_tmpfile_linkable(path, O_WRONLY|O_CLOEXEC, &tmp); @@ -1374,7 +1390,7 @@ static int attach_unit_file( if (fchmod(fd, 0644) < 0) return log_debug_errno(errno, "Failed to change unit file access mode for '%s': %m", path); - r = link_tmpfile(fd, tmp, path, LINK_TMPFILE_SYNC); + r = link_tmpfile(fd, tmp, path, link_flags); if (r < 0) return log_debug_errno(r, "Failed to install unit file '%s': %m", path); diff --git a/test/units/TEST-29-PORTABLE.sh b/test/units/TEST-29-PORTABLE.sh index 41dce4d48a0..501d492c7d9 100755 --- a/test/units/TEST-29-PORTABLE.sh +++ b/test/units/TEST-29-PORTABLE.sh @@ -73,6 +73,21 @@ busctl tree org.freedesktop.portable1 --no-pager | grep -q -F '/org/freedesktop/ # Ensure we don't regress (again) when using --force +mkdir -p /run/systemd/system.attached/minimal-app0.service.d/ +cat </run/systemd/system.attached/minimal-app0.service +[Unit] +Description=Minimal App 0 +EOF +cat </run/systemd/system.attached/minimal-app0.service.d/10-profile.conf +[Unit] +Description=Minimal App 0 +EOF +cat </run/systemd/system.attached/minimal-app0.service.d/20-portable.conf +[Unit] +Description=Minimal App 0 +EOF +systemctl daemon-reload + portablectl "${ARGS[@]}" attach --force --now --runtime /usr/share/minimal_0.raw minimal-app0 portablectl is-attached --force minimal-app0 @@ -302,6 +317,28 @@ systemctl is-active app1.service portablectl detach --now --runtime overlay app1 +# Ensure --force works also when symlinking +mkdir -p /run/systemd/system.attached/app1.service.d +cat </run/systemd/system.attached/app1.service +[Unit] +Description=App 1 +EOF +cat </run/systemd/system.attached/app1.service.d/10-profile.conf +[Unit] +Description=App 1 +EOF +cat </run/systemd/system.attached/app1.service.d/20-portable.conf +[Unit] +Description=App 1 +EOF +systemctl daemon-reload + +portablectl "${ARGS[@]}" attach --force --copy=symlink --now --runtime /tmp/overlay app1 + +systemctl is-active app1.service + +portablectl detach --now --runtime overlay app1 + umount /tmp/overlay portablectl "${ARGS[@]}" attach --copy=symlink --now --runtime --extension /tmp/app0 --extension /tmp/app1 /tmp/rootdir app0 app1