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 <bamcc...@gmail.com> <bamcc...@castopulence.org> 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