Compare commits

...

6 commits

5 changed files with 106 additions and 58 deletions

View file

@ -1,3 +1,8 @@
1.5.2 (2024-06-26)
------------------
- mmdebstrap-autopkgtest-build-qemu produces bit-by-bit reproducible output
1.5.1 (2024-06-03) 1.5.1 (2024-06-03)
------------------ ------------------

View file

@ -158,16 +158,19 @@ Contributors
- Johannes Schauer Marin Rodrigues (main author) - Johannes Schauer Marin Rodrigues (main author)
- Helmut Grohne - Helmut Grohne
- Jochen Sprickerhof
- Gioele Barabucci - Gioele Barabucci
- Benjamin Drung - Benjamin Drung
- Jochen Sprickerhof
- Josh Triplett - Josh Triplett
- Konstantin Demin - Konstantin Demin
- Chris Hofstaedtler
- Colin Watson
- David Kalnischkies - David Kalnischkies
- Emilio Pozuelo Monfort - Emilio Pozuelo Monfort
- Francesco Poli - Francesco Poli
- Jakub Wilk - Jakub Wilk
- Joe Groocock - Joe Groocock
- Max-Julian Pogner
- Nicolas Vigier - Nicolas Vigier
- Raul Tambre - Raul Tambre
- Steve Dodd - Steve Dodd

View file

@ -23,7 +23,7 @@
use strict; use strict;
use warnings; use warnings;
our $VERSION = '1.5.1'; our $VERSION = '1.5.2';
use English; use English;
use Getopt::Long; use Getopt::Long;
@ -4293,8 +4293,8 @@ sub get_sourceslist_by_suite {
# the security mirror changes, starting with bullseye # the security mirror changes, starting with bullseye
# https://lists.debian.org/87r26wqr2a.fsf@43-1.org # https://lists.debian.org/87r26wqr2a.fsf@43-1.org
my $bullseye_or_later = 0; my $bullseye_or_later = 0;
if (any { $_ eq $suite } ('oldstable', 'stable', 'bullseye', 'bookworm', 'trixie')) if (any { $_ eq $suite }
{ ('oldstable', 'stable', 'bullseye', 'bookworm', 'trixie')) {
$bullseye_or_later = 1; $bullseye_or_later = 1;
} }
my $distro_info = '/usr/share/distro-info/debian.csv'; my $distro_info = '/usr/share/distro-info/debian.csv';
@ -6973,13 +6973,29 @@ The above uses C<--map-auto> to map the block of user/group ids for the
effective user/group to a block starting at user/group ID 0. We also want to effective user/group to a block starting at user/group ID 0. We also want to
map the current effective user/group ID into the subuid/subgid range using map the current effective user/group ID into the subuid/subgid range using
C<--map-user> and C<--map-group>, respectively. But if that uid/gid overlaps C<--map-user> and C<--map-group>, respectively. But if that uid/gid overlaps
with the respective range, a "hole" will be removed from the mapping and the with the respective range, a "hole" will be removed from the mapping by the
remaining uid/gid values will get shifted. Thus, we map the current effective L<unshare(1)> utility and the remaining uid/gid values will get shifted. Thus,
user/group ID to the highest possible uid/gid, putting them at the end. Since we map the current effective user/group ID to the highest possible uid/gid,
that means that the user/group will be "nobody" and not "root" inside the putting them at the end. Since that means that the user/group will be "nobody"
namespace, C<--keep-caps> propagate permitted capabilities into the ambient set and not "root" inside the namespace, C<--keep-caps> propagate permitted
and thus give the user C<CAP_DAC_OVERRIDE> and other capabilities that it capabilities into the ambient set and thus give the user C<CAP_DAC_OVERRIDE>
would've had. and other capabilities that it would've had. The following does B<NOT> work:
$ unshare --map-root-user --map-auto ... # or equavalient:
$ unshare --map-user=0 --map-group=0 --map-users=auto --map-groups=auto ...
Using the format of L<lxc-usernsexec(1)>, these options will result in the
following mapping:
0:$UID:1 + 1:$SUBUIDBASE:65535
So a hole is punched in the automatically mapped range at the very beginning to
make space for the user id of the current user as root inside the namespace and
the remaining uids are shifted. With C<--map-user=65536> the mapping is as
follows and places the current user at the end of the range, preventing any
shifting:
0:$SUBUIDBASE:65536 + 65536:$UID:1
Lastly, if you don't mind using superuser privileges and have systemd-nspawn Lastly, if you don't mind using superuser privileges and have systemd-nspawn
available and you know your subuid/subgid offset (100000 in this example): available and you know your subuid/subgid offset (100000 in this example):

View file

@ -29,10 +29,11 @@ B<mmdebstrap-autopkgtest-build-qemu> [I<OPTIONS>] B<--boot>=B<efi> I<RELEASE> I<
B<mmdebstrap-autopkgtest-build-qemu> is a mostly compatible drop-in replacement B<mmdebstrap-autopkgtest-build-qemu> is a mostly compatible drop-in replacement
for L<autopkgtest-build-qemu(1)> with two main differences: Firstly, it uses for L<autopkgtest-build-qemu(1)> with two main differences: Firstly, it uses
L<mmdebstrap(1)> instead of L<vmdb2(1)> and thus is able to create QEMU disk L<mmdebstrap(1)> instead of L<vmdb2(1)> and thus is able to create QEMU disk
images without requiring superuser privileges. Secondly, it uses images without requiring superuser privileges and with bit-by-bit reproducible
L<systemd-boot(7)> and thus only supports booting via EFI. For architectures output. Secondly, it uses L<systemd-boot(7)> and thus only supports booting via
for which L<autopkgtest-virt-qemu(1)> does not default to EFI booting you must EFI. For architectures for which L<autopkgtest-virt-qemu(1)> does not default
pass B<--boot=efi> when invoking the autopkgtest virt backend. to EFI booting you must pass B<--boot=efi> when invoking the autopkgtest virt
backend.
=head1 POSITIONAL PARAMETERS =head1 POSITIONAL PARAMETERS
@ -110,6 +111,12 @@ all path components or by creating the image in a world-readable directory like
Make sure to add B<--boot=efi> to both the B<mmdebstrap-autopkgtest-build-qemu> Make sure to add B<--boot=efi> to both the B<mmdebstrap-autopkgtest-build-qemu>
as well as the B<autopkgtest-virt-qemu> invocation. as well as the B<autopkgtest-virt-qemu> invocation.
Create bit-by-bit reproducible images from a given snapshot.d.o timestamp.
SOURCE_DATE_EPOCH=1612543740 mmdebstrap-autopkgtest-build-qemu --boot=efi \
--mirror=http://snapshot.debian.org/archive/debian/20210205T164900Z/ \
unstable /path/to/debian-unstable.img
=head1 SEE ALSO =head1 SEE ALSO
L<autopkgtest-build-qemu(1)>, L<autopkgtest-virt-qemu(1)>, L<mmdebstrap(1)>, L<autopkgtest(1)> L<autopkgtest-build-qemu(1)>, L<autopkgtest-virt-qemu(1)>, L<mmdebstrap(1)>, L<autopkgtest(1)>
@ -273,7 +280,7 @@ test_installed() {
fi fi
} }
for pkg in autopkgtest dosfstools e2fsprogs fdisk mount mtools passwd uidmap; do for pkg in autopkgtest dosfstools e2fsprogs fdisk mount mtools passwd uidmap libarchive13; do
test_installed "$pkg" test_installed "$pkg"
done done
@ -320,33 +327,24 @@ FAT_SIZE_SECTORS=$((1024*254))
# - snapshots and overlays work just as well with raw images # - snapshots and overlays work just as well with raw images
# - users who prefer qcow2 get to choose to run it themselves with their own # - users who prefer qcow2 get to choose to run it themselves with their own
# custom options like compression # custom options like compression
#
# --map-users=auto --map-user=0 => 0:$UID:1 + 1:$SUBUIDBASE:65535
# --map-users=auto --map-user=65536 => 0:$SUBUIDBASE:65536 + 65536:$UID:1
#
# Make the image writeable to the first subgid. mmdebstrap will map this gid to
# the root group. unshare instead will map the current gid to 0 and the first
# subgid to 1. Therefore mmdebstrap will be able to write to the image.
rm -f "$IMAGE"
: >"$IMAGE"
unshare --map-user=0 --map-group=0 --map-groups=auto chown 0:1 "$IMAGE"
chmod 0660 "$IMAGE"
# Make sure that the unshared user is able to access the file.
# Alternatively to using /sbin/mkfs.ext4 could use --format=ext2 which would
# add an extra copy operation and come with the limitations of ext2.
# Another solution: https://github.com/tytso/e2fsprogs/pull/118
if ! mmdebstrap --unshare-helper touch "$IMAGE"; then
die "$IMAGE cannot be accessed by the unshared user -- either make all path components up to the image itself world-executable or place the image into a world-readable path like /tmp"
fi
set -- \ set -- \
--mode=unshare \ --mode=unshare \
--format=tar \
--variant=important \ --variant=important \
--architecture="$ARCHITECTURE" --architecture="$ARCHITECTURE"
test "$RELEASE" = jessie && case $MIRROR in http://snapshot.debian.org/archive/*|https://snapshot.debian.org/archive/*)
set -- "$@" --aptopt='Acquire::Check-Valid-Until "false"';;
esac
EXT_FEATURES=
if test "$RELEASE" = jessie; then
set -- "$@" --keyring=/usr/share/keyrings/debian-archive-removed-keys.gpg
set -- "$@" --aptopt='Apt::Key::gpgvcommand "/usr/libexec/mmdebstrap/gpgvnoexpkeysig"'
set -- "$@" --hook-dir=/usr/share/mmdebstrap/hooks/jessie-or-older set -- "$@" --hook-dir=/usr/share/mmdebstrap/hooks/jessie-or-older
EXT_FEATURES="^metadata_csum,^metadata_csum_seed,^orphan_file"
fi
set -- "$@" \ set -- "$@" \
"--include=init,$LINUXIMAGE,python3" \ "--include=init,$LINUXIMAGE,python3" \
@ -364,30 +362,35 @@ if test -n "$SCRIPT"; then
'--customize-hook=rm -f "$1/userscript"' '--customize-hook=rm -f "$1/userscript"'
fi fi
EXT4_OFFSET_BYTES=$(( (FAT_OFFSET_SECTORS + FAT_SIZE_SECTORS) * 512))
EXT4_OPTIONS="offset=$EXT4_OFFSET_BYTES,assume_storage_prezeroed=1"
# the --no-mtab option to mount is a workaround for https://github.com/util-linux/util-linux/issues/2981
# revert 8c0ddc32660ca4e98c988966251f9c05d6bcccef once it is no longer needed
set -- "$@" \ set -- "$@" \
"--customize-hook=download vmlinuz '$WORKDIR/kernel'" \ "--customize-hook=download vmlinuz '$WORKDIR/kernel'" \
"--customize-hook=download initrd.img '$WORKDIR/initrd'" \ "--customize-hook=download initrd.img '$WORKDIR/initrd'" \
'--customize-hook=mount --no-mtab --bind "$1" "$1/mnt"' \
'--customize-hook=mount --no-mtab --bind "$1/mnt/mnt" "$1/mnt/dev"' \
'--customize-hook=/sbin/mkfs.ext4 -d "$1/mnt" -L autopkgtestvm -E '"'$EXT4_OPTIONS' '$IMAGE' '$SIZE'" \
'--customize-hook=umount --lazy --no-mtab "$1/mnt/dev"' \
'--customize-hook=umount --lazy --no-mtab "$1/mnt"' \
"$RELEASE" \ "$RELEASE" \
/dev/null -
test -n "$MIRROR" && set -- "$@" "$MIRROR" test -n "$MIRROR" && set -- "$@" "$MIRROR"
test -n "$KEYRING" && set -- "$@" "--keyring=$KEYRING" test -n "$KEYRING" && set -- "$@" "--keyring=$KEYRING"
echo "mmdebstrap $*" echo "+ mmdebstrap $*" >&2
mmdebstrap "$@" || die "mmdebstrap failed" # https://github.com/koalaman/shellcheck/issues/2555
# shellcheck disable=SC3040
set -o pipefail
mmdebstrap "$@" | {
set -- -t ext4 -L autopkgtestvm -d -
if test -n "$EXT_FEATURES"; then
set -- "$@" -O "$EXT_FEATURES"
fi
EXTOPTS="offset=$(( (FAT_OFFSET_SECTORS + FAT_SIZE_SECTORS) * 512))"
if test -n "${SOURCE_DATE_EPOCH:-}"; then
uuid="$(uuidgen --sha1 --namespace="$(uuidgen --sha1 --namespace='@dns' --name mister-muffin.de)" --name "$SOURCE_DATE_EPOCH")"
set -- "$@" -U "$uuid"
EXTOPTS="$EXTOPTS,hash_seed=$uuid"
fi
set -- "$@" -E "$EXTOPTS" "$IMAGE" "$SIZE"
echo "+ mke2fs $*" >&2
/sbin/mke2fs "$@"
}
unshare -U -r --map-groups=auto chown 0:0 "$IMAGE"
chmod "$(printf %o "$(( 0666 & ~0$(umask) ))")" "$IMAGE"
echo "root=LABEL=autopkgtestvm rw console=ttyS0" > "$WORKDIR/cmdline" echo "root=LABEL=autopkgtestvm rw console=ttyS0" > "$WORKDIR/cmdline"
@ -461,4 +464,5 @@ if test -n "$VMFPKG" && test "$(dpkg-query -f '${db:Status-Status}' -W "$VMFPKG"
echo "I: you might need to install $VMFPKG to use this image with autopkgtest-virt-qemu" >&2 echo "I: you might need to install $VMFPKG to use this image with autopkgtest-virt-qemu" >&2
fi fi
echo "I: don't forget to pass --boot=efi when running autopkgtest-virt-qemu with this image" >&2 echo "I: SUCCESS! Your new image can be found here: $IMAGE" >&2
echo "I: Don't forget to pass --boot=efi when running autopkgtest-virt-qemu with this image" >&2

View file

@ -157,24 +157,44 @@ if [ "{{ VARIANT }}" = "-" ] && [ "{{ DIST}}" = oldstable ]; then
fi fi
for log in faillog lastlog; do for log in faillog lastlog; do
if ! cmp /tmp/debian-{{ DIST }}-debootstrap/var/log/$log /tmp/debian-{{ DIST }}-mm/var/log/$log >&2;then f1="/tmp/debian-{{ DIST }}-debootstrap/var/log/$log"
f2="/tmp/debian-{{ DIST }}-mm/var/log/$log"
# skip cmp if file is absent in both chroots
if [ ! -e "$f1" ] && [ ! -e "$f2" ]; then
continue
fi
if ! cmp "$f1" "$f2" >&2;then
# if the files differ, make sure they are all zeroes # if the files differ, make sure they are all zeroes
cmp -n "$(stat -c %s "/tmp/debian-{{ DIST }}-debootstrap/var/log/$log")" "/tmp/debian-{{ DIST }}-debootstrap/var/log/$log" /dev/zero >&2 cmp -n "$(stat -c %s "$f1")" "$f1" /dev/zero >&2
cmp -n "$(stat -c %s "/tmp/debian-{{ DIST }}-mm/var/log/$log")" "/tmp/debian-{{ DIST }}-mm/var/log/$log" /dev/zero >&2 cmp -n "$(stat -c %s "$f2")" "$f2" /dev/zero >&2
# then delete them # then delete them
rm /tmp/debian-{{ DIST }}-debootstrap/var/log/$log /tmp/debian-{{ DIST }}-mm/var/log/$log rm "$f1" "$f2"
fi fi
done done
# the order in which systemd and cron get installed differ and thus the order
# of lines in /etc/group and /etc/gshadow differs
if [ "{{ VARIANT }}" = "-" ]; then if [ "{{ VARIANT }}" = "-" ]; then
# the order in which systemd and cron get installed differ and thus the order
# of lines in /etc/group and /etc/gshadow differs
for f in group group- gshadow gshadow-; do for f in group group- gshadow gshadow-; do
for d in mm debootstrap; do for d in mm debootstrap; do
sort /tmp/debian-{{ DIST }}-$d/etc/$f > /tmp/debian-{{ DIST }}-$d/etc/$f.bak sort /tmp/debian-{{ DIST }}-$d/etc/$f > /tmp/debian-{{ DIST }}-$d/etc/$f.bak
mv /tmp/debian-{{ DIST }}-$d/etc/$f.bak /tmp/debian-{{ DIST }}-$d/etc/$f mv /tmp/debian-{{ DIST }}-$d/etc/$f.bak /tmp/debian-{{ DIST }}-$d/etc/$f
done done
done done
# the order in which systemd and passwd get installed differ and thus
# the order of lines in /etc/shadow and /etc/shadow- differs
for f in shadow shadow-; do
for d in mm debootstrap; do
sort /tmp/debian-{{ DIST }}-$d/etc/$f > /tmp/debian-{{ DIST }}-$d/etc/$f.bak
mv /tmp/debian-{{ DIST }}-$d/etc/$f.bak /tmp/debian-{{ DIST }}-$d/etc/$f
done
done
# and since the order was different, ignore the *- files
for f in shadow- passwd-; do
for d in mm debootstrap; do
rm /tmp/debian-{{ DIST }}-$d/etc/$f
done
done
fi fi
# since debootstrap 1.0.133 there is no tzdata in the buildd variant and thus # since debootstrap 1.0.133 there is no tzdata in the buildd variant and thus