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'

Attachment: signature.asc
Description: Digital signature

Reply via email to