On Tue, Aug 22, 2006 at 06:02:04PM +0900, Yukihiro Matsumoto wrote:
> In message "Re: sandbox timers & block scopes"
>     on Wed, 9 Aug 2006 03:09:32 +0900, why the lucky stiff <ruby-core / whytheluckystiff.net> writes:
> 
> |1. Ruby uses setitimer to switch threads.  I would like to use setitimer as well
> |to abort a sandbox which runs longer than its timeout.  Can anyone recommend a
> |signal which can be used for this?  Or could I get access to the thread
> |switching routine so I can check sandbox timeouts between threads?  Or, perhaps
> |there is another strategy.
> 
> I think you've solved this one.

Yes, I'll be fine.  I do have a small, related question about exception handling, matz.

From rb_rescue:

  if (!rb_obj_is_kind_of(argv[0], rb_cModule)) {
      rb_raise(rb_eTypeError, "class or module required for rescue clause");
  }

There is a very nice side effect of this code.  rb_eException is derived from
rb_cModule.  And sandkit->rb_eException is derived from sandkit->rb_cModule.

So, if the standard Ruby environment raises an exception, it cannot be caught by
the sandbox.  This is very nice if users want to create their own security
models.

  # setup security
  sand = Sandbox.new
  sand_k = sand.eval("Kernel")
  def sand_k.fork
    raise Exception, "User attempted to call fork!  Closing their sandbox!"
  end

  # execute user's string
  sand_k.eval(user_input)

The trouble is that, even though the user can't rescue the exception,
they can ensure.

  def endless
    begin
      fork
    ensure
      endless
    end
  end

I wondering if rb_ensure can only recover from exceptions raised which descend
from rb_cObject.  This is somewhat complicated since the sandbox will need to
use rb_ensure to catch the exception, to swap everything out and raise again.
Once rb_cObject is swapped back in, the exception could be caught.

> You have to replace ruby_dyna_vars for in-block local variables,
> ruby_frame and ruby_block for blocks.

Ah, oh, ruby_dyna_vars.  Thankyou, I will check this out!  To avoid exposing these, I 
will take a simpler approach for now and wrap every sandbox_eval call in a method.

_why