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.

(cherry picked from commit 1e2d1a7202)
This commit is contained in:
Luca Boccassi 2024-08-30 17:55:18 +01:00 committed by Mike Yuan
parent a2c84836ef
commit 2552348da2
2 changed files with 59 additions and 6 deletions

View File

@ -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);

View File

@ -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 <<EOF >/run/systemd/system.attached/minimal-app0.service
[Unit]
Description=Minimal App 0
EOF
cat <<EOF >/run/systemd/system.attached/minimal-app0.service.d/10-profile.conf
[Unit]
Description=Minimal App 0
EOF
cat <<EOF >/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 <<EOF >/run/systemd/system.attached/app1.service
[Unit]
Description=App 1
EOF
cat <<EOF >/run/systemd/system.attached/app1.service.d/10-profile.conf
[Unit]
Description=App 1
EOF
cat <<EOF >/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