Mostrando entradas con la etiqueta sandbox. Mostrar todas las entradas
Mostrando entradas con la etiqueta sandbox. Mostrar todas las entradas

domingo, 5 de junio de 2011

Shikashi v0.5.0 released

Shikashi is a sandbox for ruby that handles all ruby method calls executed in the interpreter to allow or deny these calls depending on the receiver object, the method name, the source file from where the call was originated

For more info about the project, visit the project page

You can install the gem by doing

gem install shikashi

New Enhancements

The primary focus of this latest release was improve the performance of execution of ruby code in the sandbox but maintaining the purity of ruby (i.e. without implementing anything with C or similar)

Code packets

In the previous version of shikashi (0.4.0), to execute code in the sandbox, you do:
Shikashi::Sandbox.run("1+1", Shikashi::Privileges.allow_method(:+))
This, internally, implies:
  • Parse the code
  • Process the syntax tree (evalhook)
  • Emulate the transformed tree (partialruby)
  • Execute the emulation code using eval...
This was a great performance problem in cases where you need to execute the same piece of ruby code many times in the sandbox (e.g. sandboxed web code executed for each incoming request)
To solve this, the concept of "code packet" was implemented; a "code packet" is the ultimate product of the above mentioned processing chain ready to be executed as many times as necessary without reprocess the code and tree. Example:
packet = Shikashi::Sandbox.packet(code)
# after that, you can run the "packet" as many times as you want without doing all
# parsing, tree processing and emulation stuff internally
packet.run(privileges)
packet.run(privileges)
packet.run(privileges)
packet.run(privileges)

The performance difference is of the order of 20X, you can check by doing the following benchmark:

require "rubygems"
require "shikashi"
require "benchmark"

code = "class X
def foo(n)
end
end
X.new.foo(1000)
"

s = Shikashi::Sandbox.new

Benchmark.bm(7) do |x|

x.report("normal") {
1000.times do
s.run(code, Shikashi::Privileges.allow_method(:new))
end
}

x.report("packet") {
packet = s.packet(code, Shikashi::Privileges.allow_method(:new))
1000.times do
packet.run
end
}

end

In my laptop, the result of this benchmark is:

            user     system      total        real
normal 5.870000 0.540000 6.410000 ( 6.436331)
packet 0.290000 0.020000 0.310000 ( 0.315351)

The repeated execution of code using packets is 20 times faster than normal

Refactor of evalhook internals

Evalhook is the support gem that provides the ability to hook events on the execution of ruby code. Evalhook implemenations initially was not desgined for performance, then it's possible to refactor the implementation to increase the performance by supressing unnecessary calls and other optimizations.

require "rubygems"
require "shikashi"
require "benchmark"

s = Shikashi::Sandbox.new

class NilClass
def foo
end
end

Benchmark.bm(7) do |x|

x.report {

code = "
500000.times {
nil.foo
}
"
s.run code, Shikashi::Privileges.allow_method(:times).allow_method(:foo)
}

end



The result without the optimizations:
            user     system      total        real
36.140000 1.420000 37.560000 ( 37.672708)


The result with the optimizations:
            user     system      total        real
27.460000 1.130000 28.590000 ( 28.658031)


The difference is not so significant because most of the time is used by privileges checking in both cases. Similar bechmarks executed against evalhook directly throws greater differences

Links

jueves, 17 de marzo de 2011

Shikashi - A flexible sandbox for ruby

Shikashi is an sandbox for ruby that handles all ruby method calls executed in the interpreter to allow or deny these calls depending on the receiver object, the method name, the source file from where the call was originated

Goals of the project

Provide a sandbox API to build up scripting services with granular control of privileges even at method and global variable levels

The API

The API of Shikashi expose two main services: a "eval" method and a privilege representation. The "eval" just run code in the sandbox and apply the restrictions specified in the privileges passed as parameter. Example


require "shikashi"

sandbox = Shikashi::Sandbox.new
privileges = Shikashi::Privileges.new

privileges.allow_method :"+" # mandatory to prevent SecurityError exception

result = sandbox.run "2+2", privileges
print result,"\n" # 4



Also, the API allows more effective control of the privileges by objects/method names and is not limited to methods, but also allows to control the access to global variables and constants


# ...
privileges.allow_global:$a # mandatory to prevent SecurityError exception

sandbox.run("$a = 4", privileges)

print $a, "\n"
# ...



Current Status

Currently, there are a stable version of the gem (0.3.1), but the compatibility only is guaranteed for very few environments, exluding many of the interesting like Heroku which I have verified that the gem did not work

Future

The next improvement for shikashi (for version 0.4.0) will be of course the compatibility, defining two specific objetives:
  • Making it work in Ruby 1.9
  • Making it work in Heroku (without UI or any web programming)
In addition, secondary objectives about API usability were defined for the next release, these include sugar syntax to make it easier to use like so


Sandbox.run "2+2", Privileges.allow_method("+")


Links:
https://github.com/tario/shikashi
http://tario.github.com/shikashi/doc/