David: On Sun, Dec 28, 2014 at 07:35:14PM +0100, David Emanuel da Costa Santiago wrote: > Hello!
Hello,
> How do i run and pass arguments to an anonymous subroutine that i shared
> on a safe compartment?
>
> My goal is to have a function that perform "dangerous" operations, that
> must be available to untrusted code, however this function needs some
> parameters that are only available when the code is executing, and the
> untrusted code doesn't know them (hence the anonymous subroutine).
>
> Example (35 lines):
>
> ### Example.pl file
> use strict;
> use warnings;
> use Safe;
> use 5.020;
>
> my $UNTRUSTED_SCRIPT="untrusted_script.pl";
>
> sub run_me{
>
> my $sandbox = Safe->new("Sandbox");
> $sandbox->permit(qw(:base_core :base_loop :base_mem :base_io :load
> :base_orig));
> $sandbox->deny(qw(die exit));
>
> my $operation = "Dangerous";
>
> my $anon_func = sub{
> my $param = shift;
> print "$operation $param operation!\n";
> };
>
> $sandbox->share($anon_func);
> $sandbox->rdo($UNTRUSTED_SCRIPT);
> $sandbox->reval('func1()');
> }
>
> run_me();
>
> ### untrusted_script.pl
> use 5.020;
> use warnings;
> use utf8;
>
>
> sub func1{
> say "About to run shared function!";
> $anon_func->("func1");
> }
>
> ######
>
> The output of the Example.pl script is:
>
> Error while executing the sandbox: Global symbol "$anon_func" requires
> explicit package name at untrusted_script.pl line 5.
>
> I was expecting of the output of the Example.pl script to be
> "Dangerous func1 operation!". What am i doing wrong?
I am not familiar with Safe.pm so I don't know anything about
that, but $anon_func is a lexically scoped variable in
Example.pl. That variable is not available within the
untrusted_script.pl file. I also don't see a subroutine or
anything at all named "func1" defined so I can't imagine how
$sandbox->reval('func1()') is supposed to work.
I think that the first part that you're having trouble with is
sharing data (or code) with the "compartment". I think that if
you want for $anon_func to be available to the Safe compartment,
and therefore the untrusted_script.pl when executed with the Safe
compartment, you need to pass the name of the anonymous function
variable instead of the variable itself.
$sandbox->share('$anon_func');
It also appears that you cannot share lexical variables with
these compartments (see perldoc Safe) so you need to make
$anon_func a package variable (or copy it to one). A named
function would work too. So either:
our $anon_func = sub { ... };
...
$sandbox->share('$anon_func');
Or else:
sub shared_func = sub { ... };
...
$sandbox->share('&shared_func');
A bareword passed to Safe::share is apparently assumed to be a
named function too. You can also use Safe::share_from to share a
subroutine from a different package than the caller.
I worked out a little contrived example to figure this out
myself:
./program:
#!/usr/bin/env perl
use strict;
use warnings;
use Safe;
my $sandbox = Safe->new();
$sandbox->permit(qw/print/);
# Shared variables cannot be lexicals!
our $get_id = do {
my $id = 0;
sub {
my ($base) = @_;
my $result = "${base}${id}";
++$id;
return $result;
};
};
$sandbox->share('$get_id');
$sandbox->rdo('unsafe') or die $!;
__END__
./unsafe:
my $id = $get_id->("foo_");
print "Unsafe script got id $id!\n";
__END__
Output should be:
$ ./program
Unsafe script got id foo_0!
Regards,
--
Brandon McCaig <[email protected]> <[email protected]>
Castopulence Software <https://www.castopulence.org/>
Blog <http://www.bamccaig.com/>
perl -E '$_=q{V zrna gur orfg jvgu jung V fnl. }.
q{Vg qbrfa'\''g nyjnlf fbhaq gung jnl.};
tr/A-Ma-mN-Zn-z/N-Zn-zA-Ma-m/;say'
signature.asc
Description: Digital signature
