diotalevi has asked for the wisdom of the Perl Monks concerning the following question:

I'm sort of stewing some ideas how to locally lock down sections of a program so that a restricted section isn't able to see or modify things it hasn't already been given access to. An idea is to start using B::Util to look for specifically disallowed constructions like unpack "p", pack 'p', "foo". One of the immediate problems is how do the same auditing for BEGIN blocks in the about-to-be-called code. AFAIK there's no way to run this sort of code on a BEGIN block to audit it. Ideas?

This spot of code (blatantly unfinished with all sorts of holes) checks pack's first argument for 'P' or 'p' if the argument is a constant. This could be beefed up but not just now.

BEGIN { use B::Utils qw(opgrep walkallops_filtered); walkallops_filtered ( # Search for pack() with a constant first arg sub { opgrep( { name => 'pack', first => { name => 'const' } } ) }, sub { my $pack = shift; my $const = $pack->first; # Disallow p and P if ($const->pv =~ m/p/i) { die "Format p or P was used in pack" } } ); }

Fun Fun Fun in the Fluffy Chair

Replies are listed 'Best First'.
Re: Auditing BEGIN blocks?
by PodMaster (Abbot) on Dec 18, 2002 at 16:24 UTC
    Check out PPI, it's apparently a framework for parsing perl (eek! i haven't reviewed it yet).

    I know people always say, don't parse perl, but in this case, it wouldn't be so bad. Since a BEGIN block can only look like sub BEGIN {} or BEGIN{}, i suggest you programatically change the BEGIN block to something like IwannaBEGINevil. Off the top of my head something like s/\bBEGIN\b/IwannaBEGINevil/ will do (no real thought put into the regex).

    Then you can audit that sub like you would any other user defined sub (if you can do that).

    Oy!


    MJD says you can't just make shit up and expect the computer to know what you mean, retardo!
    ** The Third rule of perl club is a statement of fact: pod is sexy.

      Since a BEGIN block can only look like sub BEGIN {} or BEGIN{}
      or use .... And there are many things that look like the two things you gave, and are not BEGIN blocks.

      Yes, it's a difficult problem.

      -- Randal L. Schwartz, Perl hacker
      Be sure to read my standard disclaimer if this is a reply.

      If that is the only way to get there then that just means perl5 isn't powerful enough for what I'm asking it to do. I refuse to parse perl. I'll bet on perl6 ;-)


      Fun Fun Fun in the Fluffy Chair

Re: Auditing BEGIN blocks?
by John M. Dlugosz (Monsignor) on Dec 18, 2002 at 17:06 UTC
    Check out the Safe module. I think there is another one similar to that, but I can't remember the name. Also see if tainting will do what you need.

    —John

      [An Ode to the Granovetter Diagram is a nice intro to the concepts I'm dealing with]

      Unfortunately no, that wouldn't work. I haven't fully explained why I'd like to audit perl code so your suggestion is reasonable given the supplied information. I've been spending time learning about Capability system and this is something that would be really useful for that sort of thing.

      While I'm not aware of all the term's connotations and requirements the general idea is to end with something with properties like a Trusted Computing Base. This might mean that a set of objects exist in a context where arbitrary perl code is restricted. The specific example I mentioned in the original question isn't even properly testable using current perl technology. For example - I'd have to disallow use of unpack/pack with use of my() and global variables as patterns since those can introduce pP. That's a finer distinction than simply disallowing all use of pack/unpack. Even better would be to allow full use of pack/unpack but just turn off it's memory reading abilities. And this is just one example - there are plenty of other interesting constructs that would need to be pruned away.

      It might be possible to use Safe if the object set's source code was continually compiled on each object invocation but you can see how that's really suboptimal. The only reasonable solution for current perl5 technology would be to split the program into separate process spaces (fork/threads/whatever) and do IPC to get object computation. Perhaps POE or something that can manage the details of IPC. But only provides one perl section protection from another - there's no internal protection without using Safe's cudgel, PPI's wobbly blade or my approach's unlocked gate. If there was a reliable way to audit a complete opcode tree then I'd be getting somewhere. Going farther it'd be good to insert assertions into the tree so then things that can only be known at runtime can be tested then.

      Anyhow, thanks for the advice. I'll just hope perl6 is powerful enough to make some real magic happen. ;-)


      Fun Fun Fun in the Fluffy Chair

        It seems to me that using a raw pointer in pack/unpack is something that taint-checking should catch. That oversight should be trivially corrected by someone with patching experience. Well, making it check the pattern argument for taint-ness up front would be trivial, but would prevent pack/unpack from working at all with user-supplied patterns (probably a good idea). Having it note the tainted string and respecting only a subset of the commands would be more difficult. Ideally, the behavior would be controlled in a manner similar to the "re" pragma for a similar issue regex's.

        I think the taint concept in Perl fits nicely with the concepts you are studying. Perhaps you can contribute some meditations for Perl 6 design and Perl 5 fixes (like this) as a product of your studies. That is, tainting seems the existing tool for this concept, how can it be improved or augmented to handle modern understanding of these concepts?

        —John