Preliminary idea for PID namespaces
This commit is contained in:
parent
1dcfccb512
commit
b78dcaaaab
1 changed files with 54 additions and 15 deletions
|
@ -5,6 +5,7 @@ use warnings;
|
||||||
|
|
||||||
use Sys::Linux::Mount qw/:all/;
|
use Sys::Linux::Mount qw/:all/;
|
||||||
use Sys::Linux::Unshare qw/:all/;
|
use Sys::Linux::Unshare qw/:all/;
|
||||||
|
use POSIX qw/_exit/;
|
||||||
|
|
||||||
sub namespace {
|
sub namespace {
|
||||||
my ($options) = @_;
|
my ($options) = @_;
|
||||||
|
@ -12,20 +13,7 @@ sub namespace {
|
||||||
my $uflags = 0;
|
my $uflags = 0;
|
||||||
my $mflags = 0;
|
my $mflags = 0;
|
||||||
|
|
||||||
if ($options->{pid}) {
|
my $post_setup = sub {
|
||||||
die "TODO, need to setup a proper 'init' PID 1";
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($options->{mount} || $options->{private_mount} || $options->{private_tmp}) {
|
|
||||||
$uflags |= CLONE_NEWNS;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($options->{net}) {
|
|
||||||
die "TODO, need to setup network interfaces";
|
|
||||||
}
|
|
||||||
|
|
||||||
unshare($uflags);
|
|
||||||
|
|
||||||
# If we want a private /tmp, or private mount we need to recursively make every mount private. it CAN be done without that but this is more reliable.
|
# If we want a private /tmp, or private mount we need to recursively make every mount private. it CAN be done without that but this is more reliable.
|
||||||
if ($options->{private_mount} || $options->{private_tmp}) {
|
if ($options->{private_mount} || $options->{private_tmp}) {
|
||||||
mount("/", "/", undef, MS_REC|MS_PRIVATE, undef);
|
mount("/", "/", undef, MS_REC|MS_PRIVATE, undef);
|
||||||
|
@ -40,4 +28,55 @@ sub namespace {
|
||||||
mount("/tmp", "/tmp", "tmpfs", MS_PRIVATE, undef);
|
mount("/tmp", "/tmp", "tmpfs", MS_PRIVATE, undef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if (ref $options->{pid} eq 'CODE') {
|
||||||
|
$uflags |= CLONE_NEWPID;
|
||||||
|
} elsif (ref $options->{pid}) {
|
||||||
|
die "New PID namespace requires a coderef";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($options->{mount} || $options->{private_mount} || $options->{private_tmp}) {
|
||||||
|
$uflags |= CLONE_NEWNS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($options->{net}) {
|
||||||
|
die "TODO, need to setup network interfaces";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ref $options->{pid} eq 'CODE') {
|
||||||
|
my $mid_pid = fork();
|
||||||
|
|
||||||
|
unless($mid_pid == -1) {
|
||||||
|
if($mid_pid) {
|
||||||
|
# Original Process
|
||||||
|
waitpid($mid_pid); # WE MUST BLOCK
|
||||||
|
return; # don't run anything else in here
|
||||||
|
} else {
|
||||||
|
# Middle child process
|
||||||
|
unshare($uflags); # Setup the namespaces
|
||||||
|
$post_setup->();
|
||||||
|
my $child_pid = fork();
|
||||||
|
|
||||||
|
unless($child_pid == -1) {
|
||||||
|
if ($child_pid) {
|
||||||
|
waitpid($child_pid);
|
||||||
|
} else {
|
||||||
|
$options->{pid}->();
|
||||||
|
}
|
||||||
|
|
||||||
|
# exit and do no cleanup, don't continue running the program, or any END{} blocks
|
||||||
|
# This is so that we don't cause anything to go wrong in the parent because something was left around
|
||||||
|
_exit(0);
|
||||||
|
} else {
|
||||||
|
die "Couldn't make PID 1: $!";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
die "Couldn't fork $!";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
unshare($uflags);
|
||||||
|
$post_setup->();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue