[e-lang] Unsafe code in capability languages
David Hopwood
david.nospam.hopwood at blueyonder.co.uk
Tue Aug 29 15:41:15 CDT 2006
Constantine Plotnikov wrote:
> I want suggest a minor improvement to way how unsafe code is invoked in
> E (possibly it can be implemented in Emily too). As I understand,
> currently the whether code is considered to be able to invoke unsafe
> operations is determined by in which file it is defined. This looks
> somewhat unnatural for me, and it is somewhat unfriendly to runtime code
> generation and mobile code.
>
> I suggest making execution of privileged code more capability-like. To
> achieve this, I suggest adopting the C# "unsafe" statement with a small
> twist. I believe that my proposal allows eliminating special classes of
> source files from E.
>
> There is an object in E runtime named unsafeKey. The object is stored in
> VM's unsafeKey register. The object is considered to be mutable and thus
> it cannot be assigned to constant.
>
> The object is passed as first argument of main function. The main
> function can pass unsafeKey to services that need to invoke unsafe
> functionality. The classes that need to invoke unsafe functionality do
> it in the following way:
>
> unsafe(<unsafe key>) {
> // operations
> }
>
> Unsafe operators are allowed only in lexical scope of unsafe operation.
> The open issue is whether to allow unsafe operations in closures within
> the lexical scope (I'm leaning against it, but possibly it is perfectly
> safe; however analysis is required here). The body is executed only if
> object passed as unsafe key to unsafe statement is identical to value
> stored in unsafe register of virtual machine, otherwise an exception is
> thrown and body is not executed.
>
> Below is a HelloWorld program that demonstrate unsafe statement
>
> # application entry point
> def HelloWorld(unsafeKey, args) : any {
> def stdout := makeStdout(unsafeKey)
Nitpick: E doesn't allow undeclared forward references. Use 'def makeStdout'
before the first reference, then 'bind'.
> stdout.println("Hello, World!")
> }
>
> # stdout service
> def makeStdout(unsafeKey) : any {
> def stdout := unsafe(unsafeKey) {
> <unsafe:java.lang.System>.getOut()
> }
> return object {
> to println(text:string) {
> unsafe(unsafeKey) {
> # assuming that println is untamed
> stdout.println(text);
> }
There's no reason to mark the 'println' as unsafe at all. It's sufficient that
the import of 'java.lang.System' is unsafe, and that the imported module is
only passed to code that can be trusted with it (like any other capability).
To make this example less trivial, I'll assume below that we want to prefix
all output with "HelloWorld: " (otherwise we could just pass
java.lang.System.getOut() directly).
> }
> }
> }
Kevin Reid has already pointed out that E's <unsafe> URI getter is
the equivalent of your 'unsafeKey' -- except that it is only needed when
importing unsafe modules, not when using them. But the example should
probably be written something like this instead (tested code, for a change):
----
#!/usr/bin/env rune
def helloWorld
def javaStdout := <unsafe:java.lang.System>.getOut()
def stdout {
to println(text :String) :void {
# gack, PrintStream.println is overloaded
E.call(javaStdout, "println(String)", ["HelloWorld: " + text])
}
}
helloWorld(stdout)
# In a real app, the above code would be the "powerbox", and the main program
# below would be in a different module.
bind helloWorld(stdout) :void {
stdout.println("Hello, World!")
}
----
Nevertheless, I think that some of the conventions currently used by E
make this issue unnecessarily difficult to understand for newcomers:
- The most obvious file suffix, ".e", is used for powerbox code, which we
expect to be the least common kind of E code.
- <unsafe> is in scope for the whole of a .e file (not because it is
a .e file; only because it was launched in a privileged environment).
So in the above example, the 'helloWorld' function *could* have
referred to <unsafe>, or other stuff that would not be in a safe scope.
For a larger application this wouldn't matter: we would put most of
the code into .emaker files where <unsafe> would not be in scope.
But this makes it difficult to show the security benefits of POLA in
small examples, because they need at least two source files.
- Is there a convention for how to launch E scripts from a secure shell
like plash, or from CapDesk? If there is, it's not at all well documented.
--
David Hopwood <david.nospam.hopwood at blueyonder.co.uk>
More information about the e-lang
mailing list