From 15029c1c3bb3057c7105be19a004c1974c37950c Mon Sep 17 00:00:00 2001 From: Joe Groocock Date: Wed, 18 Aug 2021 22:15:05 +0200 Subject: [PATCH] improve error message for missing /etc/subuid entry (closes: #9) --- coverage.sh | 59 ++++++++++++++++++++++++++++++++++++++++++++++++++++- mmdebstrap | 29 ++++++++++++++++++++++---- 2 files changed, 83 insertions(+), 5 deletions(-) diff --git a/coverage.sh b/coverage.sh index 61223c9..367a3b6 100755 --- a/coverage.sh +++ b/coverage.sh @@ -120,7 +120,7 @@ if [ ! -e shared/hooks/eatmydata/customize.sh ] || [ hooks/eatmydata/customize.s fi fi starttime= -total=196 +total=198 skipped=0 runtests=0 i=1 @@ -526,6 +526,63 @@ else runtests=$((runtests+1)) fi +print_header "mode=unshare,variant=apt: fail without /etc/subuid" +cat << END > shared/test.sh +#!/bin/sh +set -eu +export LC_ALL=C.UTF-8 +if [ ! -e /mmdebstrap-testenv ]; then + echo "this test modifies the system and should only be run inside a container" >&2 + exit 1 +fi +adduser --gecos user --disabled-password user +sysctl -w kernel.unprivileged_userns_clone=1 +rm /etc/subuid +ret=0 +runuser -u user -- $CMD --mode=unshare --variant=apt $DEFAULT_DIST /tmp/debian-chroot $mirror || ret=\$? +if [ "\$ret" = 0 ]; then + echo expected failure but got exit \$ret >&2 + exit 1 +fi +rm -r /tmp/debian-chroot +END +if [ "$HAVE_QEMU" = "yes" ]; then + ./run_qemu.sh + runtests=$((runtests+1)) +else + echo "HAVE_QEMU != yes -- Skipping test..." >&2 + skipped=$((skipped+1)) +fi + +print_header "mode=unshare,variant=apt: fail without username in /etc/subuid" +cat << END > shared/test.sh +#!/bin/sh +set -eu +export LC_ALL=C.UTF-8 +if [ ! -e /mmdebstrap-testenv ]; then + echo "this test modifies the system and should only be run inside a container" >&2 + exit 1 +fi +adduser --gecos user --disabled-password user +sysctl -w kernel.unprivileged_userns_clone=1 +awk -F: '\$1!="user"' /etc/subuid > /etc/subuid.tmp +mv /etc/subuid.tmp /etc/subuid +ret=0 +runuser -u user -- $CMD --mode=unshare --variant=apt $DEFAULT_DIST /tmp/debian-chroot $mirror || ret=\$? +if [ "\$ret" = 0 ]; then + echo expected failure but got exit \$ret >&2 + exit 1 +fi +rm -r /tmp/debian-chroot +END +if [ "$HAVE_QEMU" = "yes" ]; then + ./run_qemu.sh + runtests=$((runtests+1)) +else + echo "HAVE_QEMU != yes -- Skipping test..." >&2 + skipped=$((skipped+1)) +fi + # Before running unshare mode as root, we run "unshare --mount" but that fails # if mmdebstrap itself is executed from within a chroot: # unshare: cannot change root filesystem propagation: Invalid argument diff --git a/mmdebstrap b/mmdebstrap index 115e310..485140e 100755 --- a/mmdebstrap +++ b/mmdebstrap @@ -345,6 +345,14 @@ sub read_subuid_subgid() { last if ($n eq $username); } close $fh; + if (!length $subid) { + warning "/etc/subuid is empty"; + return; + } + if ($n ne $username) { + warning "no entry in /etc/subuid for $username"; + return; + } push @result, ["u", 0, $subid, $num_subid]; if (scalar(@result) < 1) { @@ -363,6 +371,14 @@ sub read_subuid_subgid() { last if ($n eq $username); } close $fh; + if (!length $subid) { + warning "/etc/subgid is empty"; + return; + } + if ($n ne $username) { + warning "no entry in /etc/subgid for $username"; + return; + } push @result, ["g", 0, $subid, $num_subid]; if (scalar(@result) < 2) { @@ -4250,8 +4266,11 @@ sub main() { if ($EFFECTIVE_USER_ID != 0 && !test_unshare_userns(1)) { exit 1; } - my @idmap = read_subuid_subgid; - my $pid = get_unshare_cmd( + my @idmap = (); + if ($EFFECTIVE_USER_ID != 0) { + @idmap = read_subuid_subgid; + } + my $pid = get_unshare_cmd( sub { 0 == system @ARGV[1 .. $#ARGV] or error "system failed: $?"; }, @@ -5372,12 +5391,14 @@ sub main() { my @idmap; # for unshare mode the rootfs directory has to have appropriate # permissions - if ($options->{mode} eq 'unshare') { + if ($EFFECTIVE_USER_ID != 0 and $options->{mode} eq 'unshare') { @idmap = read_subuid_subgid; # sanity check if ( scalar(@idmap) != 2 || $idmap[0][0] ne 'u' - || $idmap[1][0] ne 'g') { + || $idmap[1][0] ne 'g' + || !length $idmap[0][2] + || !length $idmap[1][2]) { error "invalid idmap"; }