Compare commits
No commits in common. "ff9b76ed19eb414adfd9ee8a539954c0b36a8cb6" and "055e1719b95960496a0cda88535fd00e9a395516" have entirely different histories.
ff9b76ed19
...
055e1719b9
1 changed files with 46 additions and 29 deletions
75
mmdebstrap
75
mmdebstrap
|
@ -305,18 +305,23 @@ sub shellescape {
|
||||||
|
|
||||||
sub test_unshare_userns {
|
sub test_unshare_userns {
|
||||||
my $verbose = shift;
|
my $verbose = shift;
|
||||||
|
my $fail = shift;
|
||||||
|
|
||||||
local *maybe_error = sub {
|
local *maybe_warn = sub {
|
||||||
my $msg = shift;
|
my $msg = shift;
|
||||||
if ($verbose) {
|
if ($verbose) {
|
||||||
error $msg;
|
if ($fail) {
|
||||||
|
error $msg;
|
||||||
|
} else {
|
||||||
|
warning $msg;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
debug $msg;
|
debug $msg;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if ($EFFECTIVE_USER_ID == 0) {
|
if ($EFFECTIVE_USER_ID == 0) {
|
||||||
maybe_error("cannot unshare user namespace when executing as root");
|
maybe_warn("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
|
||||||
|
@ -330,7 +335,7 @@ sub test_unshare_userns {
|
||||||
if ($ret == 0) {
|
if ($ret == 0) {
|
||||||
exit 0;
|
exit 0;
|
||||||
} else {
|
} else {
|
||||||
maybe_error("unshare syscall failed: $!");
|
maybe_warn("unshare syscall failed: $!");
|
||||||
exit 1;
|
exit 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -343,28 +348,28 @@ 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) {
|
||||||
maybe_error("cannot find newuidmap");
|
maybe_warn("cannot find newuidmap");
|
||||||
} else {
|
} else {
|
||||||
maybe_error("newuidmap returned unknown exit status: $?");
|
maybe_warn("newuidmap returned unknown exit status: $?");
|
||||||
}
|
}
|
||||||
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) {
|
||||||
maybe_error("cannot find newgidmap");
|
maybe_warn("cannot find newgidmap");
|
||||||
} else {
|
} else {
|
||||||
maybe_error("newgidmap returned unknown exit status: $?");
|
maybe_warn("newgidmap returned unknown exit status: $?");
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
my @idmap = read_subuid_subgid($verbose);
|
my @idmap = read_subuid_subgid($verbose);
|
||||||
if (scalar @idmap == 0) {
|
if (scalar @idmap == 0) {
|
||||||
maybe_error("failed to parse /etc/subuid and /etc/subgid");
|
maybe_warn("failed to parse /etc/subuid and /etc/subgid");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
# too much can go wrong when doing the dance required to unsharing the user
|
# 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()
|
# namespace, so instead of adding more complexity to support maybe_warn()
|
||||||
# to a function that is already too complex, we use eval()
|
# to a function that is already too complex, we use eval()
|
||||||
eval {
|
eval {
|
||||||
$pid = get_unshare_cmd(
|
$pid = get_unshare_cmd(
|
||||||
|
@ -379,12 +384,12 @@ sub test_unshare_userns {
|
||||||
);
|
);
|
||||||
waitpid $pid, 0;
|
waitpid $pid, 0;
|
||||||
if ($? != 0) {
|
if ($? != 0) {
|
||||||
maybe_error("failed to unshare the user namespace");
|
maybe_warn("failed to unshare the user namespace");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if ($@) {
|
if ($@) {
|
||||||
maybe_error($@);
|
maybe_warn($@);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -2265,7 +2270,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 0644, "$tmpfile" or error "cannot chmod $tmpfile: $!";
|
chmod 0666, "$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: $?";
|
||||||
|
@ -4367,8 +4372,8 @@ 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) {
|
if ($EFFECTIVE_USER_ID != 0 && !test_unshare_userns(1)) {
|
||||||
test_unshare_userns(1);
|
exit 1;
|
||||||
}
|
}
|
||||||
my @idmap = ();
|
my @idmap = ();
|
||||||
if ($EFFECTIVE_USER_ID != 0) {
|
if ($EFFECTIVE_USER_ID != 0) {
|
||||||
|
@ -4800,8 +4805,7 @@ 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 (use --mode for "
|
error "unable to pick chroot mode automatically";
|
||||||
. "manual selection)");
|
|
||||||
}
|
}
|
||||||
info "automatically chosen mode: $options->{mode}";
|
info "automatically chosen mode: $options->{mode}";
|
||||||
} elsif ($options->{mode} eq 'root') {
|
} elsif ($options->{mode} eq 'root') {
|
||||||
|
@ -4836,8 +4840,26 @@ 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) {
|
if ($EFFECTIVE_USER_ID != 0 && !test_unshare_userns(1, 1)) {
|
||||||
test_unshare_userns(1);
|
my $procfile = '/proc/sys/kernel/unprivileged_userns_clone';
|
||||||
|
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) {
|
||||||
|
@ -5173,14 +5195,12 @@ 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 '';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5225,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)$/) {
|
||||||
|
@ -5234,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}) {
|
||||||
|
@ -5242,7 +5262,6 @@ 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...";
|
||||||
|
@ -5266,7 +5285,6 @@ 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
|
||||||
|
@ -5283,7 +5301,6 @@ 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\"]";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6675,9 +6692,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 F</etc/subuid> and F</etc/subgid> are set up
|
B<unshare> mode is picked if the system has the sysctl
|
||||||
correctly. Should that not be the case and if the fakechroot binary exists, the
|
C<kernel.unprivileged_userns_clone> set to C<1>. Should that not be the case
|
||||||
B<fakechroot> mode is chosen.
|
and if the fakechroot binary exists, the B<fakechroot> mode is chosen.
|
||||||
|
|
||||||
=item B<sudo>, B<root>
|
=item B<sudo>, B<root>
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue