Thanks to some great replies to my last thread on this subject A perl sandbox?, I have been able to make some progress.

I have implemented a basic sandbox that will allow 100% of perl's syntax and 95% of the opcodes in what so far I have found to be a foolproof environment (no guarantees!).

The sandbox is broken up into two components:
First is the wrapper code. This basically fires off a separate perl interpreter to set up the Safe environmet and execute the required code. It then attempts to read up to 254 characters (in my case) back from this process before closing the file handle. If these steps cant be completed in under a second the alarm is fired, the process killed, and the filehandle closed.

I came to the conclusion that spawning the seperate interpreter was the simplest way to ensure that any memory used was quickly retuned to the OS. I'm not particularly worried about any CPU spikes for less than a second.

(I havent used the readmore tag before, I hope it worked. yes? good...)

#!/usr/bin/perl use strict; my $data; my $pid = open F, "perl -|"; eval { local $SIG{ALRM} = sub { kill 9, $pid; close F; $data .= " Exceeded CPU Time"; die; }; alarm(1); read (F,$data,254); close F; alarm(0); }; print $data;
My only problem with the wrapper code is that it does not allow data to be recalled from the process if less than 254 bytes of data were printed before the process hits one second of cpu time (to make that more clear, this is in the event that it does reach one second). Which means print "hello"; {redo} will return " Exceeded CPU Time" rather than "Hello Exceeded CPU Time". But right now I am not too worried about that.

Next is the actual script that maintains the Safe environment. I have gone through the list of opcodes and basically removed what *I* thought were not necessary, things like backticks, system, socket, etc... at present require is also not included.

This code simply sets up the environment, do(es) a file of perl source and then prints any errors before terminating (simple!).
(Sorry for the length of this)

#!/usr/bin/perl use strict; use Safe; my $cp = new Safe; $cp->permit_only(qw( 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 regcreset regcomp match qr 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 unpack pack split join list lslice anonlist anonhash splice push pop shift unshift sort 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 dump goto exit umask binmode tie untie tied sselect select getc read enterwrite leavewrite prtf print time tms localtime gmtime sleep entereval leaveeval entertry leavetry)); $cp->rdo("/tmp/"); print $@ if $@;

I would really appreciate it if some of you might spare some time to look over this list, just to check that I havent included anything I shouldnt have. I have basically been through each opcode one at a time, checking in perldoc if I was unsure what they were used for. I am fairly confident that my list is correct.

Critical system compromising code?

- nashdj