hoodwink.d enhanced


Sandbox's Init and Import #

by why in inspect

mfp: This makes me think that the point of sandbox is not as much allowing access to stuff you cannot use with higher $SAFE levels as offering a clean environment. Am I right? In both cases, being able to specify which stuff is to be imported could be useful.

Starting with an example:

 box = Sandbox.new(:init => [:load], :import => [:YAML, :File])
 box.eval("require 'rubygems'")

This is conceptual, it doesn’t yet work all the way. The init option loads a portion of Ruby’s core into the sandbox. It doesn’t actually load a shared lib or anything. It just allows access to some C methods (or hacked versions of them) built into the Sandbox extension.

So :init => [:load] is kind of like when Init_load from eval.c gets call. That call gives you load and require and $LOADED_FEATURES and the like. There should only be five or so of these init modules. From there you can remove_method anything you don’t want around.

The :import will copy classes from the main Ruby interpreter into the Sandbox. This is a deep copy which will recursively import modules, classes, singleton classes and methods until we hit Object or anything the sandbox already has. Oh and then instance variables get marshalled. I gotta remember to do that.

I wouldn’t recommend this approach for restricted sandboxes and I will probably disable it for the most restrictive subclass. In those cases you’ll want to just pass in a string to be eval’d. That gives only one object reference as a hook to the outside and it’s trapped in C.

said on 25 Jul 2006 at 21:14

Cool, we can do namespace tricks without losing our libs. BTW , can I pass blocks to eval?

said on 25 Jul 2006 at 21:17

No. I’m not sure if that will work yet. I think it will try to use the SCOPE struct created when the block is parsed.

said on 26 Jul 2006 at 11:44

Hmm. So what if I just want to import a sub-hierarchy? Like, just GreatMouse::Detective rather than all of GreatMouse?

said on 26 Jul 2006 at 12:40

This sounds more and more like the best route for doing a sensible class browser and “intellisense” for Ruby. I know its scoffed on by most, but for anyone who has programmed with intellisense, its hard to give up. But the only way to really know what methods are avaiable to a given object at any time in Ruby is to run the code.

Sandbox + some traps to ensure files aren’t written, sockets aren’t opened, etc. sounds like the perfect way to run some code, inspect it for methods, and provide those resuults to a class browser/intellisense engine.

said on 26 Jul 2006 at 15:57

MenTaLguY: If you want to do that, then I’ll probably have like an :import_only option for that.

Justin: I’m not sure how you’d keep the sandbox current with what you’re typing, but I hope that’ll one day be the case.

said on 27 Jul 2006 at 10:42

Hmm, okay, so you can do e.g. :import_only => ["GreatMouse::Detective"], but then what’s the difference between :import_only => ["YAML"] and :import => ["YAML"]?

Additionally, I think the ability to import to a different place in the Sandbox would be keen. For example, being able to introduce MyApp::Sandboxed::Spleen to Mr. Snadbox as MyApp::Spleen.

said on 27 Jul 2006 at 10:43

Ah, maybe :import_only doesn’t recursively import child modules? Although that wasn’t what I had in mind, it does sound useful.

said on 27 Jul 2006 at 12:01

Actually, there are two directions to the recursion, MenTaL. The ancestry of the class and the containers of the class. See, if I import GreatMouse::Detective and assume GreatMouse is a module, things’ll get all messed up if the real GreatMouse ever happens to come along and it turns out to be a subclassed OpenStruct or something.

But what I may do is have the new GreatMouse descend from some kind of TemporaryModule. Then when the real GreatMouse finally arrives, swap in the correct class and everything. Yeah, that will probably be sufficient.

11 Jul 2010 at 21:33

* do fancy stuff in your comment.