From: why the lucky stiff Date: 2006-08-23T01:56:15+09:00 Subject: Re: sandbox timers & block scopes 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 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