Hi All,
For a research project at UCL Belgium I am investigating capabilities to enable secure programming in multi-paradigm languages. The Mozart implementation of the Oz language will be my main research tool. I have to decide now whether or not to build a rough emulation of the E-language mechanisms in Oz first and learn from that, or just go ahead in Oz, and concentrate on the differences with E. 1. Any advice from the subscribers on this mailinglist, regarding this decision? Any particular reasons why you'd choose for the one or the other, or why you think I should? 2. It is claimed that Promise-based concurrency is important in E for security. Do you think it's also important for capabilities in any way?
Many thanks, Fred.
(I posted this mail on both e-lang and squeak-e mailinglists)
_______________________________________ Fred Spiessens Researcher software security UCL university Louvain-la-Neuve Belgium Email: fsp@info.ucl.ac.be URL: http://www.info.ucl.ac.be/people/fsp/fred.html
[I've cross posted to users@mozart-oz.org in addition to e-lang and squeak-e.]
At 03:42 PM 6/8/2003 Sunday, Fred Spiessens wrote:
Hi All,
For a research project at UCL Belgium I am investigating capabilities to enable secure programming in multi-paradigm languages. The Mozart implementation of the Oz language will be my main research tool. I have to decide now whether or not to build a rough emulation of the E-language mechanisms in Oz first and learn from that, or just go ahead in Oz, and concentrate on the differences with E.
- Any advice from the subscribers on this mailinglist, regarding this
decision? Any particular reasons why you'd choose for the one or the other, or why you think I should?
The E *language* (libraries aside) is secure not so much from the creation of new mechanisms, as from leaving out of those non-object non-lambda non-logic mechanisms (like global variables) that break security. The common ancestor of E and Mozart, Concurrent Prolog, was already capability secure without initially even realizing it, simply by staying clean enough to not destroy the capability security inherent in their computational model. The same was almost true of Scheme -- Jonathan Rees had to do very little to Scheme to make W7. (Though the story isn't quite as dramatic, as Scheme descends from Actors, and Actors were explicitly designed to be capability secure.)
The rights amplification pattern in Mozart is too weak. This may be the one area where you should think about adding rather than subtracting primitives from Mozart. (Though, depending on your concurrency, rights amplification may not need any additional primitives.)
Any effort you spend thinking about equality primitives will be well spent. This is an area of deceptive subtlety. Equality and rights amplification are also intimately related to each other. There are many possible stances on both in addition to E's, but if you go it afresh, don't underestimate these issues.
Think hard about modules and import. I expect E will turn to Mozart for guidance here. E's module system demonstrates some essential properties, but so far I consider it a failed experiment. (From what I've seen, I think Mozart is headed in a good direction here.)
The situation with the libraries is unlikely to be so happy. Ideally, the libraries are designed from scratch according to POLA principles. The needed factoring according to distinctions of authority does not happen accidentally, even in very clean systems. If you're stuck with a large legacy of old code you can't afford to rewrite, then see http://www.erights.org/elib/legacy/ . But taming will never be as good as a rewrite according to capability principles.
So my recommendation is, on the language design front, start with Oz, making it capability secure by removing all questionable primitives. For example, is Mozart serialization written in Mozart, or is it primitive? If it's written in Mozart, does it use any questionable primitives? Could it be written in Mozart without use of any questionable primitives? If not why not? (Btw, it would be useful to me for the paper I'm writing to know the answers to these particular questions.)
Make a list of *all* primitives. Those that can be rewritten with full equivalence purely in Mozart are effectively not primitive -- if you're right about this equivalence, then they're just optimizations. Of those that remain, any one may blow your security. Think hard about each, and remove all that you can.
On the libraries, whether you're building from scratch or taming, study the E or Waterken libraries first and emulate the lessons found there. (E and Waterken are the only extensive object-language-oriented libraries I know of designed from the ground up according to capability principles.) In the end, you will spend much more work on secure library design than secure language design.
- It is claimed that Promise-based concurrency is important in E for
security. Do you think it's also important for capabilities in any way?
"A language for writing secure programs must first of all be a language for writing reliable programs." From http://lists.squeakfoundation.org/pipermail/squeak-e/2003-February/000017.ht...
See also http://www.eros-os.org/pipermail/e-lang/2003-February/008502.html
Btw, Mozart also has promise-based concurrency -- Mozart's logic variables and E's promises both descend from Concurrent Prolog's logic variables. I suspect the difference is that E maintains Concurrent Prolog's (and Actors) event-loop orientation whereas, if I understand, Mozart abandoned it.
E's contribution to concurrency (due to E's original creator, Doug Barnes) was to reconcile the promise + event loop orientation of the Concurrent Prolog and Actor traditions with sequential programming in the imperative tradition. No previous language I'm aware of in the promise + event loop style had a sequential-imperative programming sublanguage.
---------------------------------------- Text by me above is hereby placed in the public domain
Cheers, --MarkM
Many thanks, Mark, for this elaborate answer and advice! Not everything you mention is clear to me at this stage, but I'll work it out in due time, and come back to it. Fred.
On Monday, June 9, 2003, at 01:43 AM, Mark S. Miller wrote:
[I've cross posted to users@mozart-oz.org in addition to e-lang and squeak-e.]
OK. I'll cross post this answer too, but I'm not sure this is appreciated by the people who subscribed to all 3 mailing lists. (?)
At 03:42 PM 6/8/2003 Sunday, Fred Spiessens wrote:
Hi All,
For a research project at UCL Belgium I am investigating capabilities to enable secure programming in multi-paradigm languages. The Mozart implementation of the Oz language will be my main research tool. I have to decide now whether or not to build a rough emulation of the E-language mechanisms in Oz first and learn from that, or just go ahead in Oz, and concentrate on the differences with E.
- Any advice from the subscribers on this mailing-list, regarding
this decision? Any particular reasons why you'd choose for the one or the other, or why you think I should?
The E *language* (libraries aside) is secure not so much from the creation of new mechanisms, as from leaving out of those non-object non-lambda non-logic mechanisms (like global variables) that break security. The common ancestor of E and Mozart, Concurrent Prolog, was already capability secure without initially even realizing it, simply by staying clean enough to not destroy the capability security inherent in their computational model. The same was almost true of Scheme -- Jonathan Rees had to do very little to Scheme to make W7. (Though the story isn't quite as dramatic, as Scheme descends from Actors, and Actors were explicitly designed to be capability secure.)
The rights amplification pattern in Mozart is too weak. This may be the one area where you should think about adding rather than subtracting primitives from Mozart. (Though, depending on your concurrency, rights amplification may not need any additional primitives.)
I'll come back on this later, when I can say something relevant here.
Any effort you spend thinking about equality primitives will be well spent. This is an area of deceptive subtlety. Equality and rights amplification are also intimately related to each other. There are many possible stances on both in addition to E's, but if you go it afresh, don't underestimate these issues.
I take this advise very serious. I ran into a problem already when trying to implement a GrantMatcher as described in http://www.erights.org/elib/equality/grant-matcher/index.html Oz-objects and Oz-procedures in general, are no good for this, since they can always be "deceiving transparent forwarders" (due resp. to the powerful "otherwise" method all objects can implement, and the higher order programming in Oz). But (I currently think) I can gently solve the problem with a non-OO construct: "Chunk" (a very secure Oz "data-type" that doesn't need procedure-application or message-sending to access it's internals) and the use of unforgable "Names". I am somewhat counting on it, that this kind of escape-route into the multi-paradigm approach will often make it easier to overcome the problems that you foresee.
Think hard about modules and import. I expect E will turn to Mozart for guidance here. E's module system demonstrates some essential properties, but so far I consider it a failed experiment. (From what I've seen, I think Mozart is headed in a good direction here.)
I'm only beginning to understand the huge possibilities Oz provides by making modules and module-specifications(functors) first class citizens. I count on this to make it easy to provide very good mechanisms for run-time and compile-time confinement-checkers (e.g. sandboxes, auditors, ...).
The situation with the libraries is unlikely to be so happy. Ideally, the libraries are designed from scratch according to POLA principles. The needed factoring according to distinctions of authority does not happen accidentally, even in very clean systems. If you're stuck with a large legacy of old code you can't afford to rewrite, then see http://www.erights.org/elib/legacy/ . But taming will never be as good as a rewrite according to capability principles.
I'll check this out. My answer to your next remark might apply here also.
So my recommendation is, on the language design front, start with Oz, making it capability secure by removing all questionable primitives. For example, is Mozart serialization written in Mozart, or is it primitive? If it's written in Mozart, does it use any questionable primitives? Could it be written in Mozart without use of any questionable primitives? If not why not? (Btw, it would be useful to me for the paper I'm writing to know the answers to these particular questions.)
Mozart-seniors, please correct me here, because I'm sure I will have some details wrong!!! (I hope it's only the details)
To my current knowledge serialization can be done using the functionality provided by specific system modules (either "Connection" or "Pickle" or both). System modules are currently automatically available when working in the OPI. (so no POLA at this level)
This is how I would see confinement of the serialization capability: *) A module has to explicitly import a system module to be able to use it (some exceptions might apply here, I have to look into them.).
*) Since the creation of modules from functors is done by a ModuleManager,(a first-class object in Oz), you can control (both at link-time and at load-time) what imports you allow into what modules, by providing an adapted ModuleManager for this task.
That way you can provide for sandboxing, code signature checking, etc. (Hopefully Keykos Factories also, but I have to look into sensory keys first)
I expect this is not enough in general? Why not? Is what I'm trying to do "taming" in your opinion?
Make a list of *all* primitives. Those that can be rewritten with full equivalence purely in Mozart are effectively not primitive -- if you're right about this equivalence, then they're just optimizations. Of those that remain, any one may blow your security. Think hard about each, and remove all that you can.
I was more thinking of looking for ways to disable the use of these "primitives" in untrusted (imported) modules. Am I wrong in pursuing this?
On the libraries, whether you're building from scratch or taming, study the E or Waterken libraries first and emulate the lessons found there. (E and Waterken are the only extensive object-language-oriented libraries I know of designed from the ground up according to capability principles.) In the end, you will spend much more work on secure library design than secure language design.
Thanks again for the references. I'll check them out very thoroughly
- It is claimed that Promise-based concurrency is important in E for
security. Do you think it's also important for capabilities in any way?
"A language for writing secure programs must first of all be a language for writing reliable programs." From http://lists.squeakfoundation.org/pipermail/squeak-e/2003-February/ 000017.html
See also http://www.eros-os.org/pipermail/e-lang/2003-February/008502.html
Thanks, I'l check these out.
Btw, Mozart also has promise-based concurrency -- Mozart's logic variables and E's promises both descend from Concurrent Prolog's logic variables. I suspect the difference is that E maintains Concurrent Prolog's (and Actors) event-loop orientation whereas, if I understand, Mozart abandoned it.
Yes, Mozart has threads, and their use is encouraged by the ease of dataflow synchronization, the availability of thread-reentrant locks, and the fact that threads come very cheap (you can have millions). I know the E-guys don't care for this too much :-)
I agree that the avoidance of deadlocks and the traceability of TOCTOU errors is contributing to reliability and thus to security.
In Oz we don't want to give up threads for this however, we like to think we can have our cake and eat it by promoting the use of "declarative concurrency" where possible. (the "mostly functional" style, you call it I think). We think that a good use of the necessary stateful concepts in a program can/should be "encapsulated" somehow in this declarative behaviour - whenever possible - , leading to "unobservable indeterminism": you may use state internally but at a higher (coarser) level your program remains deterministic (again, when possible). All variables in Oz are logic variables, and the stateful concepts are very explicit: Cells, Ports, Locks and Objects (did I forget some?)
E's contribution to concurrency (due to E's original creator, Doug Barnes) was to reconcile the promise + event loop orientation of the Concurrent Prolog and Actor traditions with sequential programming in the imperative tradition. No previous language I'm aware of in the promise + event loop style had a sequential-imperative programming sublanguage.
Well, I confess I think of it as a very interesting combination too.
Can I conclude that your answer to my second question is "no, but..."?
Thanks again. _______________________________________ Fred Spiessens Researcher software security UCL university Louvain-la-Neuve Belgium
Email: fsp@info.ucl.ac.be URL: http://www.info.ucl.ac.be/people/fsp/fred.html
squeak-e@lists.squeakfoundation.org