summaryrefslogtreecommitdiff
path: root/ext/Safe/Safe.pm
diff options
context:
space:
mode:
Diffstat (limited to 'ext/Safe/Safe.pm')
-rw-r--r--ext/Safe/Safe.pm670
1 files changed, 0 insertions, 670 deletions
diff --git a/ext/Safe/Safe.pm b/ext/Safe/Safe.pm
deleted file mode 100644
index 0fafcbe741..0000000000
--- a/ext/Safe/Safe.pm
+++ /dev/null
@@ -1,670 +0,0 @@
-package Safe;
-
-use vars qw($VERSION @ISA @EXPORT_OK);
-
-require Exporter;
-require DynaLoader;
-use Carp;
-$VERSION = "1.00";
-@ISA = qw(Exporter DynaLoader);
-@EXPORT_OK = qw(op_mask ops_to_mask mask_to_ops opcode opname opdesc
- MAXO emptymask fullmask);
-
-=head1 NAME
-
-Safe - Safe extension module for Perl
-
-=head1 DESCRIPTION
-
-The Safe extension module allows the creation of compartments
-in which perl code can be evaluated. Each compartment has
-
-=over 8
-
-=item a new namespace
-
-The "root" of the namespace (i.e. "main::") is changed to a
-different package and code evaluated in the compartment cannot
-refer to variables outside this namespace, even with run-time
-glob lookups and other tricks. Code which is compiled outside
-the compartment can choose to place variables into (or share
-variables with) the compartment's namespace and only that
-data will be visible to code evaluated in the compartment.
-
-By default, the only variables shared with compartments are the
-"underscore" variables $_ and @_ (and, technically, the much less
-frequently used %_, the _ filehandle and so on). This is because
-otherwise perl operators which default to $_ will not work and neither
-will the assignment of arguments to @_ on subroutine entry.
-
-=item an operator mask
-
-Each compartment has an associated "operator mask". Recall that
-perl code is compiled into an internal format before execution.
-Evaluating perl code (e.g. via "eval" or "do 'file'") causes
-the code to be compiled into an internal format and then,
-provided there was no error in the compilation, executed.
-Code evaulated in a compartment compiles subject to the
-compartment's operator mask. Attempting to evaulate code in a
-compartment which contains a masked operator will cause the
-compilation to fail with an error. The code will not be executed.
-
-By default, the operator mask for a newly created compartment masks
-out all operations which give "access to the system" in some sense.
-This includes masking off operators such as I<system>, I<open>,
-I<chown>, and I<shmget> but does not mask off operators such as
-I<print>, I<sysread> and I<E<lt>HANDLE<gt>>. Those file operators
-are allowed since for the code in the compartment to have access
-to a filehandle, the code outside the compartment must have explicitly
-placed the filehandle variable inside the compartment.
-
-Since it is only at the compilation stage that the operator mask
-applies, controlled access to potentially unsafe operations can
-be achieved by having a handle to a wrapper subroutine (written
-outside the compartment) placed into the compartment. For example,
-
- $cpt = new Safe;
- sub wrapper {
- # vet arguments and perform potentially unsafe operations
- }
- $cpt->share('&wrapper');
-
-=back
-
-=head2 Operator masks
-
-An operator mask exists at user-level as a string of bytes of length
-MAXO, each of which is either 0x00 or 0x01. Here, MAXO is the number
-of operators in the current version of perl. The subroutine MAXO()
-(available for export by package Safe) returns the number of operators
-in the current version of perl. Note that, unlike the beta versions of
-the Safe extension, this is a reliable count of the number of
-operators in the currently running perl executable. The presence of a
-0x01 byte at offset B<n> of the string indicates that operator number
-B<n> should be masked (i.e. disallowed). The Safe extension makes
-available routines for converting from operator names to operator
-numbers (and I<vice versa>) and for converting from a list of operator
-names to the corresponding mask (and I<vice versa>).
-
-=head2 Methods in class Safe
-
-To create a new compartment, use
-
- $cpt = new Safe;
-
-Optional arguments are (NAMESPACE, MASK), where
-
-=over 8
-
-=item NAMESPACE
-
-is the root namespace to use for the compartment (defaults to
-"Safe::Root000000000", auto-incremented for each new compartment); and
-
-=item MASK
-
-is the operator mask to use (defaults to a fairly restrictive set).
-
-=back
-
-The following methods can then be used on the compartment
-object returned by the above constructor. The object argument
-is implicit in each case.
-
-=over 8
-
-=item root (NAMESPACE)
-
-This is a get-or-set method for the compartment's namespace. With the
-NAMESPACE argument present, it sets the root namespace for the
-compartment. With no NAMESPACE argument present, it returns the
-current root namespace of the compartment.
-
-=item mask (MASK)
-
-This is a get-or-set method for the compartment's operator mask.
-With the MASK argument present, it sets the operator mask for the
-compartment. With no MASK argument present, it returns the
-current operator mask of the compartment.
-
-=item trap (OP, ...)
-
-This sets bits in the compartment's operator mask corresponding
-to each operator named in the list of arguments. Each OP can be
-either the name of an operation or its number. See opcode.h or
-opcode.pl in the main perl distribution for a canonical list of
-operator names.
-
-=item untrap (OP, ...)
-
-This resets bits in the compartment's operator mask corresponding
-to each operator named in the list of arguments. Each OP can be
-either the name of an operation or its number. See opcode.h or
-opcode.pl in the main perl distribution for a canonical list of
-operator names.
-
-=item share (VARNAME, ...)
-
-This shares the variable(s) in the argument list with the compartment.
-Each VARNAME must be the B<name> of a variable with a leading type
-identifier included. Examples of legal variable names are '$foo' for
-a scalar, '@foo' for an array, '%foo' for a hash, '&foo' for a
-subroutine and '*foo' for a glob (i.e. all symbol table entries
-associated with "foo", including scalar, array, hash, sub and filehandle).
-
-=item varglob (VARNAME)
-
-This returns a glob for the symbol table entry of VARNAME in the package
-of the compartment. VARNAME must be the B<name> of a variable without
-any leading type marker. For example,
-
- $cpt = new Safe 'Root';
- $Root::foo = "Hello world";
- # Equivalent version which doesn't need to know $cpt's package name:
- ${$cpt->varglob('foo')} = "Hello world";
-
-
-=item reval (STRING)
-
-This evaluates STRING as perl code inside the compartment. The code
-can only see the compartment's namespace (as returned by the B<root>
-method). Any attempt by code in STRING to use an operator which is
-in the compartment's mask will cause an error (at run-time of the
-main program but at compile-time for the code in STRING). The error
-is of the form "%s trapped by operation mask operation...". If an
-operation is trapped in this way, then the code in STRING will not
-be executed. If such a trapped operation occurs or any other
-compile-time or return error, then $@ is set to the error message,
-just as with an eval(). If there is no error, then the method returns
-the value of the last expression evaluated, or a return statement may
-be used, just as with subroutines and B<eval()>. Note that this
-behaviour differs from the beta distribution of the Safe extension
-where earlier versions of perl made it hard to mimic the return
-behaviour of the eval() command.
-
-=item rdo (FILENAME)
-
-This evaluates the contents of file FILENAME inside the compartment.
-See above documentation on the B<reval> method for further details.
-
-=back
-
-=head2 Subroutines in package Safe
-
-The Safe package contains subroutines for manipulating operator
-names and operator masks. All are available for export by the package.
-The canonical list of operator names is the contents of the array
-op_name defined and initialised in file F<opcode.h> of the Perl
-source distribution.
-
-=over 8
-
-=item ops_to_mask (OP, ...)
-
-This takes a list of operator names and returns an operator mask
-with precisely those operators masked.
-
-=item mask_to_ops (MASK)
-
-This takes an operator mask and returns a list of operator names
-corresponding to those operators which are masked in MASK.
-
-=item opcode (OP, ...)
-
-This takes a list of operator names and returns the corresponding
-list of opcodes (which can then be used as byte offsets into a mask).
-
-=item opname (OP, ...)
-
-This takes a list of opcodes and returns the corresponding list of
-operator names.
-
-=item fullmask
-
-This just returns a mask which has all operators masked.
-It returns the string "\1" x MAXO().
-
-=item emptymask
-
-This just returns a mask which has all operators unmasked.
-It returns the string "\0" x MAXO(). This is useful if you
-want a compartment to make use of the namespace protection
-features but do not want the default restrictive mask.
-
-=item MAXO
-
-This returns the number of operators (and hence the length of an
-operator mask). Note that, unlike the beta distributions of the
-Safe extension, this is derived from a genuine integer variable
-in the perl executable and not from a preprocessor constant.
-This means that the Safe extension is more robust in the presence
-of mismatched versions of the perl executable and the Safe extension.
-
-=item op_mask
-
-This returns the operator mask which is actually in effect at the
-time the invocation to the subroutine is compiled. In general,
-this is probably not terribly useful.
-
-=back
-
-=head2 AUTHOR
-
-Malcolm Beattie, mbeattie@sable.ox.ac.uk.
-
-=cut
-
-my $default_root = 'Root000000000';
-
-my $default_mask;
-
-sub new {
- my($class, $root, $mask) = @_;
- my $obj = {};
- bless $obj, $class;
- $obj->root(defined($root) ? $root : ("Safe::".$default_root++));
- $obj->mask(defined($mask) ? $mask : $default_mask);
- # We must share $_ and @_ with the compartment or else ops such
- # as split, length and so on won't default to $_ properly, nor
- # will passing argument to subroutines work (via @_). In fact,
- # for reasons I don't completely understand, we need to share
- # the whole glob *_ rather than $_ and @_ separately, otherwise
- # @_ in non default packages within the compartment don't work.
- *{$obj->root . "::_"} = *_;
- return $obj;
-}
-
-sub DESTROY {
- my($obj) = @_;
- my $root = $obj->root();
- if ($root =~ /^Safe::(Root\d+)$/){
- $root = $1;
- delete $ {"Safe::"}{"$root\::"};
- }
-}
-
-sub root {
- my $obj = shift;
- if (@_) {
- $obj->{Root} = $_[0];
- } else {
- return $obj->{Root};
- }
-}
-
-sub mask {
- my $obj = shift;
- if (@_) {
- $obj->{Mask} = verify_mask($_[0]);
- } else {
- return $obj->{Mask};
- }
-}
-
-sub verify_mask {
- my($mask) = @_;
- if (length($mask) != MAXO() || $mask !~ /^[\0\1]+$/) {
- croak("argument is not a mask");
- }
- return $mask;
-}
-
-sub trap {
- my $obj = shift;
- $obj->setmaskel("\1", @_);
-}
-
-sub untrap {
- my $obj = shift;
- $obj->setmaskel("\0", @_);
-}
-
-sub emptymask { "\0" x MAXO() }
-sub fullmask { "\1" x MAXO() }
-
-sub setmaskel {
- my $obj = shift;
- my $val = shift;
- croak("bad value for mask element") unless $val eq "\0" || $val eq "\1";
- my $maskref = \$obj->{Mask};
- my ($op, $opcode);
- foreach $op (@_) {
- $opcode = ($op =~ /^\d/) ? $op : opcode($op);
- substr($$maskref, $opcode, 1) = $val;
- }
-}
-
-sub share {
- my $obj = shift;
- my $root = $obj->root();
- my ($arg);
- foreach $arg (@_) {
- my $var;
- ($var = $arg) =~ s/^(.)//;
- my $caller = caller;
- *{$root."::$var"} = ($1 eq '$') ? \${$caller."::$var"}
- : ($1 eq '@') ? \@{$caller."::$var"}
- : ($1 eq '%') ? \%{$caller."::$var"}
- : ($1 eq '*') ? *{$caller."::$var"}
- : ($1 eq '&') ? \&{$caller."::$var"}
- : croak(qq(No such variable type for "$1$var"));
- }
-}
-
-sub varglob {
- my ($obj, $var) = @_;
- return *{$obj->root()."::$var"};
-}
-
-sub reval {
- my ($obj, $expr) = @_;
- my $root = $obj->{Root};
- my $mask = $obj->{Mask};
- verify_mask($mask);
-
- my $evalsub = eval sprintf(<<'EOT', $root);
- package %s;
- sub {
- eval $expr;
- }
-EOT
- return safe_call_sv($root, $mask, $evalsub);
-}
-
-sub rdo {
- my ($obj, $file) = @_;
- my $root = $obj->{Root};
- my $mask = $obj->{Mask};
- verify_mask($mask);
-
- $file =~ s/"/\\"/g; # just in case the filename contains any double quotes
- my $evalsub = eval sprintf(<<'EOT', $root, $file);
- package %s;
- sub {
- do "%s";
- }
-EOT
- return safe_call_sv($root, $mask, $evalsub);
-}
-
-bootstrap Safe $VERSION;
-
-$default_mask = fullmask;
-my $name;
-while (defined ($name = <DATA>)) {
- chomp $name;
- next if $name =~ /^#/;
- my $code = opcode($name);
- substr($default_mask, $code, 1) = "\0";
-}
-
-1;
-
-__DATA__
-null
-stub
-scalar
-pushmark
-wantarray
-const
-gvsv
-gv
-gelem
-padsv
-padav
-padhv
-padany
-pushre
-rv2gv
-rv2sv
-av2arylen
-rv2cv
-anoncode
-prototype
-refgen
-srefgen
-ref
-bless
-glob
-readline
-rcatline
-regcmaybe
-regcomp
-match
-subst
-substcont
-trans
-sassign
-aassign
-chop
-schop
-chomp
-schomp
-defined
-undef
-study
-pos
-preinc
-i_preinc
-predec
-i_predec
-postinc
-i_postinc
-postdec
-i_postdec
-pow
-multiply
-i_multiply
-divide
-i_divide
-modulo
-i_modulo
-repeat
-add
-i_add
-subtract
-i_subtract
-concat
-stringify
-left_shift
-right_shift
-lt
-i_lt
-gt
-i_gt
-le
-i_le
-ge
-i_ge
-eq
-i_eq
-ne
-i_ne
-ncmp
-i_ncmp
-slt
-sgt
-sle
-sge
-seq
-sne
-scmp
-bit_and
-bit_xor
-bit_or
-negate
-i_negate
-not
-complement
-atan2
-sin
-cos
-rand
-srand
-exp
-log
-sqrt
-int
-hex
-oct
-abs
-length
-substr
-vec
-index
-rindex
-sprintf
-formline
-ord
-chr
-crypt
-ucfirst
-lcfirst
-uc
-lc
-quotemeta
-rv2av
-aelemfast
-aelem
-aslice
-each
-values
-keys
-delete
-exists
-rv2hv
-helem
-hslice
-split
-join
-list
-lslice
-anonlist
-anonhash
-splice
-push
-pop
-shift
-unshift
-reverse
-grepstart
-grepwhile
-mapstart
-mapwhile
-range
-flip
-flop
-and
-or
-xor
-cond_expr
-andassign
-orassign
-method
-entersub
-leavesub
-caller
-warn
-die
-reset
-lineseq
-nextstate
-dbstate
-unstack
-enter
-leave
-scope
-enteriter
-iter
-enterloop
-leaveloop
-return
-last
-next
-redo
-goto
-close
-fileno
-tie
-untie
-dbmopen
-dbmclose
-sselect
-select
-getc
-read
-enterwrite
-leavewrite
-prtf
-print
-sysread
-syswrite
-send
-recv
-eof
-tell
-seek
-truncate
-fcntl
-ioctl
-sockpair
-bind
-connect
-listen
-accept
-shutdown
-gsockopt
-ssockopt
-getsockname
-ftrwrite
-ftsvtx
-open_dir
-readdir
-telldir
-seekdir
-rewinddir
-kill
-getppid
-getpgrp
-setpgrp
-getpriority
-setpriority
-time
-tms
-localtime
-alarm
-dofile
-entereval
-leaveeval
-entertry
-leavetry
-ghbyname
-ghbyaddr
-ghostent
-gnbyname
-gnbyaddr
-gnetent
-gpbyname
-gpbynumber
-gprotoent
-gsbyname
-gsbyport
-gservent
-shostent
-snetent
-sprotoent
-sservent
-ehostent
-enetent
-eprotoent
-eservent
-gpwnam
-gpwuid
-gpwent
-spwent
-epwent
-ggrnam
-ggrgid
-ggrent
-sgrent
-egrent