Package: mmdebstrap Version: 1.5.7-3 Severity: normal Tags: upstream fixed-upstream X-Debbugs-Cc: [email protected]
Hi Josch, During use of Debusine, I was faced with a very strange piuparts error. The relevant workrequest sadly is private, but the gist is that debsums was complaining about a checksum error for start-stop-daemon. After a while, I investigated the base image passed to piuparts and ran dpkg --verify there. It was also unhappy about start-stop-daemon. This image was created using mmdebstrap and this is where we get into the problem I am trying to report. The distribution at hand was Ubuntu xenial. It is a bit special in that it presently has a dpkg security update. What happened here is roughly this: * All essential packages are extracted (without the security update). * mmdebstrap replaces start-stop-daemon. * Remaining packages are installed and this includes the dpkg security update. * mmdebstrap moves back the replaced start-stop-daemon. A relatively simple way to reproduce this is simulating a dist-upgrade. mmdebstrap --variant=apt bookworm /tmp/upgraded.tar --chrooted-customize-hook='sed -i -e s/bookworm/trixie/ /etc/apt/sources.list && apt-get update && apt-get dist-upgrade' The problem happens after the customization stage, so we actually need to emit some image and run dpkg --verify inside to see the problem. Beyond this, I don't think the replacement of start-stop-daemon ever worked as intended, because start-stop-daemon is being replaced before the essential packages unpacked, so dpkg overwrites it. | mmdebstrap --variant=essential sid /dev/null --chrooted-customize-hook='ls -la /sbin/start-stop-daemon*' ... | I: running --chrooted-customize-hook in shell: sh -c 'ls -la /sbin/start-stop-daemon*' | -rwxr-xr-x 1 root root 44464 Jun 30 23:32 /sbin/start-stop-daemon | -rwxr-xr-x 1 root root 44464 Jun 30 23:32 /sbin/start-stop-daemon.REAL As far as I can see, the proper solution here is using dpkg-divert and creating local diversions, no? Of course this code is cargo culted from debootstrap and likely exists to maximize compatibility with it. deboostrap cannot easily use diversions, so there is that. Replacing start-stop-daemon is also something we haven't needed in a long time. Since moving to systemd, we aren't using start-stop-daemon much at all and even before, sysvinit was already using invoke-rc.d and policy-rc.d for a long time. Is this code actually needed still? My impression is that you would like to retain compatibility with very old releases where this is still needed and diversions should work there. We've discussed this on IRC now and you've already applied the attached patch to your develop upstream branch despite it failing the salsa-ci pipeline for bsdutils having become non-essential. Thank you. I'm attaching a copy for reference. Helmut
>From de180f97e354fdda3ead4657eb82d8ce611da485 Mon Sep 17 00:00:00 2001 From: Helmut Grohne <[email protected]> Date: Sat, 22 Nov 2025 08:09:37 +0100 Subject: [PATCH] Divert start-stop-daemon If we just replace it with something else, a later unpack operation of dpkg may overwrite our replacement. Our cleanup may then destroy intended changes. --- mmdebstrap | 59 +++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 45 insertions(+), 14 deletions(-) diff --git a/mmdebstrap b/mmdebstrap index 075582e..8fe5874 100755 --- a/mmdebstrap +++ b/mmdebstrap @@ -2601,34 +2601,64 @@ sub setup_mounts { # the file might not exist if it was removed in a hook if (any { $_ eq 'chroot/start-stop-daemon' } @{ $options->{skip} }) { info "skipping chroot/start-stop-daemon as requested"; + } elsif ($options->{dryrun}) { + info "skipping start-stop-daemon because of --dryrun"; } else { # $options->{root} must not be part of $ssdloc but must instead be # evaluated at the time the cleanup is run or otherwise, when # performing a pivot-root, the ssd location will still be prefixed # with the chroot path even though we changed root + # + # On merged-/usr, it can exist in both places. We still want the + # location according to the dpkg-database. At this time, neither + # usrmerge.postinst nor the merged-usr hook's post-merging + # extract hook have been run, so /sbin can only be a link if it is + # a file in base-files at that point, ssd must be below /usr. my $ssdloc; - if (-f "$options->{root}/sbin/start-stop-daemon") { + if (-f "$options->{root}/sbin/start-stop-daemon" + && !-l "$options->{root}/sbin") { $ssdloc = "/sbin/start-stop-daemon"; } elsif (-f "$options->{root}/usr/sbin/start-stop-daemon") { $ssdloc = "/usr/sbin/start-stop-daemon"; } + my @ssd_diversions = ([ + "/usr/sbin/start-stop-daemon", + "/usr/sbin/start-stop-daemon.REAL" + ], + [ + "/sbin/start-stop-daemon", + "/sbin/start-stop-daemon.REAL.usr-is-merged", + ], + ); + if ($ssdloc eq "/sbin/start-stop-daemon") { + @ssd_diversions = reverse @ssd_diversions; + } + for my $pair (@ssd_diversions) { + my ($diverted, $divertto) = @$pair; + 0 == system( + "dpkg-divert", "--root", $options->{root}, + "--local", "--rename", "--divert", + $divertto, "--add", $diverted + ) or die "failed to divert $diverted: $?"; + } + # Remove diversions in reverse order; + @ssd_diversions = reverse @ssd_diversions; + push @cleanup_tasks, sub { - return unless length $ssdloc; - if (-e "$options->{root}/$ssdloc.REAL") { - move( - "$options->{root}/$ssdloc.REAL", - "$options->{root}/$ssdloc" - ) or error "cannot move start-stop-daemon: $!"; + if (length $ssdloc and -e "$options->{root}/$ssdloc") { + unlink "$options->{root}/$ssdloc" + or error "cannot remove start-stop-daemon: $!"; + } + for my $pair (@ssd_diversions) { + my ($diverted, $divertto) = @$pair; + 0 == system( + "dpkg-divert", "--root", $options->{root}, + "--local", "--rename", "--divert", + $divertto, "--remove", $diverted + ) or die "failed to divert $diverted: $?"; } }; if (length $ssdloc) { - if (-e "$options->{root}/$ssdloc.REAL") { - error "$options->{root}/$ssdloc.REAL already exists"; - } - move( - "$options->{root}/$ssdloc", - "$options->{root}/$ssdloc.REAL" - ) or error "cannot move start-stop-daemon: $!"; open my $fh, '>', "$options->{root}/$ssdloc" or error "cannot open start-stop-daemon: $!"; print $fh "#!/bin/sh\n"; -- 2.50.1

