From dfbf9cdcef15cfa61385d6b0b6471aca0e0a99ea Mon Sep 17 00:00:00 2001 From: Johannes Schauer Marin Rodrigues Date: Tue, 17 Aug 2021 23:39:20 +0200 Subject: [PATCH] several fixes to chrootless mode --- coverage.sh | 14 ++++---------- mmdebstrap | 50 ++++++++++++++++++++++++++++++++------------------ 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/coverage.sh b/coverage.sh index 3421526..61223c9 100755 --- a/coverage.sh +++ b/coverage.sh @@ -405,7 +405,7 @@ diff --no-dereference --recursive /tmp/debian-debootstrap /tmp/debian-mm # check permissions, ownership, symlink targets, modification times using tar # mtimes of directories created by mmdebstrap will differ, thus we equalize them first -for d in etc/apt/preferences.d/ etc/apt/sources.list.d/ etc/dpkg/dpkg.cfg.d/; do +for d in etc/apt/preferences.d/ etc/apt/sources.list.d/ etc/dpkg/dpkg.cfg.d/ var/log/apt/; do touch --date="@$SOURCE_DATE_EPOCH" /tmp/debian-debootstrap/\$d /tmp/debian-mm/\$d done # debootstrap never ran apt -- fixing permissions @@ -3321,8 +3321,6 @@ fi prefix= [ "\$(id -u)" -eq 0 ] && prefix="runuser -u user --" \$prefix $CMD --mode=chrootless --variant=custom --include=doc-debian $DEFAULT_DIST /tmp/debian-chroot $mirror -# preserve output with permissions and timestamps for later test -chmod 700 /tmp/debian-chroot tar -C /tmp/debian-chroot --owner=0 --group=0 --numeric-owner --sort=name --clamp-mtime --mtime=$(date --utc --date=@$SOURCE_DATE_EPOCH --iso-8601=seconds) -cf /tmp/debian-chroot.tar . tar tvf /tmp/debian-chroot.tar > doc-debian.tar.list rm /tmp/debian-chroot.tar @@ -3340,7 +3338,6 @@ rm /tmp/debian-chroot/var/cache/apt/archives/lock rm /tmp/debian-chroot/var/lib/dpkg/lock rm /tmp/debian-chroot/var/lib/dpkg/lock-frontend rm /tmp/debian-chroot/var/lib/apt/lists/lock -rm /tmp/debian-chroot/var/lib/apt/extended_states if [ "$mode" != "chrootless" ] || dpkg --compare-versions "\$(dpkg --robot --version)" lt 1.20.0; then rm /tmp/debian-chroot/var/lib/dpkg/available rm /tmp/debian-chroot/var/lib/dpkg/cmethopt @@ -3467,10 +3464,9 @@ if [ "\$(id -u)" -eq 0 ] && ! id -u user > /dev/null 2>&1; then fi prefix= [ "\$(id -u)" -eq 0 ] && prefix="runuser -u user --" -\$prefix $CMD --mode=chrootless --variant=custom --include=doc-debian --setup-hook='touch "\$1/setup"' --customize-hook='touch "\$1/customize"' $DEFAULT_DIST /tmp/debian-chroot $mirror -rm /tmp/debian-chroot/setup -rm /tmp/debian-chroot/customize -chmod 700 /tmp/debian-chroot +\$prefix $CMD --mode=chrootless --skip=cleanup/tmp --variant=custom --include=doc-debian --setup-hook='touch "\$1/tmp/setup"' --customize-hook='touch "\$1/tmp/customize"' $DEFAULT_DIST /tmp/debian-chroot $mirror +rm /tmp/debian-chroot/tmp/setup +rm /tmp/debian-chroot/tmp/customize tar -C /tmp/debian-chroot --owner=0 --group=0 --numeric-owner --sort=name --clamp-mtime --mtime=$(date --utc --date=@$SOURCE_DATE_EPOCH --iso-8601=seconds) -cf /tmp/debian-chroot.tar . tar tvf /tmp/debian-chroot.tar | grep -v ' ./dev' | diff -u doc-debian.tar.list - rm /tmp/debian-chroot.tar @@ -3488,7 +3484,6 @@ rm /tmp/debian-chroot/var/cache/apt/archives/lock rm /tmp/debian-chroot/var/lib/dpkg/lock rm /tmp/debian-chroot/var/lib/dpkg/lock-frontend rm /tmp/debian-chroot/var/lib/apt/lists/lock -rm /tmp/debian-chroot/var/lib/apt/extended_states if dpkg --compare-versions "\$(dpkg --robot --version)" lt 1.20.0; then rm /tmp/debian-chroot/var/lib/dpkg/available rm /tmp/debian-chroot/var/lib/dpkg/cmethopt @@ -3551,7 +3546,6 @@ rm /tmp/debian-chroot/var/cache/apt/archives/lock rm /tmp/debian-chroot/var/lib/dpkg/lock rm /tmp/debian-chroot/var/lib/dpkg/lock-frontend rm /tmp/debian-chroot/var/lib/apt/lists/lock -rm /tmp/debian-chroot/var/lib/apt/extended_states if dpkg --compare-versions "\$(dpkg --robot --version)" lt 1.20.0; then rm /tmp/debian-chroot/var/lib/dpkg/available rm /tmp/debian-chroot/var/lib/dpkg/cmethopt diff --git a/mmdebstrap b/mmdebstrap index 1752943..ab019a4 100755 --- a/mmdebstrap +++ b/mmdebstrap @@ -1461,15 +1461,13 @@ sub setup { (my $pkgs_to_install, my $essential_pkgs, my $cached_debs) = run_download($options); - if ( $options->{mode} ne 'chrootless' - or $options->{variant} eq 'extract') { - # We have to extract the packages from @essential_pkgs either if we run - # in chrootless mode and extract variant or in any other mode. In - # other words, the only scenario in which the @essential_pkgs are not - # extracted are in chrootless mode in any other than the extract - # variant. - run_extract($options, $essential_pkgs); - } + # in theory, we don't have to extract the packages in chrootless mode + # but we do it anyways because otherwise directory creation timestamps + # will differ compared to non-chrootless and we want to create bit-by-bit + # identical tar output + # + # FIXME: dpkg could be changed to produce the same results + run_extract($options, $essential_pkgs); run_hooks('extract', $options); @@ -1552,8 +1550,10 @@ sub run_setup() { } # if dpkg and apt operate from the outside we need some more # directories because dpkg and apt might not even be installed inside - # the chroot - if ($options->{mode} eq 'chrootless') { + # the chroot. Thus, the following block is not strictly necessary in + # chrootless mode. We unconditionally add it anyways, so that the + # output with and without chrootless mode is equal. + { push @directories, '/var/log/apt'; # since we do not know the dpkg version inside the chroot at this # point, we can only omit it in chrootless mode @@ -2818,10 +2818,23 @@ sub run_essential() { $ENV{QEMU_LD_PREFIX} = $options->{root}; } } - run_apt_progress({ - ARGV => ['apt-get', '--yes', @chrootless_opts, 'install'], - PKGS => [map { "$options->{root}/$_" } @{$essential_pkgs}], - }); + # we don't use apt because that will not run the base-passwd preinst + # early enough + #run_apt_progress({ + # ARGV => ['apt-get', '--yes', @chrootless_opts, 'install'], + # PKGS => [map { "$options->{root}/$_" } @{$essential_pkgs}], + #}); + run_dpkg_progress({ + ARGV => [ + 'dpkg', + '--force-not-root', + '--force-script-chrootless', + "--root=$options->{root}", + "--log=$options->{root}/var/log/dpkg.log", + '--install', + '--force-depends' + ], + PKGS => [map { "$options->{root}/$_" } @{$essential_pkgs}] }); } elsif ( any { $_ eq $options->{mode} } ('root', 'unshare', 'fakechroot', 'proot') @@ -5278,7 +5291,9 @@ sub main() { # in unshare and root mode, other users than the current user need to # access the rootfs, most prominently, the _apt user. Thus, make the # temporary directory world readable. - if (any { $_ eq $options->{mode} } ('unshare', 'root')) { + if (any { $_ eq $options->{mode} } ('unshare', 'root') + or + ($EFFECTIVE_USER_ID == 0 and $options->{mode} eq 'chrootless')) { chmod 0755, $options->{root} or error "cannot chmod root: $!"; } } elsif ($format eq 'directory') { @@ -6667,8 +6682,7 @@ the required priority. =item B -Extract the downloaded packages into the rootfs. This step is not carried out -in chrootless mode if the variant is not B. +Extract the downloaded packages into the rootfs. =item B