forked from josch/mmdebstrap
Compare commits
20 commits
dd774b4f20
...
81d155cac8
Author | SHA1 | Date | |
---|---|---|---|
81d155cac8 | |||
b3338bd33b | |||
71a9a2e7a9 | |||
19a2ec044a | |||
af95b4d778 | |||
4d44b9dbbe | |||
846662276f | |||
9a19801095 | |||
9710ee16a0 | |||
8db443a6c4 | |||
ff9b76ed19 | |||
|
a719ffd20a | ||
55cae49ec7 | |||
055e1719b9 | |||
2614924925 | |||
901d017099 | |||
6b49a2dbbf | |||
034698f8d3 | |||
a184cc003c | |||
8253daf403 |
17 changed files with 287 additions and 143 deletions
10
CHANGELOG.md
10
CHANGELOG.md
|
@ -1,3 +1,13 @@
|
||||||
|
1.3.5 (2023-03-20)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- bugfix release
|
||||||
|
|
||||||
|
1.3.4 (2023-03-16)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
- more safeguards before automatically choosing unshare mode
|
||||||
|
|
||||||
1.3.3 (2023-02-19)
|
1.3.3 (2023-02-19)
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
|
|
@ -152,13 +152,14 @@ Contributors
|
||||||
============
|
============
|
||||||
|
|
||||||
- Johannes Schauer Marin Rodrigues (main author)
|
- Johannes Schauer Marin Rodrigues (main author)
|
||||||
- Gioele Barabucci
|
|
||||||
- Helmut Grohne
|
- Helmut Grohne
|
||||||
|
- Gioele Barabucci
|
||||||
- Benjamin Drung
|
- Benjamin Drung
|
||||||
- Jochen Sprickerhof
|
- Jochen Sprickerhof
|
||||||
- Josh Triplett
|
- Josh Triplett
|
||||||
- Konstantin Demin
|
- Konstantin Demin
|
||||||
- David Kalnischkies
|
- David Kalnischkies
|
||||||
|
- Jakub Wilk
|
||||||
- Joe Groocock
|
- Joe Groocock
|
||||||
- Nicolas Vigier
|
- Nicolas Vigier
|
||||||
- Raul Tambre
|
- Raul Tambre
|
||||||
|
|
|
@ -69,7 +69,7 @@ mirror="http://127.0.0.1/debian"
|
||||||
|
|
||||||
export HAVE_QEMU HAVE_BINFMT RUN_MA_SAME_TESTS DEFAULT_DIST SOURCE_DATE_EPOCH CMD mirror
|
export HAVE_QEMU HAVE_BINFMT RUN_MA_SAME_TESTS DEFAULT_DIST SOURCE_DATE_EPOCH CMD mirror
|
||||||
|
|
||||||
./coverage.py
|
./coverage.py "$@"
|
||||||
|
|
||||||
if [ -e shared/cover_db.img ]; then
|
if [ -e shared/cover_db.img ]; then
|
||||||
# produce report inside the VM to make sure that the versions match or
|
# produce report inside the VM to make sure that the versions match or
|
||||||
|
|
11
coverage.txt
11
coverage.txt
|
@ -283,10 +283,16 @@ Test: debootstrap-no-op-options
|
||||||
Needs-Root: true
|
Needs-Root: true
|
||||||
|
|
||||||
Test: verbose
|
Test: verbose
|
||||||
Needs-Root: true
|
Variants: - standard
|
||||||
|
Skip-If:
|
||||||
|
variant == "-" and hostarch not in ["armel", "armhf", "mipsel"] # #1031276
|
||||||
|
variant == "standard" and hostarch in ["armel", "armhf", "mipsel"] # #1031276
|
||||||
|
|
||||||
Test: debug
|
Test: debug
|
||||||
Needs-Root: true
|
Variants: - standard
|
||||||
|
Skip-If:
|
||||||
|
variant == "-" and hostarch not in ["armel", "armhf", "mipsel"] # #1031276
|
||||||
|
variant == "standard" and hostarch in ["armel", "armhf", "mipsel"] # #1031276
|
||||||
|
|
||||||
Test: quiet
|
Test: quiet
|
||||||
Needs-Root: true
|
Needs-Root: true
|
||||||
|
@ -396,6 +402,7 @@ Test: error-if-stdout-is-tty
|
||||||
Test: variant-custom-timeout
|
Test: variant-custom-timeout
|
||||||
|
|
||||||
Test: include-deb-file
|
Test: include-deb-file
|
||||||
|
Modes: root unshare fakechroot
|
||||||
Needs-APT-Config: true
|
Needs-APT-Config: true
|
||||||
|
|
||||||
Test: unshare-include-deb
|
Test: unshare-include-deb
|
||||||
|
|
|
@ -14,6 +14,10 @@ env APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" apt-get indextargets --no-release-info -
|
||||||
| sort -u \
|
| sort -u \
|
||||||
| while read -r path; do
|
| while read -r path; do
|
||||||
mkdir -p "$rootdir/run/mmdebstrap"
|
mkdir -p "$rootdir/run/mmdebstrap"
|
||||||
|
if [ ! -d "/$path" ]; then
|
||||||
|
echo "/$path is not an existing directory" >&2
|
||||||
|
continue
|
||||||
|
fi
|
||||||
case $MMDEBSTRAP_MODE in
|
case $MMDEBSTRAP_MODE in
|
||||||
root|unshare)
|
root|unshare)
|
||||||
echo "bind-mounting /$path into the chroot" >&2
|
echo "bind-mounting /$path into the chroot" >&2
|
||||||
|
@ -22,8 +26,8 @@ env APT_CONFIG="$MMDEBSTRAP_APT_CONFIG" apt-get indextargets --no-release-info -
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "copying /$path into the chroot" >&2
|
echo "copying /$path into the chroot" >&2
|
||||||
mkdir -p "$rootdir/$(dirname "$path")"
|
mkdir -p "$rootdir/$path"
|
||||||
cp -av "/$path" "$rootdir/$(dirname "$path")"
|
"$MMDEBSTRAP_ARGV0" --hook-helper "$rootdir" "$MMDEBSTRAP_MODE" "$MMDEBSTRAP_HOOK" env "$MMDEBSTRAP_VERBOSITY" sync-in "/$path" "/$path" <&"$MMDEBSTRAP_HOOKSOCK" >&"$MMDEBSTRAP_HOOKSOCK"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
printf '/%s\0' "$path" >> "$rootdir/run/mmdebstrap/file-mirror-automount"
|
printf '/%s\0' "$path" >> "$rootdir/run/mmdebstrap/file-mirror-automount"
|
||||||
|
@ -47,6 +51,10 @@ for pkg in $MMDEBSTRAP_INCLUDE; do
|
||||||
fi
|
fi
|
||||||
# make path absolute
|
# make path absolute
|
||||||
pkg="$(realpath "$pkg")"
|
pkg="$(realpath "$pkg")"
|
||||||
|
case "$pkg" in
|
||||||
|
/*) : ;;
|
||||||
|
*) echo "path for $pkg is not absolute" >&2; continue;;
|
||||||
|
esac
|
||||||
mkdir -p "$rootdir/run/mmdebstrap"
|
mkdir -p "$rootdir/run/mmdebstrap"
|
||||||
mkdir -p "$rootdir/$(dirname "$pkg")"
|
mkdir -p "$rootdir/$(dirname "$pkg")"
|
||||||
case $MMDEBSTRAP_MODE in
|
case $MMDEBSTRAP_MODE in
|
||||||
|
@ -57,7 +65,7 @@ for pkg in $MMDEBSTRAP_INCLUDE; do
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "copying $pkg into the chroot" >&2
|
echo "copying $pkg into the chroot" >&2
|
||||||
cp -av "$pkg" "$rootdir/$pkg"
|
"$MMDEBSTRAP_ARGV0" --hook-helper "$rootdir" "$MMDEBSTRAP_MODE" "$MMDEBSTRAP_HOOK" env "$MMDEBSTRAP_VERBOSITY" upload "$pkg" "$pkg" <&"$MMDEBSTRAP_HOOKSOCK" >&"$MMDEBSTRAP_HOOKSOCK"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
printf '/%s\0' "$pkg" >> "$rootdir/run/mmdebstrap/file-mirror-automount"
|
printf '/%s\0' "$pkg" >> "$rootdir/run/mmdebstrap/file-mirror-automount"
|
||||||
|
|
|
@ -20,7 +20,10 @@ deletecache() {
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
# be very careful with removing the old directory
|
# be very careful with removing the old directory
|
||||||
for dist in oldstable stable testing unstable; do
|
# experimental is pulled in with USE_HOST_APT_CONFIG=yes on debci
|
||||||
|
# when testing a package from experimental
|
||||||
|
for dist in oldstable stable testing unstable experimental; do
|
||||||
|
# deleting artifacts from test "debootstrap"
|
||||||
for variant in minbase buildd -; do
|
for variant in minbase buildd -; do
|
||||||
if [ -e "$dir/debian-$dist-$variant.tar" ]; then
|
if [ -e "$dir/debian-$dist-$variant.tar" ]; then
|
||||||
rm "$dir/debian-$dist-$variant.tar"
|
rm "$dir/debian-$dist-$variant.tar"
|
||||||
|
@ -28,6 +31,18 @@ deletecache() {
|
||||||
echo "does not exist: $dir/debian-$dist-$variant.tar" >&2
|
echo "does not exist: $dir/debian-$dist-$variant.tar" >&2
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
# deleting artifacts from test "mmdebstrap"
|
||||||
|
for variant in essential apt minbase buildd - standard; do
|
||||||
|
for format in tar ext2 squashfs; do
|
||||||
|
if [ -e "$dir/mmdebstrap-$dist-$variant.$format" ]; then
|
||||||
|
# attempt to delete for all dists because DEFAULT_DIST might've been different the last time
|
||||||
|
rm "$dir/mmdebstrap-$dist-$variant.$format"
|
||||||
|
elif [ "$dist" = "$DEFAULT_DIST" ]; then
|
||||||
|
# only warn about non-existance when it's expected to exist
|
||||||
|
echo "does not exist: $dir/mmdebstrap-$dist-$variant.$format" >&2
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
done
|
||||||
if [ -e "$dir/debian/dists/$dist" ]; then
|
if [ -e "$dir/debian/dists/$dist" ]; then
|
||||||
rm --one-file-system --recursive "$dir/debian/dists/$dist"
|
rm --one-file-system --recursive "$dir/debian/dists/$dist"
|
||||||
else
|
else
|
||||||
|
@ -63,11 +78,16 @@ deletecache() {
|
||||||
rm --one-file-system "$f"
|
rm --one-file-system "$f"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
if [ -e "$dir/debian/pool/main" ]; then
|
# on i386 and amd64, the intel-microcode and amd64-microcode packages
|
||||||
rm --one-file-system --recursive "$dir/debian/pool/main"
|
# from non-free-firwame get pulled in because they are
|
||||||
else
|
# priority:standard with USE_HOST_APT_CONFIG=yes
|
||||||
echo "does not exist: $dir/debian/pool/main" >&2
|
for c in main non-free-firmware; do
|
||||||
fi
|
if [ -e "$dir/debian/pool/$c" ]; then
|
||||||
|
rm --one-file-system --recursive "$dir/debian/pool/$c"
|
||||||
|
else
|
||||||
|
echo "does not exist: $dir/debian/pool/$c" >&2
|
||||||
|
fi
|
||||||
|
done
|
||||||
if [ -e "$dir/debian-security/pool/updates/main" ]; then
|
if [ -e "$dir/debian-security/pool/updates/main" ]; then
|
||||||
rm --one-file-system --recursive "$dir/debian-security/pool/updates/main"
|
rm --one-file-system --recursive "$dir/debian-security/pool/updates/main"
|
||||||
else
|
else
|
||||||
|
|
248
mmdebstrap
248
mmdebstrap
|
@ -23,7 +23,7 @@
|
||||||
use strict;
|
use strict;
|
||||||
use warnings;
|
use warnings;
|
||||||
|
|
||||||
our $VERSION = '1.3.3';
|
our $VERSION = '1.3.5';
|
||||||
|
|
||||||
use English;
|
use English;
|
||||||
use Getopt::Long;
|
use Getopt::Long;
|
||||||
|
@ -304,15 +304,19 @@ sub shellescape {
|
||||||
}
|
}
|
||||||
|
|
||||||
sub test_unshare_userns {
|
sub test_unshare_userns {
|
||||||
my $verbose = shift;
|
my $verbose = shift;
|
||||||
my $unshare_fail = shift;
|
|
||||||
if ($EFFECTIVE_USER_ID == 0) {
|
local *maybe_error = sub {
|
||||||
my $msg = "cannot unshare user namespace when executing as root";
|
my $msg = shift;
|
||||||
if ($verbose) {
|
if ($verbose) {
|
||||||
warning $msg;
|
error $msg;
|
||||||
} else {
|
} else {
|
||||||
debug $msg;
|
debug $msg;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if ($EFFECTIVE_USER_ID == 0) {
|
||||||
|
maybe_error("cannot unshare user namespace when executing as root");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
# arguments to syscalls have to be stored in their own variable or
|
# arguments to syscalls have to be stored in their own variable or
|
||||||
|
@ -326,12 +330,7 @@ sub test_unshare_userns {
|
||||||
if ($ret == 0) {
|
if ($ret == 0) {
|
||||||
exit 0;
|
exit 0;
|
||||||
} else {
|
} else {
|
||||||
my $msg = "unshare syscall failed: $!";
|
maybe_error("unshare syscall failed: $!");
|
||||||
if ($verbose) {
|
|
||||||
warning $msg;
|
|
||||||
} else {
|
|
||||||
debug $msg;
|
|
||||||
}
|
|
||||||
exit 1;
|
exit 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -344,120 +343,140 @@ sub test_unshare_userns {
|
||||||
system "newuidmap 2>/dev/null";
|
system "newuidmap 2>/dev/null";
|
||||||
if (($? >> 8) != 1) {
|
if (($? >> 8) != 1) {
|
||||||
if (($? >> 8) == 127) {
|
if (($? >> 8) == 127) {
|
||||||
my $msg = "cannot find newuidmap";
|
maybe_error("cannot find newuidmap");
|
||||||
if ($verbose) {
|
|
||||||
if ($unshare_fail) {
|
|
||||||
error $msg;
|
|
||||||
} else {
|
|
||||||
warning $msg;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
debug $msg;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
my $msg = "newuidmap returned unknown exit status: $?";
|
maybe_error("newuidmap returned unknown exit status: $?");
|
||||||
if ($verbose) {
|
|
||||||
warning $msg;
|
|
||||||
} else {
|
|
||||||
debug $msg;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
system "newgidmap 2>/dev/null";
|
system "newgidmap 2>/dev/null";
|
||||||
if (($? >> 8) != 1) {
|
if (($? >> 8) != 1) {
|
||||||
if (($? >> 8) == 127) {
|
if (($? >> 8) == 127) {
|
||||||
my $msg = "cannot find newgidmap";
|
maybe_error("cannot find newgidmap");
|
||||||
if ($verbose) {
|
|
||||||
warning $msg;
|
|
||||||
} else {
|
|
||||||
debug $msg;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
my $msg = "newgidmap returned unknown exit status: $?";
|
maybe_error("newgidmap returned unknown exit status: $?");
|
||||||
if ($verbose) {
|
|
||||||
warning $msg;
|
|
||||||
} else {
|
|
||||||
debug $msg;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
my @idmap = read_subuid_subgid($verbose);
|
||||||
|
if (scalar @idmap == 0) {
|
||||||
|
maybe_error("failed to parse /etc/subuid and /etc/subgid");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
# too much can go wrong when doing the dance required to unsharing the user
|
||||||
|
# namespace, so instead of adding more complexity to support maybe_error()
|
||||||
|
# to a function that is already too complex, we use eval()
|
||||||
|
eval {
|
||||||
|
$pid = get_unshare_cmd(
|
||||||
|
sub {
|
||||||
|
if ($EFFECTIVE_USER_ID == 0) {
|
||||||
|
exit 0;
|
||||||
|
} else {
|
||||||
|
exit 1;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
\@idmap
|
||||||
|
);
|
||||||
|
waitpid $pid, 0;
|
||||||
|
if ($? != 0) {
|
||||||
|
maybe_error("failed to unshare the user namespace");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
if ($@) {
|
||||||
|
maybe_error($@);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub read_subuid_subgid() {
|
sub read_subuid_subgid {
|
||||||
|
my $verbose = shift;
|
||||||
|
my @result = ();
|
||||||
my $username = getpwuid $REAL_USER_ID;
|
my $username = getpwuid $REAL_USER_ID;
|
||||||
my ($subid, $num_subid, $fh, $n);
|
my ($subid, $num_subid, $fh, $n);
|
||||||
my @result = ();
|
|
||||||
|
|
||||||
|
local *maybe_warn = sub {
|
||||||
|
my $msg = shift;
|
||||||
|
if ($verbose) {
|
||||||
|
warning $msg;
|
||||||
|
} else {
|
||||||
|
debug $msg;
|
||||||
|
}
|
||||||
|
};
|
||||||
if (!-e "/etc/subuid") {
|
if (!-e "/etc/subuid") {
|
||||||
warning "/etc/subuid doesn't exist";
|
maybe_warn("/etc/subuid doesn't exist");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!-r "/etc/subuid") {
|
if (!-r "/etc/subuid") {
|
||||||
warning "/etc/subuid is not readable";
|
maybe_warn("/etc/subuid is not readable");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
open $fh, "<", "/etc/subuid"
|
open $fh, "<", "/etc/subuid"
|
||||||
or error "cannot open /etc/subuid for reading: $!";
|
or maybe_warn("cannot open /etc/subuid for reading: $!");
|
||||||
|
if (!$fh) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
while (my $line = <$fh>) {
|
while (my $line = <$fh>) {
|
||||||
($n, $subid, $num_subid) = split(/:/, $line, 3);
|
($n, $subid, $num_subid) = split(/:/, $line, 3);
|
||||||
last if ($n eq $username);
|
last if ($n eq $username);
|
||||||
}
|
}
|
||||||
close $fh;
|
close $fh;
|
||||||
if (!length $subid) {
|
if (!length $subid) {
|
||||||
warning "/etc/subuid is empty";
|
maybe_warn("/etc/subuid is empty");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ($n ne $username) {
|
if ($n ne $username) {
|
||||||
warning "no entry in /etc/subuid for $username";
|
maybe_warn("no entry in /etc/subuid for $username");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
push @result, ["u", 0, $subid, $num_subid];
|
push @result, ["u", 0, $subid, $num_subid];
|
||||||
|
|
||||||
if (scalar(@result) < 1) {
|
if (scalar(@result) < 1) {
|
||||||
warning "/etc/subuid does not contain an entry for $username";
|
maybe_warn("/etc/subuid does not contain an entry for $username");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (scalar(@result) > 1) {
|
if (scalar(@result) > 1) {
|
||||||
warning "/etc/subuid contains multiple entries for $username";
|
maybe_warn("/etc/subuid contains multiple entries for $username");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!-e "/etc/subgid") {
|
if (!-e "/etc/subgid") {
|
||||||
warning "/etc/subgid doesn't exist";
|
maybe_warn("/etc/subgid doesn't exist");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!-r "/etc/subgid") {
|
if (!-r "/etc/subgid") {
|
||||||
warning "/etc/subgid is not readable";
|
maybe_warn("/etc/subgid is not readable");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
open $fh, "<", "/etc/subgid"
|
open $fh, "<", "/etc/subgid"
|
||||||
or error "cannot open /etc/subgid for reading: $!";
|
or maybe_warn("cannot open /etc/subgid for reading: $!");
|
||||||
|
if (!$fh) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
while (my $line = <$fh>) {
|
while (my $line = <$fh>) {
|
||||||
($n, $subid, $num_subid) = split(/:/, $line, 3);
|
($n, $subid, $num_subid) = split(/:/, $line, 3);
|
||||||
last if ($n eq $username);
|
last if ($n eq $username);
|
||||||
}
|
}
|
||||||
close $fh;
|
close $fh;
|
||||||
if (!length $subid) {
|
if (!length $subid) {
|
||||||
warning "/etc/subgid is empty";
|
maybe_warn("/etc/subgid is empty");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ($n ne $username) {
|
if ($n ne $username) {
|
||||||
warning "no entry in /etc/subgid for $username";
|
maybe_warn("no entry in /etc/subgid for $username");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
push @result, ["g", 0, $subid, $num_subid];
|
push @result, ["g", 0, $subid, $num_subid];
|
||||||
|
|
||||||
if (scalar(@result) < 2) {
|
if (scalar(@result) < 2) {
|
||||||
warning "/etc/subgid does not contain an entry for $username";
|
maybe_warn("/etc/subgid does not contain an entry for $username");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (scalar(@result) > 2) {
|
if (scalar(@result) > 2) {
|
||||||
warning "/etc/subgid contains multiple entries for $username";
|
maybe_warn("/etc/subgid contains multiple entries for $username");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1594,6 +1613,9 @@ sub run_hooks {
|
||||||
if (length $ENV{APT_CONFIG}) {
|
if (length $ENV{APT_CONFIG}) {
|
||||||
push @env_opts, "MMDEBSTRAP_APT_CONFIG=$ENV{APT_CONFIG}";
|
push @env_opts, "MMDEBSTRAP_APT_CONFIG=$ENV{APT_CONFIG}";
|
||||||
}
|
}
|
||||||
|
# I hook script that wants to call mmdebstrap with --hook-helper needs to
|
||||||
|
# know how mmdebstrap was executed
|
||||||
|
push @env_opts, "MMDEBSTRAP_ARGV0=$PROGRAM_NAME";
|
||||||
# Storing the mode is important for hook scripts to potentially change
|
# Storing the mode is important for hook scripts to potentially change
|
||||||
# their behavior depending on the mode. It's also important for when the
|
# their behavior depending on the mode. It's also important for when the
|
||||||
# hook wants to use the mmdebstrap --hook-helper.
|
# hook wants to use the mmdebstrap --hook-helper.
|
||||||
|
@ -1801,6 +1823,25 @@ sub setup {
|
||||||
|
|
||||||
run_hooks('setup', $options);
|
run_hooks('setup', $options);
|
||||||
|
|
||||||
|
# apt runs dpkg from inside the chroot and directly passes the filename to
|
||||||
|
# dpkg. Hence, the included files on the outside must be present under the
|
||||||
|
# same path on the inside. If they are not, dpkg cannot find them.
|
||||||
|
if (scalar(grep { /^\// } @{ $options->{include} }) > 0) {
|
||||||
|
my $ret = 0;
|
||||||
|
foreach my $f (grep { /^\// } @{ $options->{include} }) {
|
||||||
|
next if -e "$options->{root}/$f";
|
||||||
|
warning
|
||||||
|
"path given via --include is not present inside the chroot: $f";
|
||||||
|
$ret = 1;
|
||||||
|
}
|
||||||
|
if ($ret != 0) {
|
||||||
|
warning("apt runs chrooted dpkg which needs access to the "
|
||||||
|
. "package paths given via --include inside the chroot.");
|
||||||
|
warning "maybe try running mmdebstrap with "
|
||||||
|
. "--hook-dir=/usr/share/mmdebstrap/hooks/file-mirror-automount";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (any { $_ eq 'update' } @{ $options->{skip} }) {
|
if (any { $_ eq 'update' } @{ $options->{skip} }) {
|
||||||
info "skipping update as requested";
|
info "skipping update as requested";
|
||||||
} else {
|
} else {
|
||||||
|
@ -2246,7 +2287,7 @@ sub run_setup() {
|
||||||
# we have to make the config file world readable so that a possible
|
# we have to make the config file world readable so that a possible
|
||||||
# /usr/lib/apt/solvers/apt process which is run by the _apt user is also
|
# /usr/lib/apt/solvers/apt process which is run by the _apt user is also
|
||||||
# able to read it
|
# able to read it
|
||||||
chmod 0666, "$tmpfile" or error "cannot chmod $tmpfile: $!";
|
chmod 0644, "$tmpfile" or error "cannot chmod $tmpfile: $!";
|
||||||
if ($verbosity_level >= 3) {
|
if ($verbosity_level >= 3) {
|
||||||
0 == system('apt-get', '--version')
|
0 == system('apt-get', '--version')
|
||||||
or error "apt-get --version failed: $?";
|
or error "apt-get --version failed: $?";
|
||||||
|
@ -4348,12 +4389,12 @@ sub main() {
|
||||||
# lxc-usernsexec -- lxc-unshare -s 'MOUNT|PID|UTSNAME|IPC' ...
|
# lxc-usernsexec -- lxc-unshare -s 'MOUNT|PID|UTSNAME|IPC' ...
|
||||||
# but without needing lxc
|
# but without needing lxc
|
||||||
if (scalar @ARGV >= 1 && $ARGV[0] eq "--unshare-helper") {
|
if (scalar @ARGV >= 1 && $ARGV[0] eq "--unshare-helper") {
|
||||||
if ($EFFECTIVE_USER_ID != 0 && !test_unshare_userns(1)) {
|
if ($EFFECTIVE_USER_ID != 0) {
|
||||||
exit 1;
|
test_unshare_userns(1);
|
||||||
}
|
}
|
||||||
my @idmap = ();
|
my @idmap = ();
|
||||||
if ($EFFECTIVE_USER_ID != 0) {
|
if ($EFFECTIVE_USER_ID != 0) {
|
||||||
@idmap = read_subuid_subgid;
|
@idmap = read_subuid_subgid 1;
|
||||||
}
|
}
|
||||||
my $pid = get_unshare_cmd(
|
my $pid = get_unshare_cmd(
|
||||||
sub {
|
sub {
|
||||||
|
@ -4423,10 +4464,8 @@ sub main() {
|
||||||
my ($opt_name, $opt_value) = @_;
|
my ($opt_name, $opt_value) = @_;
|
||||||
my $sanitize_path = sub {
|
my $sanitize_path = sub {
|
||||||
my $pkg = shift;
|
my $pkg = shift;
|
||||||
$pkg = abs_path($pkg);
|
$pkg = abs_path($pkg)
|
||||||
if (!defined $pkg) {
|
// error "cannot resolve absolute path of $pkg: $!";
|
||||||
error "cannot resolve absolute path of $pkg: $!";
|
|
||||||
}
|
|
||||||
if ($pkg !~ /^\//) {
|
if ($pkg !~ /^\//) {
|
||||||
error "absolute path of $pkg doesn't start with a slash";
|
error "absolute path of $pkg doesn't start with a slash";
|
||||||
}
|
}
|
||||||
|
@ -4781,7 +4820,8 @@ sub main() {
|
||||||
}
|
}
|
||||||
exec 'fakechroot', 'fakeroot', @prefix, $PROGRAM_NAME, @ARGVORIG;
|
exec 'fakechroot', 'fakeroot', @prefix, $PROGRAM_NAME, @ARGVORIG;
|
||||||
} else {
|
} else {
|
||||||
error "unable to pick chroot mode automatically";
|
error( "unable to pick chroot mode automatically (use --mode for "
|
||||||
|
. "manual selection)");
|
||||||
}
|
}
|
||||||
info "automatically chosen mode: $options->{mode}";
|
info "automatically chosen mode: $options->{mode}";
|
||||||
} elsif ($options->{mode} eq 'root') {
|
} elsif ($options->{mode} eq 'root') {
|
||||||
|
@ -4816,26 +4856,8 @@ sub main() {
|
||||||
}
|
}
|
||||||
# ...or we are not root and then we need to be able to unshare the user
|
# ...or we are not root and then we need to be able to unshare the user
|
||||||
# namespace.
|
# namespace.
|
||||||
if ($EFFECTIVE_USER_ID != 0 && !test_unshare_userns(1, 1)) {
|
if ($EFFECTIVE_USER_ID != 0) {
|
||||||
my $procfile = '/proc/sys/kernel/unprivileged_userns_clone';
|
test_unshare_userns(1);
|
||||||
open(my $fh, '<', $procfile)
|
|
||||||
or error "failed to open $procfile: $!";
|
|
||||||
chomp(
|
|
||||||
my $content = do { local $/; <$fh> }
|
|
||||||
);
|
|
||||||
close($fh);
|
|
||||||
if ($content ne "1") {
|
|
||||||
info "/proc/sys/kernel/unprivileged_userns_clone is set to"
|
|
||||||
. " $content";
|
|
||||||
info "Try running:";
|
|
||||||
info " sudo sysctl -w kernel.unprivileged_userns_clone=1";
|
|
||||||
info "or permanently enable unprivileged usernamespaces by"
|
|
||||||
. " putting the setting into /etc/sysctl.d/";
|
|
||||||
info "THIS SETTING HAS SECURITY IMPLICATIONS!";
|
|
||||||
info "Refer to https://bugs.debian.org/cgi-bin/"
|
|
||||||
. "bugreport.cgi?bug=898446";
|
|
||||||
}
|
|
||||||
exit 1;
|
|
||||||
}
|
}
|
||||||
} elsif ($options->{mode} eq 'chrootless') {
|
} elsif ($options->{mode} eq 'chrootless') {
|
||||||
if ($EFFECTIVE_USER_ID == 0) {
|
if ($EFFECTIVE_USER_ID == 0) {
|
||||||
|
@ -5171,12 +5193,14 @@ sub main() {
|
||||||
my $keyring
|
my $keyring
|
||||||
= get_keyring_by_suite($options->{suite}, \%suite_by_vendor);
|
= get_keyring_by_suite($options->{suite}, \%suite_by_vendor);
|
||||||
if (!defined $keyring) {
|
if (!defined $keyring) {
|
||||||
|
debug "get_keyring_by_suite() cannot find keyring";
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
# we can only check if we need the signed-by entry if we u
|
# we can only check if we need the signed-by entry if we u
|
||||||
# automatically chosen keyring exists
|
# automatically chosen keyring exists
|
||||||
if (!defined $keyring || !-e $keyring) {
|
if (!defined $keyring || !-e $keyring) {
|
||||||
|
debug "found keyring does not exist";
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5221,7 +5245,7 @@ sub main() {
|
||||||
# find all the fingerprints of the keys apt currently
|
# find all the fingerprints of the keys apt currently
|
||||||
# knows about
|
# knows about
|
||||||
my @keyrings = ();
|
my @keyrings = ();
|
||||||
opendir my $dh, "$options->{apttrustedparts}"
|
opendir my $dh, $options->{apttrustedparts}
|
||||||
or error "cannot read $options->{apttrustedparts}";
|
or error "cannot read $options->{apttrustedparts}";
|
||||||
while (my $filename = readdir $dh) {
|
while (my $filename = readdir $dh) {
|
||||||
if ($filename !~ /\.(asc|gpg)$/) {
|
if ($filename !~ /\.(asc|gpg)$/) {
|
||||||
|
@ -5230,7 +5254,7 @@ sub main() {
|
||||||
$filename = "$options->{apttrustedparts}/$filename";
|
$filename = "$options->{apttrustedparts}/$filename";
|
||||||
# skip empty keyrings
|
# skip empty keyrings
|
||||||
-s "$filename" || next;
|
-s "$filename" || next;
|
||||||
push @keyrings, "$filename";
|
push @keyrings, $filename;
|
||||||
}
|
}
|
||||||
closedir $dh;
|
closedir $dh;
|
||||||
if (-s $options->{apttrusted}) {
|
if (-s $options->{apttrusted}) {
|
||||||
|
@ -5238,6 +5262,7 @@ sub main() {
|
||||||
}
|
}
|
||||||
my @aptfingerprints = ();
|
my @aptfingerprints = ();
|
||||||
if (scalar @keyrings == 0) {
|
if (scalar @keyrings == 0) {
|
||||||
|
debug "no keyring is trusted by apt";
|
||||||
return " [signed-by=\"$keyring\"]";
|
return " [signed-by=\"$keyring\"]";
|
||||||
}
|
}
|
||||||
info "finding correct signed-by value...";
|
info "finding correct signed-by value...";
|
||||||
|
@ -5261,6 +5286,7 @@ sub main() {
|
||||||
}
|
}
|
||||||
print_progress("done");
|
print_progress("done");
|
||||||
if (scalar @aptfingerprints == 0) {
|
if (scalar @aptfingerprints == 0) {
|
||||||
|
debug "no fingerprints found";
|
||||||
return " [signed-by=\"$keyring\"]";
|
return " [signed-by=\"$keyring\"]";
|
||||||
}
|
}
|
||||||
# check if all fingerprints from the keyring that we guessed
|
# check if all fingerprints from the keyring that we guessed
|
||||||
|
@ -5277,6 +5303,7 @@ sub main() {
|
||||||
# if this fingerprint is not known by apt, then we need
|
# if this fingerprint is not known by apt, then we need
|
||||||
#to add the signed-by option
|
#to add the signed-by option
|
||||||
if (none { $_ eq $1 } @aptfingerprints) {
|
if (none { $_ eq $1 } @aptfingerprints) {
|
||||||
|
debug "fingerprint $1 is not trusted by apt";
|
||||||
return " [signed-by=\"$keyring\"]";
|
return " [signed-by=\"$keyring\"]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5665,7 +5692,7 @@ sub main() {
|
||||||
# for unshare mode the rootfs directory has to have appropriate
|
# for unshare mode the rootfs directory has to have appropriate
|
||||||
# permissions
|
# permissions
|
||||||
if ($EFFECTIVE_USER_ID != 0 and $options->{mode} eq 'unshare') {
|
if ($EFFECTIVE_USER_ID != 0 and $options->{mode} eq 'unshare') {
|
||||||
@idmap = read_subuid_subgid;
|
@idmap = read_subuid_subgid 1;
|
||||||
# sanity check
|
# sanity check
|
||||||
if ( scalar(@idmap) != 2
|
if ( scalar(@idmap) != 2
|
||||||
|| $idmap[0][0] ne 'u'
|
|| $idmap[0][0] ne 'u'
|
||||||
|
@ -5712,9 +5739,9 @@ sub main() {
|
||||||
);
|
);
|
||||||
waitpid $pid, 0;
|
waitpid $pid, 0;
|
||||||
if ($? != 0) {
|
if ($? != 0) {
|
||||||
warning "no read access for some packages for the unshared user";
|
warning("apt on the outside is run as the unshared user and "
|
||||||
warning "maybe try running mmdebstrap with "
|
. "needs read access to packages outside the chroot given "
|
||||||
. "--hook-dir=/usr/share/mmdebstrap/hooks/file-mirror-automount";
|
. "via --include");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6450,8 +6477,9 @@ by this option will be the only ones that get either extracted or installed by
|
||||||
dpkg, respectively. For all other variants, apt is used to install the
|
dpkg, respectively. For all other variants, apt is used to install the
|
||||||
additional packages. Package names are directly passed to apt and thus, you
|
additional packages. Package names are directly passed to apt and thus, you
|
||||||
can use apt features like C<pkg/suite>, C<pkg=version>, C<pkg->, use a glob or
|
can use apt features like C<pkg/suite>, C<pkg=version>, C<pkg->, use a glob or
|
||||||
regex for C<pkg>, use apt patterns or pass a path to a .deb package file. See
|
regex for C<pkg>, use apt patterns or pass a path to a .deb package file (see
|
||||||
apt(8) for the supported syntax.
|
below for notes concerning passing the path to a .deb package file in
|
||||||
|
B<unshare> mode). See apt(8) for the supported syntax.
|
||||||
|
|
||||||
The option can be specified multiple times and the packages are concatenated in
|
The option can be specified multiple times and the packages are concatenated in
|
||||||
the order in which they are given on the command line. If later list items are
|
the order in which they are given on the command line. If later list items are
|
||||||
|
@ -6479,6 +6507,22 @@ apt. To add more packages, use multiple B<--include> options. To disable this
|
||||||
detection of patterns and paths, start the argument to B<--include> with a
|
detection of patterns and paths, start the argument to B<--include> with a
|
||||||
comma or whitespace.
|
comma or whitespace.
|
||||||
|
|
||||||
|
If you pass the path to a .deb package file using B<--include>, B<mmdebstrap>
|
||||||
|
will ensure that the path exists. If the path is a relative path, it will
|
||||||
|
internally by converted to an absolute path. Since apt (outside the chroot)
|
||||||
|
passes paths to dpkg (on the inside) verbatim, you have to make the .deb
|
||||||
|
package available under the same path inside the chroot as well or otherwise
|
||||||
|
dpkg inside the chroot will be unable to access it. This can be achieved using
|
||||||
|
a setup-hook. A hook that automatically makes the contents of C<file://>
|
||||||
|
mirrors as well as .deb packages given with B<--include> available inside the
|
||||||
|
chroot is provided by B<mmdebstrap> as
|
||||||
|
B<--hook-dir=/usr/share/mmdebstrap/hooks/file-mirror-automount>. This hook
|
||||||
|
takes care of copying all relevant file to their correct locations and cleans
|
||||||
|
up those files at the end. In B<unshare> mode, the .deb package paths have to
|
||||||
|
be accessible by the unshared user as well. This means that the package itself
|
||||||
|
likely must be made world-readable and all directory components on the path to
|
||||||
|
it world-executable.
|
||||||
|
|
||||||
=item B<--components>=I<comp1>[,I<comp2>,...]
|
=item B<--components>=I<comp1>[,I<comp2>,...]
|
||||||
|
|
||||||
Comma or whitespace separated list of components like main, contrib, non-free
|
Comma or whitespace separated list of components like main, contrib, non-free
|
||||||
|
@ -6668,9 +6712,9 @@ decides which way this is achieved.
|
||||||
|
|
||||||
This mode automatically selects a fitting mode. If the effective user id is the
|
This mode automatically selects a fitting mode. If the effective user id is the
|
||||||
one of the superuser, then the B<sudo> mode is chosen. Otherwise, the
|
one of the superuser, then the B<sudo> mode is chosen. Otherwise, the
|
||||||
B<unshare> mode is picked if the system has the sysctl
|
B<unshare> mode is picked if F</etc/subuid> and F</etc/subgid> are set up
|
||||||
C<kernel.unprivileged_userns_clone> set to C<1>. Should that not be the case
|
correctly. Should that not be the case and if the fakechroot binary exists, the
|
||||||
and if the fakechroot binary exists, the B<fakechroot> mode is chosen.
|
B<fakechroot> mode is chosen.
|
||||||
|
|
||||||
=item B<sudo>, B<root>
|
=item B<sudo>, B<root>
|
||||||
|
|
||||||
|
@ -6935,11 +6979,13 @@ C<MMDEBSTRAP_APT_CONFIG> environment variable. All environment variables set by
|
||||||
the user are preserved, except for C<TMPDIR> which is cleared. See section
|
the user are preserved, except for C<TMPDIR> which is cleared. See section
|
||||||
B<TMPDIR>. Furthermore, C<MMDEBSTRAP_MODE> will store the mode set by
|
B<TMPDIR>. Furthermore, C<MMDEBSTRAP_MODE> will store the mode set by
|
||||||
B<--mode>, C<MMDEBSTRAP_HOOK> stores which hook is currently run (setup,
|
B<--mode>, C<MMDEBSTRAP_HOOK> stores which hook is currently run (setup,
|
||||||
extract, essential, customize) and C<MMDEBSTRAP_VERBOSITY> stores the numerical
|
extract, essential, customize), C<MMDEBSTRAP_ARGV0> stores the name of the
|
||||||
verbosity level (0 for no output, 1 for normal, 2 for verbose and 3 for debug
|
binary with which B<mmdebstrap> was executed and C<MMDEBSTRAP_VERBOSITY> stores
|
||||||
output). The C<MMDEBSTRAP_INCLUDE> variable stores the list of packages, apt
|
the numerical verbosity level (0 for no output, 1 for normal, 2 for verbose and
|
||||||
patterns or file paths given by the B<--include> option, separated by a comma
|
3 for debug output). The C<MMDEBSTRAP_INCLUDE> variable stores the list of
|
||||||
and with commas and percent signs in the option values urlencoded.
|
packages, apt patterns or file paths given by the B<--include> option,
|
||||||
|
separated by a comma and with commas and percent signs in the option values
|
||||||
|
urlencoded.
|
||||||
|
|
||||||
In special hooks, the paths inside the chroot are relative to the root
|
In special hooks, the paths inside the chroot are relative to the root
|
||||||
directory of the chroot. The path on the outside is relative to current
|
directory of the chroot. The path on the outside is relative to current
|
||||||
|
|
|
@ -5,14 +5,19 @@ if [ ! -e /mmdebstrap-testenv ]; then
|
||||||
echo "this test modifies the system and should only be run inside a container" >&2
|
echo "this test modifies the system and should only be run inside a container" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
for f in /etc/apt/trusted.gpg.d/*.gpg /etc/apt/trusted.gpg.d/*.asc; do
|
||||||
|
[ -e "$f" ] || continue
|
||||||
|
rm "$f"
|
||||||
|
done
|
||||||
|
rmdir /etc/apt/trusted.gpg.d
|
||||||
|
mkdir /etc/apt/trusted.gpg.d
|
||||||
for f in /usr/share/keyrings/*.gpg; do
|
for f in /usr/share/keyrings/*.gpg; do
|
||||||
name=$(basename "$f" .gpg)
|
name=$(basename "$f" .gpg)
|
||||||
gpg --enarmor < "/usr/share/keyrings/$name.gpg" \
|
gpg --enarmor < "/usr/share/keyrings/$name.gpg" \
|
||||||
| sed 's/ PGP ARMORED FILE/ PGP PUBLIC KEY BLOCK/;/^Comment: /d' \
|
| sed 's/ PGP ARMORED FILE/ PGP PUBLIC KEY BLOCK/;/^Comment: /d' \
|
||||||
> "/etc/apt/trusted.gpg.d/$name.asc"
|
> "/etc/apt/trusted.gpg.d/$name.asc"
|
||||||
|
rm "/usr/share/keyrings/$name.gpg"
|
||||||
done
|
done
|
||||||
rm /etc/apt/trusted.gpg.d/*.gpg
|
|
||||||
rm /usr/share/keyrings/*.gpg
|
|
||||||
{{ CMD }} --mode=root --variant=apt {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
|
{{ CMD }} --mode=root --variant=apt {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
|
||||||
tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt -
|
tar -tf /tmp/debian-chroot.tar | sort | diff -u tar1.txt -
|
||||||
rm -r /tmp/debian-chroot.tar
|
rm -r /tmp/debian-chroot.tar
|
||||||
|
|
|
@ -5,14 +5,21 @@ export SOURCE_DATE_EPOCH={{ SOURCE_DATE_EPOCH }}
|
||||||
|
|
||||||
trap "rm -f /tmp/debian-chroot-{{ MODE }}.{{ FORMAT }}" EXIT INT TERM
|
trap "rm -f /tmp/debian-chroot-{{ MODE }}.{{ FORMAT }}" EXIT INT TERM
|
||||||
|
|
||||||
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
|
case {{ MODE }} in unshare|fakechroot) : ;; *) exit 1;; esac
|
||||||
if [ ! -e /mmdebstrap-testenv ]; then
|
|
||||||
echo "this test modifies the system and should only be run inside a container" >&2
|
prefix=
|
||||||
exit 1
|
if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then
|
||||||
|
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
|
||||||
|
if [ ! -e /mmdebstrap-testenv ]; then
|
||||||
|
echo "this test modifies the system and should only be run inside a container" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
|
||||||
fi
|
fi
|
||||||
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
|
prefix="runuser -u ${SUDO_USER:-user} --"
|
||||||
fi
|
fi
|
||||||
runuser -u "${SUDO_USER:-user}" -- {{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} {{ DIST }} /tmp/debian-chroot-{{ MODE }}.{{ FORMAT }} {{ MIRROR }}
|
|
||||||
|
$prefix {{ CMD }} --mode={{ MODE }} --variant={{ VARIANT }} {{ DIST }} /tmp/debian-chroot-{{ MODE }}.{{ FORMAT }} {{ MIRROR }}
|
||||||
cmp ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.{{ FORMAT }} /tmp/debian-chroot-{{ MODE }}.{{ FORMAT }} \
|
cmp ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.{{ FORMAT }} /tmp/debian-chroot-{{ MODE }}.{{ FORMAT }} \
|
||||||
|| diffoscope ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.{{ FORMAT }} /tmp/debian-chroot-{{ MODE }}.{{ FORMAT }}
|
|| diffoscope ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.{{ FORMAT }} /tmp/debian-chroot-{{ MODE }}.{{ FORMAT }}
|
||||||
|
|
||||||
|
|
17
tests/debug
17
tests/debug
|
@ -1,6 +1,17 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -eu
|
set -eu
|
||||||
export LC_ALL=C.UTF-8
|
export LC_ALL=C.UTF-8
|
||||||
{{ CMD }} --mode=root --variant=apt --debug {{ DIST }} /tmp/debian-chroot {{ MIRROR }}
|
export SOURCE_DATE_EPOCH={{ SOURCE_DATE_EPOCH }}
|
||||||
tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort | diff -u tar1.txt -
|
|
||||||
rm -r /tmp/debian-chroot
|
trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM
|
||||||
|
|
||||||
|
# we use variant standard in verbose mode to see the maximum number of packages
|
||||||
|
# that was chosen in case of USE_HOST_APT_CONFIG=yes
|
||||||
|
# we use variant important on arches where variant standard is not bit-by-bit
|
||||||
|
# reproducible due to #1031276
|
||||||
|
case {{ VARIANT }} in standard|-) : ;; *) exit 1;; esac
|
||||||
|
|
||||||
|
{{ CMD }} --variant={{ VARIANT }} --debug {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
|
||||||
|
|
||||||
|
cmp ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.tar /tmp/debian-chroot.tar \
|
||||||
|
|| diffoscope ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.tar /tmp/debian-chroot.tar
|
||||||
|
|
|
@ -13,4 +13,4 @@ if [ "$ret" = 0 ]; then
|
||||||
echo expected failure but got exit $ret >&2
|
echo expected failure but got exit $ret >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
rm -r /tmp/debian-chroot
|
[ ! -e /tmp/debian-chroot ]
|
||||||
|
|
|
@ -14,4 +14,4 @@ if [ "$ret" = 0 ]; then
|
||||||
echo expected failure but got exit $ret >&2
|
echo expected failure but got exit $ret >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
rm -r /tmp/debian-chroot
|
[ ! -e /tmp/debian-chroot ]
|
||||||
|
|
|
@ -5,6 +5,18 @@ export LC_ALL=C.UTF-8
|
||||||
|
|
||||||
trap "rm -rf /tmp/dummypkg.deb /tmp/dummypkg" EXIT INT TERM
|
trap "rm -rf /tmp/dummypkg.deb /tmp/dummypkg" EXIT INT TERM
|
||||||
|
|
||||||
|
prefix=
|
||||||
|
if [ "$(id -u)" -eq 0 ] && [ "{{ MODE }}" != "root" ] && [ "{{ MODE }}" != "auto" ]; then
|
||||||
|
if ! id "${SUDO_USER:-user}" >/dev/null 2>&1; then
|
||||||
|
if [ ! -e /mmdebstrap-testenv ]; then
|
||||||
|
echo "this test modifies the system and should only be run inside a container" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
useradd --home-dir "/home/${SUDO_USER:-user}" --create-home "${SUDO_USER:-user}"
|
||||||
|
fi
|
||||||
|
prefix="runuser -u ${SUDO_USER:-user} --"
|
||||||
|
fi
|
||||||
|
|
||||||
# instead of obtaining a .deb from our cache, we create a new package because
|
# instead of obtaining a .deb from our cache, we create a new package because
|
||||||
# otherwise apt might decide to download the package with the same name and
|
# otherwise apt might decide to download the package with the same name and
|
||||||
# version from the cache instead of using the local .deb
|
# version from the cache instead of using the local .deb
|
||||||
|
@ -22,7 +34,7 @@ Description: dummypkg
|
||||||
END
|
END
|
||||||
dpkg-deb --build "/tmp/dummypkg" "/tmp/dummypkg.deb"
|
dpkg-deb --build "/tmp/dummypkg" "/tmp/dummypkg.deb"
|
||||||
|
|
||||||
{{ CMD }} --variant=apt --include="/tmp/dummypkg.deb" \
|
$prefix {{ CMD }} --mode={{ MODE }} --variant=apt --include="/tmp/dummypkg.deb" \
|
||||||
--hook-dir=./hooks/file-mirror-automount \
|
--hook-dir=./hooks/file-mirror-automount \
|
||||||
--customize-hook='chroot "$1" dpkg-query -W -f="\${Status}\n" dummypkg | grep "^install ok installed$"' \
|
--customize-hook='chroot "$1" dpkg-query -W -f="\${Status}\n" dummypkg | grep "^install ok installed$"' \
|
||||||
{{ DIST }} /dev/null {{ MIRROR }}
|
{{ DIST }} /dev/null {{ MIRROR }}
|
||||||
|
|
|
@ -5,7 +5,12 @@ if [ ! -e /mmdebstrap-testenv ]; then
|
||||||
echo "this test modifies the system and should only be run inside a container" >&2
|
echo "this test modifies the system and should only be run inside a container" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
rm /etc/apt/trusted.gpg.d/*.gpg
|
for f in /etc/apt/trusted.gpg.d/*.gpg /etc/apt/trusted.gpg.d/*.asc; do
|
||||||
|
[ -e "$f" ] || continue
|
||||||
|
rm "$f"
|
||||||
|
done
|
||||||
|
rmdir /etc/apt/trusted.gpg.d
|
||||||
|
mkdir /etc/apt/trusted.gpg.d
|
||||||
{{ CMD }} --mode=root --variant=apt --keyring=/usr/share/keyrings/debian-archive-keyring.gpg --keyring=/usr/share/keyrings/ {{ DIST }} /tmp/debian-chroot "deb {{ MIRROR }} {{ DIST }} main"
|
{{ CMD }} --mode=root --variant=apt --keyring=/usr/share/keyrings/debian-archive-keyring.gpg --keyring=/usr/share/keyrings/ {{ DIST }} /tmp/debian-chroot "deb {{ MIRROR }} {{ DIST }} main"
|
||||||
# make sure that no [signedby=...] managed to make it into the sources.list
|
# make sure that no [signedby=...] managed to make it into the sources.list
|
||||||
echo "deb {{ MIRROR }} {{ DIST }} main" | cmp /tmp/debian-chroot/etc/apt/sources.list -
|
echo "deb {{ MIRROR }} {{ DIST }} main" | cmp /tmp/debian-chroot/etc/apt/sources.list -
|
||||||
|
|
|
@ -12,14 +12,10 @@ rm /tmp/debian-chroot/etc/timezone
|
||||||
rm -r /tmp/debian-chroot/usr/share/doc/tzdata
|
rm -r /tmp/debian-chroot/usr/share/doc/tzdata
|
||||||
rm -r /tmp/debian-chroot/usr/share/zoneinfo
|
rm -r /tmp/debian-chroot/usr/share/zoneinfo
|
||||||
rm /tmp/debian-chroot/var/lib/apt/extended_states
|
rm /tmp/debian-chroot/var/lib/apt/extended_states
|
||||||
rm /tmp/debian-chroot/var/lib/dpkg/info/doc-debian.list
|
for p in doc-debian tzdata; do
|
||||||
rm /tmp/debian-chroot/var/lib/dpkg/info/doc-debian.md5sums
|
for f in list md5sums config postinst postrm templates preinst prerm; do
|
||||||
rm /tmp/debian-chroot/var/lib/dpkg/info/tzdata.list
|
[ -e "/tmp/debian-chroot/var/lib/dpkg/info/$p.$f" ] || continue
|
||||||
rm /tmp/debian-chroot/var/lib/dpkg/info/tzdata.md5sums
|
rm "/tmp/debian-chroot/var/lib/dpkg/info/$p.$f"
|
||||||
rm /tmp/debian-chroot/var/lib/dpkg/info/tzdata.config
|
done
|
||||||
rm /tmp/debian-chroot/var/lib/dpkg/info/tzdata.postinst
|
done
|
||||||
rm /tmp/debian-chroot/var/lib/dpkg/info/tzdata.postrm
|
|
||||||
rm /tmp/debian-chroot/var/lib/dpkg/info/tzdata.templates
|
|
||||||
rm /tmp/debian-chroot/var/lib/dpkg/info/tzdata.preinst
|
|
||||||
rm /tmp/debian-chroot/var/lib/dpkg/info/tzdata.prerm
|
|
||||||
tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort | diff -u tar1.txt -
|
tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort | diff -u tar1.txt -
|
||||||
|
|
|
@ -5,7 +5,12 @@ if [ ! -e /mmdebstrap-testenv ]; then
|
||||||
echo "this test modifies the system and should only be run inside a container" >&2
|
echo "this test modifies the system and should only be run inside a container" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
rm /etc/apt/trusted.gpg.d/*.gpg
|
for f in /etc/apt/trusted.gpg.d/*.gpg /etc/apt/trusted.gpg.d/*.asc; do
|
||||||
|
[ -e "$f" ] || continue
|
||||||
|
rm "$f"
|
||||||
|
done
|
||||||
|
rmdir /etc/apt/trusted.gpg.d
|
||||||
|
mkdir /etc/apt/trusted.gpg.d
|
||||||
{{ CMD }} --mode=root --variant=apt {{ DIST }} /tmp/debian-chroot {{ MIRROR }}
|
{{ CMD }} --mode=root --variant=apt {{ DIST }} /tmp/debian-chroot {{ MIRROR }}
|
||||||
printf 'deb [signed-by="/usr/share/keyrings/debian-archive-keyring.gpg"] {{ MIRROR }} {{ DIST }} main\n' | cmp /tmp/debian-chroot/etc/apt/sources.list -
|
printf 'deb [signed-by="/usr/share/keyrings/debian-archive-keyring.gpg"] {{ MIRROR }} {{ DIST }} main\n' | cmp /tmp/debian-chroot/etc/apt/sources.list -
|
||||||
tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort | diff -u tar1.txt -
|
tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort | diff -u tar1.txt -
|
||||||
|
|
|
@ -1,6 +1,17 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
set -eu
|
set -eu
|
||||||
export LC_ALL=C.UTF-8
|
export LC_ALL=C.UTF-8
|
||||||
{{ CMD }} --mode=root --variant=apt --verbose {{ DIST }} /tmp/debian-chroot {{ MIRROR }}
|
export SOURCE_DATE_EPOCH={{ SOURCE_DATE_EPOCH }}
|
||||||
tar -C /tmp/debian-chroot --one-file-system -c . | tar -t | sort | diff -u tar1.txt -
|
|
||||||
rm -r /tmp/debian-chroot
|
trap "rm -f /tmp/debian-chroot.tar" EXIT INT TERM
|
||||||
|
|
||||||
|
# we use variant standard in verbose mode to see the maximum number of packages
|
||||||
|
# that was chosen in case of USE_HOST_APT_CONFIG=yes
|
||||||
|
# we use variant important on arches where variant standard is not bit-by-bit
|
||||||
|
# reproducible due to #1031276
|
||||||
|
case {{ VARIANT }} in standard|-) : ;; *) exit 1;; esac
|
||||||
|
|
||||||
|
{{ CMD }} --variant={{ VARIANT }} --verbose {{ DIST }} /tmp/debian-chroot.tar {{ MIRROR }}
|
||||||
|
|
||||||
|
cmp ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.tar /tmp/debian-chroot.tar \
|
||||||
|
|| diffoscope ./cache/mmdebstrap-{{ DIST }}-{{ VARIANT }}.tar /tmp/debian-chroot.tar
|
||||||
|
|
Loading…
Reference in a new issue