Adding debian version 1.0.141.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
This commit is contained in:
parent
04ec7bd664
commit
53607d61bf
21 changed files with 4622 additions and 0 deletions
3465
debian/changelog
vendored
Normal file
3465
debian/changelog
vendored
Normal file
File diff suppressed because it is too large
Load diff
30
debian/control
vendored
Normal file
30
debian/control
vendored
Normal file
|
@ -0,0 +1,30 @@
|
|||
Source: debootstrap
|
||||
Section: admin
|
||||
Priority: optional
|
||||
Maintainer: Debian Install System Team <debian-boot@lists.debian.org>
|
||||
Uploaders: Colin Watson <cjwatson@debian.org>, Steve McIntyre <93sam@debian.org>,
|
||||
Hideki Yamane <henrich@debian.org>, Luca Boccassi <bluca@debian.org>,
|
||||
Build-Depends: debhelper-compat (= 13)
|
||||
Standards-Version: 4.7.0
|
||||
Rules-Requires-Root: no
|
||||
Vcs-Browser: https://salsa.debian.org/installer-team/debootstrap
|
||||
Vcs-Git: https://salsa.debian.org/installer-team/debootstrap.git
|
||||
|
||||
Package: debootstrap
|
||||
Architecture: all
|
||||
Multi-Arch: foreign
|
||||
Depends: ${misc:Depends}, wget, distro-info
|
||||
Recommends: sopv | sqv | gpgv, mount, ${debootstrap:Recommends}
|
||||
Suggests: squid-deb-proxy-client, ${debootstrap:Suggests}
|
||||
Description: Bootstrap a basic Debian system
|
||||
debootstrap is used to create a Debian base system from scratch,
|
||||
without requiring the availability of dpkg or apt. It does this by
|
||||
downloading .deb files from a mirror site, and carefully unpacking them
|
||||
into a directory which can eventually be chrooted into.
|
||||
|
||||
Package: debootstrap-udeb
|
||||
Section: debian-installer
|
||||
Package-Type: udeb
|
||||
Architecture: all
|
||||
Depends: ${misc:Depends}, mounted-partitions
|
||||
Description: Bootstrap the Debian system
|
23
debian/copyright
vendored
Normal file
23
debian/copyright
vendored
Normal file
|
@ -0,0 +1,23 @@
|
|||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
|
||||
Files: *
|
||||
Copyright: 2001-2007 Anthony Towns <ajt@debian.org>
|
||||
2007-2024 Debian Install System Team <debian-boot@lists.debian.org>
|
||||
License: Expat
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
.
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE
|
1
debian/debootstrap.docs
vendored
Normal file
1
debian/debootstrap.docs
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
README
|
1
debian/debootstrap.manpages
vendored
Normal file
1
debian/debootstrap.manpages
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
debootstrap.8
|
2
debian/gbp.conf
vendored
Normal file
2
debian/gbp.conf
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
[DEFAULT]
|
||||
debian-tag = %(version)s
|
36
debian/rules
vendored
Executable file
36
debian/rules
vendored
Executable file
|
@ -0,0 +1,36 @@
|
|||
#! /usr/bin/make -f
|
||||
|
||||
ifeq (0,$(shell dpkg-vendor --derives-from Ubuntu; echo $$?))
|
||||
RECOMMENDS := ubuntu-keyring
|
||||
SUGGESTS := debian-archive-keyring, arch-test (>= 0.11~),
|
||||
else ifeq (0,$(shell dpkg-vendor --derives-from Tanglu; echo $$?))
|
||||
RECOMMENDS := tanglu-archive-keyring, arch-test (>= 0.11~),
|
||||
SUGGESTS := debian-archive-keyring, ubuntu-archive-keyring, binutils, xz-utils, zstd
|
||||
else ifeq (0,$(shell dpkg-vendor --derives-from Kali; echo $$?))
|
||||
RECOMMENDS := kali-archive-keyring, arch-test (>= 0.11~),
|
||||
SUGGESTS := debian-archive-keyring, ubuntu-archive-keyring, binutils, xz-utils, zstd
|
||||
else ifeq (0,$(shell dpkg-vendor --derives-from Pardus; echo $$?))
|
||||
RECOMMENDS := pardus-archive-keyring, arch-test (>= 0.11~),
|
||||
SUGGESTS := debian-archive-keyring, ubuntu-archive-keyring, binutils, xz-utils, zstd
|
||||
else ifeq (0,$(shell dpkg-vendor --derives-from eLxr; echo $$?))
|
||||
RECOMMENDS := elxr-archive-keyring, arch-test (>= 0.11~),
|
||||
SUGGESTS := debian-archive-keyring, ubuntu-archive-keyring, binutils, xz-utils, zstd
|
||||
else
|
||||
RECOMMENDS := debian-archive-keyring, arch-test (>= 0.11~),
|
||||
SUGGESTS := ubuntu-archive-keyring, binutils, xz-utils, zstd
|
||||
endif
|
||||
|
||||
%:
|
||||
dh $@
|
||||
|
||||
override_dh_auto_install:
|
||||
$(MAKE) install DESTDIR=$(CURDIR)/debian/debootstrap
|
||||
$(MAKE) install DESTDIR=$(CURDIR)/debian/debootstrap-udeb
|
||||
|
||||
override_dh_gencontrol:
|
||||
dh_gencontrol -- -Vdebootstrap:Recommends='$(RECOMMENDS)' -Vdebootstrap:Suggests='$(SUGGESTS)'
|
||||
|
||||
# Specify gzip to mitigate #770217:
|
||||
override_dh_builddeb:
|
||||
dh_builddeb -pdebootstrap -- -Zgzip
|
||||
dh_builddeb -pdebootstrap-udeb -- -Zxz
|
76
debian/salsa-ci.yml
vendored
Normal file
76
debian/salsa-ci.yml
vendored
Normal file
|
@ -0,0 +1,76 @@
|
|||
---
|
||||
include:
|
||||
- https://salsa.debian.org/installer-team/branch2repo/-/raw/main/trigger_b2r.yml
|
||||
|
||||
variables:
|
||||
SALSA_CI_DISABLE_BUILD_PACKAGE_ANY: 1
|
||||
# undo some of branch2repo's defaults, which are tuned for udebs
|
||||
SALSA_CI_DISABLE_LINTIAN: 0
|
||||
SALSA_CI_DISABLE_PIUPARTS: 0
|
||||
|
||||
# This tests running debootstrap inside an unshared user namespace.
|
||||
# Inside that namespace, mknod is not available.
|
||||
# In such an environment "mount -t proc proc /proc" will not work (see
|
||||
# #1031222) so this also tests whether the fallback to bind-mounting
|
||||
# proc works as systemd-tmpfiles will otherwise not create several files.
|
||||
test-unshare:
|
||||
stage: test
|
||||
image: $SALSA_CI_IMAGES_BASE
|
||||
needs:
|
||||
- job: build
|
||||
artifacts: true
|
||||
variables:
|
||||
DEBOOTSTRAP_SCRIPT: $CI_PROJECT_DIR/debootstrap
|
||||
DEBOOTSTRAP_DIR: $CI_PROJECT_DIR
|
||||
AUTOPKGTEST_TMP: /tmp
|
||||
script:
|
||||
- apt-get update
|
||||
- apt-get install --no-install-recommends -y libdistro-info-perl libdpkg-perl libipc-run-perl perl systemd systemd-container ca-certificates mmdebstrap uidmap wget distro-info
|
||||
- mmdebstrap --variant=custom --mode=unshare --setup-hook="./debian/tests/debian-testing minbase" --skip=update,setup,cleanup - "$AUTOPKGTEST_TMP/chroot.d"
|
||||
|
||||
test-buildd:
|
||||
stage: test
|
||||
image: $SALSA_CI_IMAGES_BASE
|
||||
needs:
|
||||
- job: build
|
||||
artifacts: true
|
||||
script:
|
||||
- |
|
||||
set -x
|
||||
apt-get update
|
||||
apt-get install --no-install-recommends -y wget distro-info
|
||||
for SUITE in bullseye bookworm trixie; do
|
||||
env DEBOOTSTRAP_DIR="$CI_PROJECT_DIR" ./debootstrap --variant=buildd "$SUITE" ./chroot
|
||||
# check if chroots before trixie are unmerged and chroots of trixie
|
||||
# or later are using merged-/usr
|
||||
case "$SUITE" in
|
||||
bullseye|bookworm)
|
||||
for f in bin sbin lib; do
|
||||
[ ! -d "./chroot/$f" ] && echo "E: /$f is not a directory" && exit 1
|
||||
[ -L "./chroot/$f" ] && echo "E: /$f is a symlink" && exit 1
|
||||
done
|
||||
;;
|
||||
trixie)
|
||||
for f in bin sbin lib; do
|
||||
[ ! -L "./chroot/$f" ] && echo "E: /$f is not a symlink" && exit 1
|
||||
done
|
||||
;;
|
||||
esac
|
||||
# check if trixie buildd chroots do not contain Priority:required
|
||||
# packages like tzdata
|
||||
case "$SUITE" in
|
||||
bullseye|bookworm)
|
||||
if [ "$(chroot ./chroot dpkg-query --no-pager --showformat '${db:Status-Status}' --show tzdata)" != "installed" ]; then
|
||||
echo "E: tzdata should be installed in the buildd variant for bullseye and bookworm"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
trixie)
|
||||
if [ "$(chroot ./chroot dpkg-query --no-pager --showformat '${db:Status-Status}' --show tzdata)" = "installed" ]; then
|
||||
echo "E: tzdata should not be installed in the buildd variant for trixie"
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
rm -rf ./chroot
|
||||
done
|
1
debian/source/format
vendored
Normal file
1
debian/source/format
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
3.0 (native)
|
3
debian/source/lintian-overrides
vendored
Normal file
3
debian/source/lintian-overrides
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
debootstrap source: custom-compression-in-debian-source-options compression = gzip [debian/source/options:*]
|
||||
debootstrap source: custom-compression-in-debian-rules dh_builddeb -pdebootstrap * -- -Zgzip [debian/rules:*]
|
||||
debootstrap source: custom-compression-in-debian-rules dh_builddeb -pdebootstrap-udeb -- -Zxz [debian/rules:*]
|
1
debian/source/options
vendored
Normal file
1
debian/source/options
vendored
Normal file
|
@ -0,0 +1 @@
|
|||
compression = gzip
|
120
debian/tests/arch-all-mitm.py
vendored
Normal file
120
debian/tests/arch-all-mitm.py
vendored
Normal file
|
@ -0,0 +1,120 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2023 Debian Install System Team <debian-boot@lists.debian.org>
|
||||
# Copyright (C) 2023 Matthias Klumpp <matthias@tenstral.net>
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
"""
|
||||
Flask app which MITM's a legacy-compatibility archive to make it arch:all-only.
|
||||
"""
|
||||
import functools
|
||||
import gzip
|
||||
import hashlib
|
||||
import os
|
||||
|
||||
import requests
|
||||
import tempfile
|
||||
from apt_pkg import TagFile, TagSection
|
||||
from flask import Flask, redirect
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
ARCH = os.environ.get("FLASK_ARCH", "amd64")
|
||||
DIST = os.environ.get("FLASK_DIST", "trixie")
|
||||
DISTRO = os.environ.get("FLASK_DISTRO", "debian")
|
||||
MIRROR = os.environ.get("FLASK_MIRROR", "http://deb.debian.org")
|
||||
|
||||
|
||||
if DISTRO in ("debian", "pureos"):
|
||||
hash_funcs = [hashlib.md5, hashlib.sha256]
|
||||
else:
|
||||
# Ubuntu includes SHA1 still
|
||||
hash_funcs = [hashlib.md5, hashlib.sha1, hashlib.sha256]
|
||||
|
||||
|
||||
def _munge_release_file(url: str) -> bytes:
|
||||
"""Given a Release file URL, rewrite it for our modified Packages content."""
|
||||
original = requests.get(MIRROR + "/" + url).content.decode('utf-8')
|
||||
packages_content = _packages_arch_content(
|
||||
f"{DISTRO}/dists/{DIST}/main/binary-{ARCH}/Packages"
|
||||
)
|
||||
size = str(len(packages_content))
|
||||
sums = [
|
||||
hash_func(packages_content).hexdigest()
|
||||
for hash_func in hash_funcs
|
||||
]
|
||||
new_lines = []
|
||||
filename = f"main/binary-{ARCH}/Packages"
|
||||
for line in original.splitlines():
|
||||
if line.startswith('No-Support-for-Architecture-all:'):
|
||||
continue
|
||||
if line.startswith('Architectures:'):
|
||||
if ' all' not in line:
|
||||
line += ' all'
|
||||
new_lines.append(line)
|
||||
continue
|
||||
if line.startswith('Acquire-By-Hash:'):
|
||||
new_lines.append('Acquire-By-Hash: no')
|
||||
continue
|
||||
if not line.endswith(filename):
|
||||
new_lines.append(line)
|
||||
continue
|
||||
new_lines.append(" ".join(["", sums.pop(0), size, filename]))
|
||||
|
||||
result = "\n".join(new_lines)
|
||||
return result.encode('utf-8')
|
||||
|
||||
|
||||
@functools.lru_cache
|
||||
def _packages_arch_content(url: str) -> bytes:
|
||||
"""Given an arch-specific Packages URL, fetch it and filter out arch:all."""
|
||||
resp = requests.get(MIRROR + "/" + url + ".gz")
|
||||
upstream_content = gzip.decompress(resp.content)
|
||||
|
||||
filtered_sections = []
|
||||
with tempfile.NamedTemporaryFile() as tmp_f:
|
||||
tmp_f.write(upstream_content)
|
||||
tmp_f.flush()
|
||||
|
||||
with TagFile(tmp_f.name) as tf:
|
||||
for section in tf:
|
||||
if section.get('Architecture') == 'all':
|
||||
continue
|
||||
filtered_sections.append(section)
|
||||
|
||||
result = '\n'.join([str(s) for s in filtered_sections])
|
||||
return result.encode('utf-8')
|
||||
|
||||
|
||||
@functools.lru_cache
|
||||
def _packages_indep_content(url: str) -> bytes:
|
||||
"""Given an arch:all Packages URL, just return its uncompressed contents."""
|
||||
resp = requests.get(MIRROR + "/" + url + ".gz")
|
||||
upstream_content = gzip.decompress(resp.content)
|
||||
|
||||
return upstream_content
|
||||
|
||||
|
||||
@app.route("/<path:url>", methods=["GET", "POST"])
|
||||
def root(url):
|
||||
"""Handler for all requests."""
|
||||
if (
|
||||
url == f"{DISTRO}/dists/{DIST}/InRelease"
|
||||
or "by-hash" in url
|
||||
or "Packages.xz" in url
|
||||
or "Packages.gz" in url
|
||||
):
|
||||
# 404 these URLs to force clients to fetch by path and without compression, to
|
||||
# make MITM easier
|
||||
return "", 404
|
||||
if url == f"{DISTRO}/dists/{DIST}/Release":
|
||||
# If Release is being fetched, return our modified version
|
||||
return _munge_release_file(url)
|
||||
if url == f"{DISTRO}/dists/{DIST}/main/binary-all/Packages":
|
||||
return _packages_indep_content(url)
|
||||
if url == f"{DISTRO}/dists/{DIST}/main/binary-{ARCH}/Packages":
|
||||
# If Packages is being fetched, return our modified version
|
||||
return _packages_arch_content(url)
|
||||
# For anything we don't need to modify, redirect clients to upstream mirror
|
||||
return redirect(f"{MIRROR}/{url}")
|
30
debian/tests/arch-all-support
vendored
Executable file
30
debian/tests/arch-all-support
vendored
Executable file
|
@ -0,0 +1,30 @@
|
|||
#!/bin/sh
|
||||
|
||||
# This test runs the arch-all-mitm.py Flask app which debootstrap is then
|
||||
# pointed at.
|
||||
# It is used to pretend an archive in legacy-compatibility mode is only
|
||||
# supporting the split-arch-all mode, to test if debootstrap will handle
|
||||
# that situation correctly.
|
||||
|
||||
export FLASK_ARCH="$(dpkg --print-architecture)"
|
||||
export FLASK_DIST=testing
|
||||
export FLASK_DISTRO=debian
|
||||
export FLASK_MIRROR=http://deb.debian.org
|
||||
export PATH=$PATH:/usr/sbin
|
||||
|
||||
# Launch our MitM "mirror" server, ensure that request logging is sent to stdout
|
||||
PYTHONDONTWRITEBYTECODE=true FLASK_APP=debian/tests/arch-all-mitm.py flask run 2>&1 &
|
||||
flask_pid=$!
|
||||
|
||||
# Give Flask time to come up
|
||||
sleep 2
|
||||
|
||||
tempdir=$(mktemp -d)
|
||||
# Run debootstrap against our MitM "mirror", ignoring the inevitable GPG errors
|
||||
./debootstrap --download-only --variant minbase --no-check-sig ${FLASK_DIST} $tempdir http://127.0.0.1:5000/${FLASK_DISTRO}/
|
||||
rc=$?
|
||||
|
||||
rm -rf $tempdir
|
||||
kill $flask_pid
|
||||
|
||||
exit $rc
|
57
debian/tests/control
vendored
Normal file
57
debian/tests/control
vendored
Normal file
|
@ -0,0 +1,57 @@
|
|||
Features: test-name=debian-testing-minbase
|
||||
Test-Command: ./debian/tests/debian-testing minbase
|
||||
Depends:
|
||||
debootstrap,
|
||||
libdistro-info-perl,
|
||||
libdpkg-perl,
|
||||
libipc-run-perl,
|
||||
perl,
|
||||
systemd [linux-any],
|
||||
systemd-container [linux-any],
|
||||
ca-certificates,
|
||||
distro-info,
|
||||
Restrictions: allow-stderr, needs-root
|
||||
|
||||
Features: test-name=debian-testing-buildd
|
||||
Test-Command: ./debian/tests/debian-testing buildd
|
||||
Depends:
|
||||
debootstrap,
|
||||
libdistro-info-perl,
|
||||
libdpkg-perl,
|
||||
libipc-run-perl,
|
||||
perl,
|
||||
systemd [linux-any],
|
||||
systemd-container [linux-any],
|
||||
ca-certificates,
|
||||
distro-info,
|
||||
Restrictions: allow-stderr, needs-root
|
||||
|
||||
Features: test-name=debian-testing-default
|
||||
Test-Command: ./debian/tests/debian-testing -
|
||||
Depends:
|
||||
debootstrap,
|
||||
libdistro-info-perl,
|
||||
libdpkg-perl,
|
||||
libipc-run-perl,
|
||||
perl,
|
||||
systemd [linux-any],
|
||||
systemd-container [linux-any],
|
||||
ca-certificates,
|
||||
distro-info,
|
||||
Restrictions: allow-stderr, needs-root
|
||||
|
||||
Tests: unsorted-packages-files
|
||||
Depends:
|
||||
debootstrap,
|
||||
python3-debian,
|
||||
python3-flask,
|
||||
python3-requests,
|
||||
Restrictions: allow-stderr
|
||||
|
||||
Tests: arch-all-support
|
||||
Depends:
|
||||
debootstrap,
|
||||
python3-apt,
|
||||
python3-flask,
|
||||
python3-requests,
|
||||
Restrictions: allow-stderr
|
398
debian/tests/debian-testing
vendored
Executable file
398
debian/tests/debian-testing
vendored
Executable file
|
@ -0,0 +1,398 @@
|
|||
#!/usr/bin/perl
|
||||
# Verify that debootstrap'ing Debian testing produces a usable chroot,
|
||||
# and in particular that using it with early 2017 versions of schroot and
|
||||
# pbuilder results in working pseudo-terminals (#817236)
|
||||
#
|
||||
# Copyright © 2017 Simon McVittie
|
||||
# SPDX-License-Identifier: MIT
|
||||
# (see debian/copyright)
|
||||
|
||||
use strict;
|
||||
use warnings;
|
||||
|
||||
use Cwd qw(getcwd);
|
||||
use Debian::DistroInfo;
|
||||
use Dpkg::Version;
|
||||
use IPC::Run qw(run);
|
||||
use Test::More;
|
||||
|
||||
if (scalar @ARGV != 1) {
|
||||
die "usage: $0 [minbase|-|buildd]"
|
||||
}
|
||||
my $variant = $ARGV[0];
|
||||
my $srcdir = getcwd;
|
||||
|
||||
sub verbose_run {
|
||||
my $argv = shift;
|
||||
diag("Running: @{$argv}");
|
||||
return run($argv, @_);
|
||||
}
|
||||
|
||||
sub capture {
|
||||
my $output;
|
||||
my $argv = shift;
|
||||
ok(verbose_run($argv, '>', \$output), "@{$argv}");
|
||||
chomp $output;
|
||||
return $output;
|
||||
}
|
||||
|
||||
my $check_non_docker_env;
|
||||
if (run([qw(grep docker.*cgroup /proc/1/mountinfo)], '&>', '/dev/null')) {
|
||||
diag("it seems docker environment");
|
||||
$check_non_docker_env = 0;
|
||||
}
|
||||
else {
|
||||
diag("okay, it's not docker environment");
|
||||
$check_non_docker_env = 1;
|
||||
}
|
||||
|
||||
my @maybe_unshare_mount_ns;
|
||||
|
||||
if (verbose_run(['unshare', '-m', 'true'])) {
|
||||
diag('can unshare mount namespace');
|
||||
@maybe_unshare_mount_ns = ('unshare', '-m');
|
||||
}
|
||||
else {
|
||||
diag('cannot unshare mount namespace, are we in a container?');
|
||||
}
|
||||
|
||||
sub check_fake_schroot {
|
||||
my %params = @_;
|
||||
my $reference = $params{reference};
|
||||
my $version = $params{version} || '1.6.10-3';
|
||||
my $extra_argv = $params{extra_argv} || [];
|
||||
|
||||
# Use unshare -m to make sure the /dev mount gets cleaned up on exit, even
|
||||
# on failures
|
||||
my $response = capture([@maybe_unshare_mount_ns,
|
||||
"$srcdir/debian/tests/fake/schroot-$version", @{$extra_argv},
|
||||
$params{chroot},
|
||||
qw(runuser -u nobody --),
|
||||
qw(script -q -c), 'cat /etc/debian_version', '/dev/null']);
|
||||
$response =~ s/\r//g;
|
||||
is($response, $reference, 'script(1) should work under (fake) schroot');
|
||||
}
|
||||
|
||||
sub check_fake_pbuilder {
|
||||
my %params = @_;
|
||||
my $reference = $params{reference};
|
||||
my $version = $params{version} || '0.228.4-1';
|
||||
|
||||
my $response = capture([@maybe_unshare_mount_ns,
|
||||
"$srcdir/debian/tests/fake/pbuilder-$version", $params{chroot},
|
||||
qw(runuser -u nobody --),
|
||||
qw(script -q -c), 'cat /etc/debian_version', '/dev/null']);
|
||||
$response =~ s/\r//g;
|
||||
is($response, $reference,
|
||||
'script(1) should work under (fake) pbuilder');
|
||||
}
|
||||
|
||||
sub check_chroot {
|
||||
my %params = @_;
|
||||
my $chroot = $params{chroot};
|
||||
my $response;
|
||||
|
||||
ok(-f "$chroot/etc/debian_version",
|
||||
'chroot should have /etc/debian_version');
|
||||
ok(-x "$chroot/usr/bin/env",
|
||||
'chroot should have /usr/bin/env which is Essential');
|
||||
|
||||
if ($params{has_systemd}) {
|
||||
for my $p (
|
||||
"root/.ssh", "run/lock/subsys",
|
||||
"var/cache/private", "var/lib/private",
|
||||
"var/lib/systemd/coredump", "var/lib/systemd/pstore",
|
||||
"var/log/README", "var/log/private"
|
||||
)
|
||||
{
|
||||
ok( -e "$chroot/$p",
|
||||
"chroot should have /$p created by systemd-tmpfiles" );
|
||||
}
|
||||
}
|
||||
|
||||
ok(-x "$chroot/usr/bin/hello", 'chroot should have /usr/bin/hello due to --include');
|
||||
ok(-d "$chroot/usr/share/doc", 'chroot should have /usr/share/doc');
|
||||
|
||||
if (!defined $ENV{container} || $ENV{container} ne "mmdebstrap-unshare") {
|
||||
diag("not running with container=mmdebstrap-unshare");
|
||||
ok(-c "$chroot/dev/full", '/dev/full should be a character device');
|
||||
is(capture(['/usr/bin/stat', '--printf=%t %T %a', "$chroot/dev/full"]),
|
||||
'1 7 666', '/dev/full should be device 1,7 with 0666 permissions');
|
||||
ok(-c "$chroot/dev/null");
|
||||
is(capture(['/usr/bin/stat', '--printf=%t %T %a', "$chroot/dev/null"]),
|
||||
'1 3 666', '/dev/null should be device 1,3 with 0666 permissions');
|
||||
}
|
||||
|
||||
my $did_mknod_ptmx;
|
||||
my $output;
|
||||
|
||||
if (verbose_run([qw(ls -l), "$chroot/dev/ptmx"], '>', \$output)) {
|
||||
diag("$chroot/dev/ptmx: $output");
|
||||
}
|
||||
else {
|
||||
diag("Unable to list $chroot/dev/ptmx");
|
||||
}
|
||||
if (verbose_run([qw(ls -l), "$chroot/dev/pts/ptmx"], '>', \$output)) {
|
||||
diag("$chroot/dev/pts/ptmx: $output");
|
||||
}
|
||||
else {
|
||||
diag("Unable to list $chroot/dev/pts/ptmx");
|
||||
}
|
||||
|
||||
if (-l "$chroot/dev/ptmx") {
|
||||
# Necessary if debootstrap is run inside some containers, see
|
||||
# https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=817236#77
|
||||
diag("/dev/ptmx is a symbolic link");
|
||||
like(readlink("$chroot/dev/ptmx"), qr{(?:/dev/)?pts/ptmx},
|
||||
'if /dev/ptmx is a symlink it should be to /dev/pts/ptmx');
|
||||
$did_mknod_ptmx = 0;
|
||||
}
|
||||
else {
|
||||
diag("/dev/ptmx is not a symbolic link");
|
||||
ok(-c "$chroot/dev/ptmx",
|
||||
'if /dev/ptmx is not a symlink it should be a character device');
|
||||
is(capture(['/usr/bin/stat', '--printf=%t %T %a',
|
||||
"$chroot/dev/ptmx"]), '5 2 666',
|
||||
'if /dev/ptmx is a device node it should be 5,2 with 0666 permissions');
|
||||
$did_mknod_ptmx = 1;
|
||||
}
|
||||
|
||||
if ($params{can_mknod_ptmx}) {
|
||||
ok($did_mknod_ptmx, 'able to mknod ptmx so should have done so');
|
||||
}
|
||||
|
||||
my $reference = capture(['cat', "$chroot/etc/debian_version"]);
|
||||
|
||||
is(capture([qw(chroot chroot.d runuser -u nobody --
|
||||
cat /etc/debian_version)]),
|
||||
$reference);
|
||||
|
||||
# The remaining tests rely on device nodes to either exist or already
|
||||
# being bind-mounted. Their setups are not prepared to deal with the
|
||||
# conditions in an environment with an unshared user namespace as
|
||||
# used in mmdebstrap.
|
||||
if (defined $ENV{container} && $ENV{container} eq "mmdebstrap-unshare") {
|
||||
return;
|
||||
}
|
||||
|
||||
# The schroot behaviour proposed to fix #856877 and #983423 works,
|
||||
# even inside (privileged) lxc.
|
||||
check_fake_schroot(%params, reference => $reference, version => 'proposed');
|
||||
check_fake_schroot(%params, reference => $reference, version => 'proposed',
|
||||
extra_argv => ['--sbuild']);
|
||||
|
||||
# As of 1.6.10-3, or equivalently 1.6.10-11, the default profile
|
||||
# certainly doesn't work in lxc >= 3 or in Docker:
|
||||
# https://bugs.debian.org/983423
|
||||
# It probably won't work in other container managers either, for
|
||||
# similar reasons.
|
||||
if (defined $params{container}) {
|
||||
TODO: {
|
||||
local $TODO = "schroot default profile doesn't work in lxc >= 3 or Docker";
|
||||
check_fake_schroot(%params, reference => $reference,
|
||||
version => '1.6.10-3');
|
||||
}
|
||||
}
|
||||
else {
|
||||
check_fake_schroot(%params, reference => $reference,
|
||||
version => '1.6.10-3');
|
||||
}
|
||||
|
||||
# schroot 1.6.10-3's sbuild profile does work in lxc, but only on newer
|
||||
# kernels: https://bugs.debian.org/856877
|
||||
if (Dpkg::Version->new($params{kernel}) < Dpkg::Version->new('4.7') &&
|
||||
defined $params{container} && $params{container} eq 'lxc') {
|
||||
TODO: {
|
||||
local $TODO = "schroot --sbuild doesn't work in lxc on older ".
|
||||
"kernels";
|
||||
check_fake_schroot(%params, reference => $reference,
|
||||
extra_argv => ['--sbuild']);
|
||||
}
|
||||
}
|
||||
elsif (! $params{can_mknod_ptmx}) {
|
||||
TODO: {
|
||||
local $TODO = "schroot --sbuild doesn't work when /dev/ptmx is ".
|
||||
"a symlink to /dev/pts/ptmx";
|
||||
check_fake_schroot(%params, reference => $reference,
|
||||
extra_argv => ['--sbuild']);
|
||||
}
|
||||
}
|
||||
else {
|
||||
check_fake_schroot(%params, reference => $reference,
|
||||
extra_argv => ['--sbuild']);
|
||||
}
|
||||
|
||||
# pbuilder >= 0.228.6 works fine
|
||||
check_fake_pbuilder(%params, reference => $reference,
|
||||
version => '0.231');
|
||||
|
||||
# Older pbuilder doesn't work if we are in a container where we can't
|
||||
# create the /dev/ptmx device node: https://bugs.debian.org/841935
|
||||
if (! $params{can_mknod_ptmx}) {
|
||||
TODO: {
|
||||
local $TODO = "pbuilder 0.228.4-1 doesn't work when /dev/ptmx is ".
|
||||
"a symlink to /dev/pts/ptmx";
|
||||
check_fake_pbuilder(%params, reference => $reference,
|
||||
version => '0.228.4-1');
|
||||
}
|
||||
}
|
||||
else {
|
||||
check_fake_pbuilder(%params, reference => $reference,
|
||||
version => '0.228.4-1');
|
||||
}
|
||||
}
|
||||
|
||||
# Specify https mirror to check https mirror specific problem
|
||||
# https://bugs.debian.org/896071
|
||||
my $mirror = 'https://deb.debian.org/debian';
|
||||
my $tmp = $ENV{AUTOPKGTEST_TMP};
|
||||
die "no autopkgtest temporary directory specified" unless $tmp;
|
||||
chdir $tmp or die "chdir $tmp: $!";
|
||||
|
||||
$ENV{LC_ALL} = 'C.UTF-8';
|
||||
|
||||
# Try to inherit a Debian mirror from the host
|
||||
foreach my $file ('/etc/apt/sources.list',
|
||||
glob('/etc/apt/sources.list.d/*.list')) {
|
||||
open(my $fh, '<', $file);
|
||||
while (<$fh>) {
|
||||
if (m{^deb\s+(http://[-a-zA-Z0-9.:]+/debian)\s}) {
|
||||
$mirror = $1;
|
||||
last;
|
||||
}
|
||||
}
|
||||
close $fh;
|
||||
}
|
||||
|
||||
if (run(['ischroot'], '>&2')) {
|
||||
diag("In a chroot according to ischroot(1)");
|
||||
}
|
||||
else {
|
||||
diag("Not in a chroot according to ischroot(1)");
|
||||
}
|
||||
|
||||
my $virtualization;
|
||||
if ($^O ne 'linux') {
|
||||
diag("Cannot use systemd-detect-virt on non-Linux");
|
||||
}
|
||||
elsif (run(['systemd-detect-virt', '--vm'], '>', \$virtualization)) {
|
||||
chomp $virtualization;
|
||||
diag("Virtualization: $virtualization");
|
||||
}
|
||||
else {
|
||||
$virtualization = undef;
|
||||
diag("Virtualization: (not in a virtual machine)");
|
||||
}
|
||||
|
||||
my $in_container = 0;
|
||||
my $container;
|
||||
if ($^O ne 'linux') {
|
||||
diag("Cannot use systemd-detect-virt on non-Linux");
|
||||
}
|
||||
elsif (run(['systemd-detect-virt', '--container'], '>', \$container)) {
|
||||
$in_container = 1;
|
||||
chomp $container;
|
||||
diag("Container: $container");
|
||||
}
|
||||
else {
|
||||
$container = undef;
|
||||
diag("Container: (not in a container)");
|
||||
}
|
||||
|
||||
my $kernel = capture([qw(uname -r)]);
|
||||
chomp $kernel;
|
||||
|
||||
open(my $fh, '<', '/proc/self/mountinfo');
|
||||
while (<$fh>) {
|
||||
chomp;
|
||||
diag("mountinfo: $_");
|
||||
}
|
||||
close $fh;
|
||||
|
||||
my $output;
|
||||
if (verbose_run([qw(ls -l /dev/ptmx)], '>', \$output)) {
|
||||
diag("/dev/ptmx: $output");
|
||||
}
|
||||
else {
|
||||
diag("Unable to list /dev/ptmx");
|
||||
}
|
||||
if (verbose_run([qw(ls -l /dev/pts/ptmx)], '>', \$output)) {
|
||||
diag("/dev/pts/ptmx: $output");
|
||||
}
|
||||
else {
|
||||
diag("Unable to list /dev/pts/ptmx");
|
||||
}
|
||||
|
||||
my $can_mknod_ptmx;
|
||||
if (run([qw(mknod -m000 ptmx c 5 2)], '&>', '/dev/null')) {
|
||||
diag("mknod ptmx succeeded");
|
||||
$can_mknod_ptmx = 1;
|
||||
}
|
||||
else {
|
||||
diag("mknod ptmx failed, are we in a container?");
|
||||
$can_mknod_ptmx = 0;
|
||||
}
|
||||
|
||||
my $distro_info = DebianDistroInfo->new;
|
||||
my $testing = $distro_info->testing;
|
||||
|
||||
# Should specify multiple components for checking (see Bug#898738)
|
||||
if (!verbose_run([length($ENV{DEBOOTSTRAP_SCRIPT}) ? $ENV{DEBOOTSTRAP_SCRIPT} : 'debootstrap',
|
||||
'--include=debootstrap,debian-archive-keyring,gnupg,hello,systemd',
|
||||
"--variant=$variant",
|
||||
'--components=main,contrib,non-free',
|
||||
$testing, 'chroot.d', $mirror], '>&2')) {
|
||||
BAIL_OUT("debootstrap failed: $?");
|
||||
}
|
||||
|
||||
if (!verbose_run([qw(find chroot.d/dev -ls)], '>&2')) {
|
||||
BAIL_OUT("Unable to list contents of chroot's /dev: $?");
|
||||
}
|
||||
|
||||
if ($check_non_docker_env) {
|
||||
check_chroot(chroot => 'chroot.d', can_mknod_ptmx => $can_mknod_ptmx,
|
||||
kernel => $kernel, container => $container, has_systemd => 1);
|
||||
}
|
||||
|
||||
if ($^O ne 'linux') {
|
||||
diag("Cannot use systemd-nspawn on non-Linux");
|
||||
}
|
||||
elsif ($in_container) {
|
||||
diag('in a container according to systemd-detect-virt, not trying to '.
|
||||
'use systemd-nspawn');
|
||||
}
|
||||
elsif (defined $ENV{container} && length $ENV{container}) {
|
||||
diag('in a container according to $container, not trying to '.
|
||||
'use systemd-nspawn');
|
||||
}
|
||||
elsif (! -d '/run/systemd/system') {
|
||||
diag('systemd not booted, not trying to use systemd-nspawn');
|
||||
}
|
||||
else {
|
||||
if (!verbose_run(['systemd-nspawn', '-D', 'chroot.d',
|
||||
"--bind=$ENV{AUTOPKGTEST_TMP}:/mnt",
|
||||
'--bind-ro=/usr/sbin/debootstrap',
|
||||
'--bind-ro=/usr/share/debootstrap',
|
||||
'--',
|
||||
'debootstrap', '--include=hello', "--variant=$variant",
|
||||
$testing, '/mnt/from-nspawn.d', $mirror], '>&2')) {
|
||||
BAIL_OUT("debootstrap wrapped in systemd-nspawn failed: $?");
|
||||
}
|
||||
|
||||
check_chroot(chroot => "$ENV{AUTOPKGTEST_TMP}/from-nspawn.d", can_mknod_ptmx => 0,
|
||||
kernel => $kernel, container => "nspawn");
|
||||
}
|
||||
|
||||
if (!defined $ENV{container} || $ENV{container} ne "mmdebstrap-unshare") {
|
||||
if (!run([qw(rm -fr --one-file-system chroot.d)], '>&2')) {
|
||||
BAIL_OUT('Unable to remove chroot.d');
|
||||
}
|
||||
} else {
|
||||
if (!run([qw(env --chdir=chroot.d find . -mount -mindepth 1 -delete)], '>&2')) {
|
||||
BAIL_OUT('Unable to remove contents of chroot.d');
|
||||
}
|
||||
}
|
||||
|
||||
done_testing;
|
||||
|
||||
# vim:set sw=4 sts=4 et:
|
37
debian/tests/fake/pbuilder-0.228.4-1
vendored
Executable file
37
debian/tests/fake/pbuilder-0.228.4-1
vendored
Executable file
|
@ -0,0 +1,37 @@
|
|||
#!/bin/sh
|
||||
# fake/pbuilder-0.228.4-1 -- emulate how pbuilder/0.228.4-1 would chroot.
|
||||
#
|
||||
# Please do not modify this script without verifying that its behaviour
|
||||
# is still equivalent to the stated versions of pbuilder.
|
||||
#
|
||||
# This version has #841935 unfixed. It mounts /dev/pts, without explicitly
|
||||
# requesting a new instance or a usable /dev/pts/ptmx.
|
||||
# (There is of course a lot more that it does, but these are the parts that
|
||||
# affect pty users like script(1).)
|
||||
#
|
||||
# Reference: pbuilder/pbuilder-modules, search for dev/pts.
|
||||
#
|
||||
# Copyright © 2017 Simon McVittie
|
||||
# SPDX-License-Identifier: MIT
|
||||
# (see debian/copyright)
|
||||
|
||||
set -e
|
||||
|
||||
chroot="$1"
|
||||
shift
|
||||
if test -z "$chroot" || test -z "$1"; then
|
||||
echo "Usage: $0 CHROOT COMMAND...">&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
mkdir -p "$chroot/dev/pts"
|
||||
mount -t devpts none "$chroot/dev/pts" -onoexec,nosuid,gid=5,mode=620
|
||||
|
||||
ls -l "$chroot/dev/ptmx" | sed -e 's/^/# fake-pbuilder: /' >&2
|
||||
ls -l "$chroot/dev/pts/ptmx" | sed -e 's/^/# fake-pbuilder: /' >&2
|
||||
|
||||
e=0
|
||||
chroot "$chroot" "$@" || e=$?
|
||||
|
||||
umount "$chroot/dev/pts"
|
||||
exit "$e"
|
64
debian/tests/fake/pbuilder-0.231
vendored
Executable file
64
debian/tests/fake/pbuilder-0.231
vendored
Executable file
|
@ -0,0 +1,64 @@
|
|||
#!/bin/sh
|
||||
# fake/pbuilder-0.231 -- emulate how pbuilder >= 0.228.6 sets up its chroot
|
||||
#
|
||||
# Please do not modify this script without verifying that its behaviour
|
||||
# is still equivalent to the stated versions of pbuilder. If a future
|
||||
# version of pbuilder changes its behaviour, please copy this script and
|
||||
# modify the copy instead.
|
||||
#
|
||||
# This has #841935 fixed (commit 4a4134dd). It was checked for equivalence
|
||||
# to pbuilder 0.231, which is the version included in Debian 11 and 12,
|
||||
# but the versions in Debian 10 and 9 have equivalent code here.
|
||||
#
|
||||
# Reference: pbuilder/pbuilder-modules, search for dev/pts.
|
||||
#
|
||||
# Copyright © 2017-2021 Simon McVittie
|
||||
# SPDX-License-Identifier: MIT
|
||||
# (see debian/copyright)
|
||||
|
||||
set -e
|
||||
|
||||
BUILDPLACE="$1"
|
||||
shift
|
||||
if test -z "$BUILDPLACE" || test -z "$1"; then
|
||||
echo "Usage: $0 CHROOT COMMAND...">&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
mkdir -p "$BUILDPLACE/dev/pts"
|
||||
TTYGRP=5
|
||||
TTYMODE=620
|
||||
mount -t devpts devpts "$BUILDPLACE/dev/pts" -o "newinstance,noexec,nosuid,gid=$TTYGRP,mode=$TTYMODE,ptmxmode=0666"
|
||||
|
||||
mounted_ptmx=no
|
||||
|
||||
if ! [ -L "$BUILDPLACE/dev/ptmx" ]; then
|
||||
echo "# fake-pbuilder: redirecting /dev/ptmx to /dev/pts/ptmx" >&2
|
||||
mount --bind "$BUILDPLACE/dev/pts/ptmx" "$BUILDPLACE/dev/ptmx"
|
||||
mounted_ptmx=yes
|
||||
fi
|
||||
|
||||
mounted_console=no
|
||||
|
||||
if stdin_tty="$(tty)"; then
|
||||
if [ ! -e "$BUILDPLACE/dev/console" ]; then
|
||||
echo "# fake-pbuilder: creating /dev/console" >&2
|
||||
mknod -m600 "$BUILDPLACE/dev/console" c 5 1
|
||||
fi
|
||||
|
||||
echo "# fake-pbuilder: mounting $stdin_tty over /dev/console" >&2
|
||||
mount --bind "$stdin_tty" "$BUILDPLACE/dev/console"
|
||||
mounted_console=yes
|
||||
fi
|
||||
|
||||
ls -l "$BUILDPLACE/dev/console" | sed -e 's/^/# fake-pbuilder: /' >&2
|
||||
ls -l "$BUILDPLACE/dev/ptmx" | sed -e 's/^/# fake-pbuilder: /' >&2
|
||||
ls -l "$BUILDPLACE/dev/pts/ptmx" | sed -e 's/^/# fake-pbuilder: /' >&2
|
||||
|
||||
e=0
|
||||
chroot "$BUILDPLACE" "$@" || e=$?
|
||||
|
||||
[ "$mounted_console" = no ] || umount "$BUILDPLACE/dev/console"
|
||||
[ "$mounted_ptmx" = no ] || umount "$BUILDPLACE/dev/ptmx"
|
||||
umount "$BUILDPLACE/dev/pts"
|
||||
exit "$e"
|
58
debian/tests/fake/schroot-1.6.10-3
vendored
Executable file
58
debian/tests/fake/schroot-1.6.10-3
vendored
Executable file
|
@ -0,0 +1,58 @@
|
|||
#!/bin/sh
|
||||
# fake/schroot-1.6.10-3 -- emulate how schroot/1.6.10-3 would chroot.
|
||||
#
|
||||
# Please do not modify this script without verifying that its behaviour
|
||||
# is still equivalent to the stated versions of schroot. If a future
|
||||
# version of schroot changes its behaviour, please copy this script and
|
||||
# modify the copy instead.
|
||||
#
|
||||
# This version has #856877 unfixed. It bind-mounts /dev/pts and maybe
|
||||
# /dev from the host system, rather than creating a new instance of /dev/pts.
|
||||
# (There is of course a lot more that it does, but these are the parts that
|
||||
# affect pty users like script(1).)
|
||||
#
|
||||
# Copyright © 2017-2023 Simon McVittie
|
||||
# SPDX-License-Identifier: MIT
|
||||
# (see debian/copyright)
|
||||
|
||||
set -e
|
||||
|
||||
# Reference: /etc/schroot/default/fstab
|
||||
# (in schroot source tree: etc/profile-templates/default/linux/fstab)
|
||||
bind_dev=yes
|
||||
|
||||
while true; do
|
||||
case "$1" in
|
||||
(--sbuild)
|
||||
shift
|
||||
# Reference: /etc/schroot/sbuild/fstab
|
||||
# (source: etc/profile-templates/sbuild/linux/fstab)
|
||||
bind_dev=no
|
||||
;;
|
||||
(*)
|
||||
break
|
||||
esac
|
||||
done
|
||||
|
||||
chroot="$1"
|
||||
shift
|
||||
if test -z "$chroot" || test -z "$1"; then
|
||||
echo "Usage: $0 CHROOT COMMAND...">&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
[ "$bind_dev" = no ] || mount --bind /dev "$chroot/dev"
|
||||
mount --bind /dev/pts "$chroot/dev/pts"
|
||||
|
||||
ls -l "/dev/ptmx" | sed -e 's/^/# fake-schroot: outside chroot: /' >&2
|
||||
ls -l "/dev/pts/ptmx" | sed -e 's/^/# fake-schroot: outside chroot: /' >&2
|
||||
ls -l "$chroot/dev/ptmx" | sed -e 's/^/# fake-schroot: /' >&2
|
||||
ls -l "$chroot/dev/pts/ptmx" | sed -e 's/^/# fake-schroot: /' >&2
|
||||
|
||||
e=0
|
||||
chroot "$chroot" "$@" || e=$?
|
||||
|
||||
umount "$chroot/dev/pts"
|
||||
[ "$bind_dev" = no ] || umount "$chroot/dev"
|
||||
|
||||
exit "$e"
|
87
debian/tests/fake/schroot-proposed
vendored
Executable file
87
debian/tests/fake/schroot-proposed
vendored
Executable file
|
@ -0,0 +1,87 @@
|
|||
#!/bin/sh
|
||||
# fake/schroot-proposed -- emulate proposed mount behaviour for schroot
|
||||
#
|
||||
# This version emulates the behaviour proposed on #856877. If it needs
|
||||
# changing, please update the proposed patch on #856877 too.
|
||||
#
|
||||
# Copyright © 2017-2023 Simon McVittie
|
||||
# SPDX-License-Identifier: MIT
|
||||
# (see debian/copyright)
|
||||
|
||||
set -e
|
||||
|
||||
# Reference: /etc/schroot/default/fstab
|
||||
# (in schroot source tree: etc/profile-templates/default/linux/fstab)
|
||||
bind_dev=yes
|
||||
|
||||
while true; do
|
||||
case "$1" in
|
||||
(--sbuild)
|
||||
shift
|
||||
# Reference: /etc/schroot/sbuild/fstab
|
||||
# (source: etc/profile-templates/sbuild/linux/fstab)
|
||||
bind_dev=no
|
||||
;;
|
||||
(*)
|
||||
break
|
||||
esac
|
||||
done
|
||||
|
||||
CHROOT_PATH="$1"
|
||||
shift
|
||||
if test -z "$CHROOT_PATH" || test -z "$1"; then
|
||||
echo "Usage: $0 CHROOT COMMAND...">&2
|
||||
exit 2
|
||||
fi
|
||||
|
||||
[ "$bind_dev" = no ] || mount --bind /dev "$CHROOT_PATH/dev"
|
||||
mount -t devpts -o rw,newinstance,ptmxmode=666,mode=620,gid=5 /dev/pts "$CHROOT_PATH/dev/pts"
|
||||
|
||||
ls -l "/dev/ptmx" | sed -e 's/^/# fake-schroot: outside chroot: /' >&2
|
||||
ls -l "/dev/pts/ptmx" | sed -e 's/^/# fake-schroot: outside chroot: /' >&2
|
||||
|
||||
ls -l "$CHROOT_PATH/dev/ptmx" | sed -e 's/^/# fake-schroot: after first step: /' >&2
|
||||
ls -l "$CHROOT_PATH/dev/pts/ptmx" | sed -e 's/^/# fake-schroot: after first step: /' >&2
|
||||
|
||||
mounted_ptmx=no
|
||||
|
||||
# Depending on how /dev was set up, /dev/ptmx might either be
|
||||
# character device (5,2), or a symbolic link to pts/ptmx.
|
||||
# Either way we want it to be equivalent to /dev/pts/ptmx, assuming
|
||||
# both exist.
|
||||
if [ -e "$CHROOT_PATH/dev/pts/ptmx" ] && \
|
||||
[ -e "$CHROOT_PATH/dev/ptmx" ] && \
|
||||
! [ "$CHROOT_PATH/dev/pts/ptmx" -ef "$CHROOT_PATH/dev/ptmx" ]; then
|
||||
mount --bind "$CHROOT_PATH/dev/pts/ptmx" "$CHROOT_PATH/dev/ptmx"
|
||||
mounted_ptmx=yes
|
||||
fi
|
||||
|
||||
mounted_console=no
|
||||
|
||||
# If schroot was invoked from a terminal, we still want to be able to
|
||||
# access that terminal. lxc and systemd-nspawn achieve this by
|
||||
# binding it onto /dev/console; so can we.
|
||||
if stdin_tty="$(tty)"; then
|
||||
if [ ! -e "$CHROOT_PATH/dev/console" ]; then
|
||||
# We need something to mount onto, and it might as well be
|
||||
# the correctly-numbered device node.
|
||||
mknod -m700 "$CHROOT_PATH/dev/console" c 5 1
|
||||
fi
|
||||
|
||||
mount --bind "$stdin_tty" "$CHROOT_PATH/dev/console"
|
||||
mounted_console=yes
|
||||
fi
|
||||
|
||||
ls -l "$CHROOT_PATH/dev/console" | sed -e 's/^/# fake-schroot: after fixing mounts: /' >&2
|
||||
ls -l "$CHROOT_PATH/dev/ptmx" | sed -e 's/^/# fake-schroot: after fixing mounts: /' >&2
|
||||
ls -l "$CHROOT_PATH/dev/pts/ptmx" | sed -e 's/^/# fake-schroot: after fixing mounts: /' >&2
|
||||
|
||||
e=0
|
||||
chroot "$CHROOT_PATH" "$@" || e=$?
|
||||
|
||||
[ "$mounted_console" = no ] || umount "$CHROOT_PATH/dev/console"
|
||||
[ "$mounted_ptmx" = no ] || umount "$CHROOT_PATH/dev/ptmx"
|
||||
umount "$CHROOT_PATH/dev/pts"
|
||||
[ "$bind_dev" = no ] || umount "$CHROOT_PATH/dev"
|
||||
|
||||
exit "$e"
|
98
debian/tests/out-of-order-mitm.py
vendored
Normal file
98
debian/tests/out-of-order-mitm.py
vendored
Normal file
|
@ -0,0 +1,98 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (C) 2023 Debian Install System Team <debian-boot@lists.debian.org>
|
||||
#
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
"""Flask app which MITM's an archive to generate out-of-order apt lists.
|
||||
|
||||
Specifically, it prepends an additional Packages file stanza for a non-existent
|
||||
lower version of apt: a fixed version of debootstrap will find the second
|
||||
(correct) apt stanza and succeed; a broken version of debootstrap will find
|
||||
only the first (non-existent) apt stanza and fail.
|
||||
"""
|
||||
import functools
|
||||
import gzip
|
||||
import hashlib
|
||||
import os
|
||||
|
||||
import requests
|
||||
from debian.deb822 import Packages
|
||||
from flask import Flask, redirect
|
||||
|
||||
app = Flask(__name__)
|
||||
|
||||
ARCH = os.environ.get("FLASK_ARCH", "amd64")
|
||||
DIST = os.environ.get("FLASK_DIST", "trixie")
|
||||
DISTRO = os.environ.get("FLASK_DISTRO", "debian")
|
||||
MIRROR = os.environ.get("FLASK_MIRROR", "http://deb.debian.org")
|
||||
|
||||
|
||||
if DISTRO in ("debian", "pureos"):
|
||||
hash_funcs = [hashlib.md5, hashlib.sha256]
|
||||
else:
|
||||
# Ubuntu includes SHA1 still
|
||||
hash_funcs = [hashlib.md5, hashlib.sha1, hashlib.sha256]
|
||||
|
||||
|
||||
def _munge_release_file(url: str) -> bytes:
|
||||
"""Given a Release file URL, rewrite it for our modified Packages content."""
|
||||
original = requests.get(MIRROR + "/" + url).content
|
||||
packages_content = _packages_content(
|
||||
f"{DISTRO}/dists/{DIST}/main/binary-{ARCH}/Packages"
|
||||
)
|
||||
size = bytes(str(len(packages_content)), "ascii")
|
||||
sums = [
|
||||
bytes(hash_func(packages_content).hexdigest(), "ascii")
|
||||
for hash_func in hash_funcs
|
||||
]
|
||||
new_lines = []
|
||||
filename = f"main/binary-{ARCH}/Packages".encode("ascii")
|
||||
for line in original.splitlines():
|
||||
if not line.endswith(filename):
|
||||
new_lines.append(line)
|
||||
continue
|
||||
new_lines.append(b" ".join([b"", sums.pop(0), size, filename]))
|
||||
return b"\n".join(new_lines)
|
||||
|
||||
|
||||
@functools.lru_cache
|
||||
def _packages_content(url: str) -> bytes:
|
||||
"""Given a Packages URL, fetch it and prepend a broken apt stanza."""
|
||||
resp = requests.get(MIRROR + "/" + url + ".gz")
|
||||
upstream_content = gzip.decompress(resp.content)
|
||||
|
||||
# Find the first `apt` stanza
|
||||
for stanza in Packages.iter_paragraphs(upstream_content):
|
||||
if stanza["Package"] == "apt":
|
||||
break
|
||||
|
||||
# Generate the broken stanza
|
||||
new_version = stanza["Version"] + "~test"
|
||||
stanza["Filename"] = stanza["Filename"].replace(stanza["Version"], new_version)
|
||||
stanza["Version"] = new_version
|
||||
|
||||
# Prepend the stanza to the upstream content
|
||||
return bytes(stanza) + b"\n" + upstream_content
|
||||
|
||||
|
||||
@app.route("/<path:url>", methods=["GET", "POST"])
|
||||
def root(url):
|
||||
"""Handler for all requests."""
|
||||
if (
|
||||
url == f"{DISTRO}/dists/{DIST}/InRelease"
|
||||
or "by-hash" in url
|
||||
or "Packages.xz" in url
|
||||
or "Packages.gz" in url
|
||||
):
|
||||
# 404 these URLs to force clients to fetch by path and without compression, to
|
||||
# make MITM easier
|
||||
return "", 404
|
||||
if url == f"{DISTRO}/dists/{DIST}/Release":
|
||||
# If Release is being fetched, return our modified version
|
||||
return _munge_release_file(url)
|
||||
if url == f"{DISTRO}/dists/{DIST}/main/binary-{ARCH}/Packages":
|
||||
# If Packages is being fetched, return our modified version
|
||||
return _packages_content(url)
|
||||
# For anything we don't need to modify, redirect clients to upstream mirror
|
||||
return redirect(f"{MIRROR}/{url}")
|
34
debian/tests/unsorted-packages-files
vendored
Executable file
34
debian/tests/unsorted-packages-files
vendored
Executable file
|
@ -0,0 +1,34 @@
|
|||
#!/bin/sh
|
||||
|
||||
# This test runs the out-of-order-mitm.py Flask app which debootstrap is then
|
||||
# pointed at.
|
||||
# out-of-order-mitm.py will return a Packages file which has an additional
|
||||
# `apt` stanza prepended, with the Version and Filename adjusted to point at
|
||||
# a lower, non-existent version. Versions of debootstrap which process
|
||||
# _all_ Packages files entries will find the original stanza later in the file
|
||||
# (and succesfully fetch the corresponding package file): versions that don't
|
||||
# will find the prepended stanza and fail (with a 404 of the nonexistent
|
||||
# package file).
|
||||
|
||||
export FLASK_ARCH="$(dpkg --print-architecture)"
|
||||
export FLASK_DIST=testing
|
||||
export FLASK_DISTRO=debian
|
||||
export FLASK_MIRROR=http://deb.debian.org
|
||||
export PATH=$PATH:/usr/sbin
|
||||
|
||||
# Launch our MitM "mirror" server, ensure that request logging is sent to stdout
|
||||
PYTHONDONTWRITEBYTECODE=true FLASK_APP=debian/tests/out-of-order-mitm.py flask run 2>&1 &
|
||||
flask_pid=$!
|
||||
|
||||
# Give Flask time to come up
|
||||
sleep 2
|
||||
|
||||
tempdir=$(mktemp -d)
|
||||
# Run debootstrap against our MitM "mirror", ignoring the inevitable GPG errors
|
||||
debootstrap --download-only --variant minbase --no-check-sig ${FLASK_DIST} $tempdir http://127.0.0.1:5000/${FLASK_DISTRO}/
|
||||
rc=$?
|
||||
|
||||
rm -rf $tempdir
|
||||
kill $flask_pid
|
||||
|
||||
exit $rc
|
Loading…
Add table
Add a link
Reference in a new issue