From 6a8fbae9d81d0bc30cdd472c2918154737406d63 Mon Sep 17 00:00:00 2001 From: Johannes Schauer Marin Rodrigues Date: Fri, 27 Aug 2021 19:50:11 +0200 Subject: [PATCH] make fakechroot mode bit-by-bit identical to the others --- coverage.sh | 38 ++++++++++++----------------------- mmdebstrap | 58 ++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 62 insertions(+), 34 deletions(-) diff --git a/coverage.sh b/coverage.sh index 361c406..8df1c51 100755 --- a/coverage.sh +++ b/coverage.sh @@ -753,7 +753,15 @@ else fi runuser -u user -- $CMD --mode=unshare --variant=$variant $DEFAULT_DIST /tmp/debian-chroot-unshare.$format $mirror cmp /tmp/debian-chroot-root.$format /tmp/debian-chroot-unshare.$format -rm /tmp/debian-chroot-root.$format /tmp/debian-chroot-unshare.$format +rm /tmp/debian-chroot-unshare.$format +case $variant in essential|apt|minbase) + # /etc/ld.so.cache differs with some variants + runuser -u user -- $CMD --mode=fakechroot --variant=$variant $DEFAULT_DIST /tmp/debian-chroot-fakechroot.$format $mirror + cmp /tmp/debian-chroot-root.$format /tmp/debian-chroot-fakechroot.$format + rm /tmp/debian-chroot-fakechroot.$format + ;; +esac +rm /tmp/debian-chroot-root.$format END if [ "$HAVE_QEMU" = "yes" ]; then ./run_qemu.sh @@ -1208,12 +1216,7 @@ prefix= mkdir /tmp/mnt mount /tmp/debian-chroot.ext2 /tmp/mnt rmdir /tmp/mnt/lost+found -# in fakechroot mode, we use a fake ldconfig, so we have to -# artificially add some files -{ tar -C /tmp/mnt -c . | tar -t; - [ "$mode" = "fakechroot" ] && printf "./etc/ld.so.cache\n./var/cache/ldconfig/\n"; - [ "$mode" = "fakechroot" ] && printf "./etc/.pwd.lock\n"; -} | sort | diff -u tar1.txt - +tar -C /tmp/mnt -c . | tar -t | sort | diff -u tar1.txt - umount /tmp/mnt rmdir /tmp/mnt rm /tmp/debian-chroot.ext2 @@ -1239,9 +1242,7 @@ fi adduser --gecos user --disabled-password user sysctl -w kernel.unprivileged_userns_clone=0 runuser -u user -- $CMD --mode=auto --variant=apt $DEFAULT_DIST /tmp/debian-chroot.tar.gz $mirror -{ tar -tf /tmp/debian-chroot.tar.gz; - printf "./etc/ld.so.cache\n./var/cache/ldconfig/\n./etc/.pwd.lock\n"; -} | sort | diff -u tar1.txt - +tar -tf /tmp/debian-chroot.tar.gz | sort | diff -u tar1.txt - rm /tmp/debian-chroot.tar.gz END if [ "$HAVE_QEMU" = "yes" ]; then @@ -2651,12 +2652,7 @@ echo upload-customize | cmp /tmp/download-customize - echo sync-in-setup | cmp /tmp/sync-out-setup/file - echo sync-in-essential | cmp /tmp/sync-out-essential/file - echo sync-in-customize | cmp /tmp/sync-out-customize/file - -# in fakechroot mode, we use a fake ldconfig, so we have to -# artificially add some files -{ tar -tf /tmp/debian-chroot.tar; - [ "$mode" = "fakechroot" ] && printf "./etc/ld.so.cache\n./var/cache/ldconfig/\n"; - [ "$mode" = "fakechroot" ] && [ "$variant" != "essential" ] && printf "./etc/.pwd.lock\n"; -} | sort | diff -u tar1.txt - +tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt - rm /tmp/debian-chroot.tar \ /tmp/copy-in-setup /tmp/copy-in-essential /tmp/copy-in-customize \ /tmp/copy-out-setup /tmp/copy-out-essential /tmp/copy-out-customize \ @@ -3192,12 +3188,7 @@ fi prefix= [ "\$(id -u)" -eq 0 ] && prefix="runuser -u user --" \$prefix $CMD --mode=$mode --variant=$variant $DEFAULT_DIST /tmp/debian-chroot.tar $mirror -# in fakechroot mode, we use a fake ldconfig, so we have to -# artificially add some files -{ tar -tf /tmp/debian-chroot.tar; - [ "$mode" = "fakechroot" ] && printf "./etc/ld.so.cache\n./var/cache/ldconfig/\n"; - [ "$mode" = "fakechroot" ] && [ "$variant" != "essential" ] && printf "./etc/.pwd.lock\n"; -} | sort | diff -u "./$variant.txt" - +tar -tf /tmp/debian-chroot.tar | sort | diff -u "./$variant.txt" - rm /tmp/debian-chroot.tar END if [ "$HAVE_QEMU" = "yes" ]; then @@ -3714,8 +3705,6 @@ prefix= \$prefix $CMD --mode=$mode --variant=apt --architectures=arm64 $DEFAULT_DIST /tmp/debian-chroot.tar $mirror # we ignore differences between architectures by ignoring some files # and renaming others -# in fakechroot mode, we use a fake ldconfig, so we have to -# artificially add some files # in proot mode, some extra files are put there by proot { tar -tf /tmp/debian-chroot.tar \ | grep -v '^\./lib/ld-linux-aarch64\.so\.1$' \ @@ -3723,7 +3712,6 @@ prefix= | grep -v '^\./usr/share/doc/[^/]\+/changelog\(\.Debian\)\?\.arm64\.gz$' \ | sed 's/aarch64-linux-gnu/x86_64-linux-gnu/' \ | sed 's/arm64/amd64/'; - [ "$mode" = "fakechroot" ] && printf "./etc/ld.so.cache\n./var/cache/ldconfig/\n./etc/.pwd.lock\n"; } | sort > tar2.txt { cat tar1.txt \ | grep -v '^\./usr/bin/i386$' \ diff --git a/mmdebstrap b/mmdebstrap index 5948388..77730bd 100755 --- a/mmdebstrap +++ b/mmdebstrap @@ -251,6 +251,24 @@ sub get_tar_compressor { return; } +# avoid dependency on String::ShellQuote by implementing the mechanism +# from python's shlex.quote function +sub shellescape { + my $string = shift; + if (length $string == 0) { + return "''"; + } + # search for occurrences of characters that are not safe + # the 'a' regex modifier makes sure that \w only matches ASCII + if ($string !~ m/[^\w@\%+=:,.\/-]/a) { + return $string; + } + # wrap the string in single quotes and handle existing single quotes by + # putting them outside of the single-quoted string + $string =~ s/'/'"'"'/g; + return "'$string'"; +} + sub test_unshare_userns { my $verbose = shift; if ($EFFECTIVE_USER_ID == 0) { @@ -1977,16 +1995,15 @@ sub run_setup() { copy($tmpfile, \*STDERR); } - if (any { $_ eq $options->{mode} } ('fakechroot', 'proot')) { + if (none { $_ eq $options->{mode} } ('fakechroot', 'proot')) { # Apt dropping privileges to another user than root is not useful in # fakechroot and proot mode because all users are faked and thus there - # is no real privilege difference anyways. Thus, we also print no - # warning message in this case. - open my $fh, '>>', $tmpfile - or error "cannot open $tmpfile for appending: $!"; - print $fh "APT::Sandbox::User \"root\";\n"; - close $fh; - } else { + # is no real privilege difference anyways. We could set + # APT::Sandbox::User "root" in fakechroot and proot mode but we don't + # because if we would, then /var/cache/apt/archives/partial/ and + # /var/lib/apt/lists/partial/ would not be owned by the _apt user + # if mmdebstrap was run in fakechroot or proot mode. + # # when apt-get update is run by the root user, then apt will attempt to # drop privileges to the _apt user. This will fail if the _apt user # does not have permissions to read the root directory. In that case, @@ -2643,11 +2660,28 @@ sub run_prepare { # /etc/fakechroot/debootstrap.env and # /etc/fakechroot/chroot.env { + # we add "$@" before "-r" such that any other "-r" options will be + # overwritten by the one we set + my $escapedroot = shellescape $options->{root}; + my ($fh, $filename) = tempfile( + "mmdebstrap.ldconfig.XXXXXXXXXXXX", + UNLINK => 1, + TMPDIR => 1 + ); + print $fh <{mode} eq 'fakechroot') { + # By default, FAKECHROOT_EXCLUDE_PATH includes /proc and + # /sys which means that the resulting tarball will contain + # the permission and ownership information of /proc and + # /sys from the outside, which we want to avoid. + ## no critic (Variables::RequireLocalizedPunctuationVars) + $ENV{FAKECHROOT_EXCLUDE_PATH} = "/dev"; # Fakechroot requires tar to run inside the chroot or # otherwise absolute symlinks will include the path to the # root directory