1
0
Fork 0
mirror of https://github.com/perlbot/perlbuut synced 2025-06-07 16:45:40 -04:00

Reorg the evalserver code a little

This commit is contained in:
Ryan Voots 2017-05-05 13:19:32 -07:00
parent 0258d79682
commit 1a9145aec1
4 changed files with 95 additions and 75 deletions

@ -1 +1 @@
Subproject commit fe69764c77d5f9047c006de6944d4a36b46e510e
Subproject commit afea70ce7a9ce085620a20101d85af40eca16f92

View file

@ -8,20 +8,7 @@ use POE::Filter::Line;
use POE::Filter::Stream;
use POE::Wheel::Run;
use strict;
use Config;
use Sys::Linux::Namespace;
use Sys::Linux::Mount qw/:all/;
my %sig_map;
use FindBin;
do {
my @sig_names = split ' ', $Config{sig_name};
my @sig_nums = split ' ', $Config{sig_num};
@sig_map{@sig_nums} = map {'SIG' . $_} @sig_names;
$sig_map{31} = "SIGSYS (Illegal Syscall)";
};
my $namespace = Sys::Linux::Namespace->new(private_pid => 1, no_proc => 1, private_mount => 1, private_uts => 1, private_ipc => 1, private_sysvsem => 1);
use EvalServer::Sandbox;
sub start {
my( $class ) = @_;
@ -54,31 +41,8 @@ sub spawn_eval {
}
warn "Spawning Eval: $args->{code}\n";
my $wheel = POE::Wheel::Run->new(
Program => sub {
$namespace->run(code => sub {
mount($FindBin::Bin."/../jail_root", $FindBin::Bin."/../jail", undef, MS_BIND|MS_RDONLY, undef);
mount("tmpfs", $FindBin::Bin."/../jail/tmp", "tmpfs", 0, {size => "16m"});
mount("tmpfs", $FindBin::Bin."/../jail/tmp", "tmpfs", MS_PRIVATE, {size => "16m"});
mount("/lib64", $FindBin::Bin."/../jail/lib64", undef, MS_BIND|MS_PRIVATE|MS_RDONLY, undef);
mount("/lib", $FindBin::Bin."/../jail/lib", undef, MS_BIND|MS_PRIVATE|MS_RDONLY, undef);
mount("/usr/bin", $FindBin::Bin."/../jail/usr/bin", undef, MS_BIND|MS_PRIVATE|MS_RDONLY, undef);
mount("/usr/lib", $FindBin::Bin."/../jail/usr/lib", undef, MS_BIND|MS_PRIVATE|MS_RDONLY, undef);
mount("/home/ryan/perl5", $FindBin::Bin."/../jail/perl5", undef, MS_BIND|MS_PRIVATE|MS_RDONLY, undef);
#my $q = qx|ls -lh /home/ryan/bots/perlbuut/jail/perl5/perlbrew/perls/perl-5.18*/bin|;
#print $q;
system($^X, $filename);
my ($exit, $signal) = (($?&0xFF00)>>8, $?&0xFF);
if ($exit) {
print "[Exited $exit]";
} elsif ($signal) {
my $signame = $sig_map{$signal} // $signal;
print "[Died $signame]";
}
});
},
ProgramArgs => [ ],
Program => \&EvalServer::Sandbox::run_eval,
ProgramArgs => [ ],
CloseOnCall => 1, #Make sure all of the filehandles are closed.
Priority => 10, #Let's be nice!

73
lib/EvalServer/Sandbox.pm Normal file
View file

@ -0,0 +1,73 @@
package EvalServer::Sandbox;
use strict;
use warnings;
use Config;
use Sys::Linux::Namespace;
use Sys::Linux::Mount qw/:all/;
my %sig_map;
use FindBin;
do {
my @sig_names = split ' ', $Config{sig_name};
my @sig_nums = split ' ', $Config{sig_num};
@sig_map{@sig_nums} = map {'SIG' . $_} @sig_names;
$sig_map{31} = "SIGSYS (Illegal Syscall)";
};
my $namespace = Sys::Linux::Namespace->new(private_pid => 1, no_proc => 1, private_mount => 1, private_uts => 1, private_ipc => 1, private_sysvsem => 1);
# {files => [
# {filename => '...',
# contents => '...',},
# ...,],
# main_file => 'filename',
# main_language => '',
# }
#
sub run_eval {
my $code = shift; # TODO this should be more than just code
my $jail_path = $FindBin::Bin."/../jail";
my $jail_root_path = $FindBin::Bin."/../jail_root";
my $filename = '/eval/elib/eval.pl';
$namespace->run(code => sub {
my @binds = (
{src => $jail_root_path, target => "/"},
{src => "/lib64", target => "/lib64"},
{src => "/lib", target => "/lib"},
{src => "/usr/lib", target => "/usr/lib"},
{src => "/usr/bin", target => "/usr/bin"},
{src => "/home/ryan/perl5", target => "/perl5"},
{src => "/home/ryan/perl5", target => "/home/ryan/perl5"},
{src => $FindBin::Bin."/../lib", target => "/eval/elib"},
);
for my $bind (@binds) {
# printf "mount: %s => %s\n", $bind->{src}, $jail_path . $bind->{target};
mount($bind->{src}, $jail_path . $bind->{target}, undef, MS_BIND|MS_PRIVATE|MS_RDONLY, undef);
}
mount("tmpfs", $FindBin::Bin."/../jail/tmp", "tmpfs", 0, {size => "16m"});
mount("tmpfs", $FindBin::Bin."/../jail/tmp", "tmpfs", MS_PRIVATE, {size => "16m"});
chdir($jail_path) or die "Jail not made, see bin/makejail.sh";
chroot($jail_path) or die $!;
system("/perl5/perlbrew/perls/perlbot-inuse/bin/perl", $filename);
my ($exit, $signal) = (($?&0xFF00)>>8, $?&0xFF);
if ($exit) {
print "[Exited $exit]";
} elsif ($signal) {
my $signame = $sig_map{$signal} // $signal;
print "[Died $signame]";
}
});
}
1;

View file

@ -328,24 +328,13 @@ use Storable qw/nfreeze/; nfreeze([]); #Preload Nfreeze since it's loaded on dem
chomp $q; $q
};
my $code;
# if ($type ne 'perl4') { # Perl 4 has special needs. It rides on the short bus.
$code = do {local $/; <STDIN>};
# redirect STDIN to /dev/null, to avoid warnings in convoluted cases.
# we have to leave this open for perl4, so only do this for other systems
open STDIN, '<', '/dev/null' or die "Can't open /dev/null: $!";
# }
# print Dumper({type => $type, code => $code});
# Close every other filehandle we may have open
# this is probably legacy code at this point since it was used
# inside the original bb2 which forked to execute this code.
opendir my $dh, "/proc/self/fd" or die $!;
while(my $fd = readdir($dh)) { next unless $fd > 2; POSIX::close($fd) }
my $code = do {local $/; <STDIN>};
# redirect STDIN to /dev/null, to avoid warnings in convoluted cases.
# we have to leave this open for perl4, so only do this for other systems
open STDIN, '<', '/dev/null' or die "Can't open /dev/null: $!";
# Get the nobody uid before we chroot.
my $nobody_uid = getpwnam("nobody");
my $nobody_uid = 65534; #getpwnam("nobody");
die "Error, can't find a uid for 'nobody'. Replace with someone who exists" unless $nobody_uid;
# Set the CPU LIMIT.
@ -362,27 +351,23 @@ use Storable qw/nfreeze/; nfreeze([]); #Preload Nfreeze since it's loaded on dem
# }
# The chroot section
chdir($FindBin::Bin."/../jail") or die "Jail not made, see bin/makejail.sh";
chroot(".") or die $!;
chdir("/eval") or die $!;
# It's now safe for us to do this so that we can load modules and files provided by the user
push @INC, "/eval/lib";
if ($< == 0) {
# Here's where we actually drop our root privilege
$)="$nobody_uid $nobody_uid";
$(=$nobody_uid;
$<=$>=$nobody_uid;
POSIX::setgid($nobody_uid); #We just assume the uid is the same as the gid. Hot.
if ($< == 0) {
# Here's where we actually drop our root privilege
$)="$nobody_uid $nobody_uid";
$(=$nobody_uid;
$<=$>=$nobody_uid;
POSIX::setgid($nobody_uid); #We just assume the uid is the same as the gid. Hot.
die "Failed to drop to nobody"
if $> != $nobody_uid
or $< != $nobody_uid;
}
die "Failed to drop to nobody"
if $> != $nobody_uid
or $< != $nobody_uid;
}
my $kilo = 1024;
my $meg = $kilo * $kilo;
@ -413,16 +398,14 @@ use Storable qw/nfreeze/; nfreeze([]); #Preload Nfreeze since it's loaded on dem
)
or die "Failed to set rlimit: $!";
%ENV=(TZ=>'Asia/Pyongyang');
%ENV=(TZ=>'Asia/Pyongyang');
#setrlimit(RLIMIT_MSGQUEUE,100,100);
die "Failed to drop root: $<" if $< == 0;
# close STDIN;
# Setup SECCOMP for us
get_seccomp($type);
# Setup SECCOMP for us
get_seccomp($type);
# Chomp code..
$code =~ s/\s*$//;