REBOL3 tracker
  0.9.12 beta
Ticket #0001998 User: anonymous

Project:



rss
TypeBug Statusbuilt Date16-Mar-2013 05:07
Versionalpha 80 CategoryMezzanine Submitted byBrianH
PlatformAll Severityminor Prioritynormal

Summary Private modules should take precedence over public modules
Description Since the alpha 80 version of the module system, when private modules were first introduced as a sensible meaning for what unnamed modules should mean (in alpha 108 they were more integrated), the normal import of words from lib (it was system/contexts/system back then) was given precedence over the import of private modules. I've come to realize that this is the wrong approach.

The default import from lib happens automatically. The default export to lib happens automatically too (if the module has a name). Named non-private modules are considered the default type of module, and are even called "regular modules".

Under "normal" circumstances (meaning: your module has a name) you have to explicitly specify a private option to have your module be considered to be private. You don't even import private modules at all unless you ask for each of them explicitly with your Needs header or IMPORT, even if they are already loaded.

That means that when you import a private module, you have specifically said that you want to do this. If you didn't want it, you would have just said nothing. That is a much stronger statement than just taking the default imports without saying anything about it at all. Clearly, your explicit intentions should be given precedence.

On a practical note, this will also make private modules more useful. This makes it very easy to explicitly request a whole set of overrides that will only apply to you and any others that explicitly requested it. This makes it possible to make a module that replaces core functions on a local level without affecting everyone, making it much easier to mix code from different sources without as many conflicts. You can even implement local compatibility modes, to a certain extent.

Overall it makes for a cleaner model to have private modules take precedence over the default imports.
Example code

			

Assigned ton/a Fixed inr3 master Last Update17-Feb-2014 22:01


Comments
(0003789)
abolka
7-Apr-2013 01:47

I strongly agree and consider this change an absolute necessity.

Repeating what Brian already stated: importing a named private module expresses the explicit intent that _this_ module's exported words should be imported, which means they must take precedence over the default imports (from lib).
(0003790)
adrians
7-Apr-2013 01:59

Me too - this just seems the logical approach. Can you remind me, though, how words referencing 'secured' (by external entity which asks for credentials and is not the deployer of the application) resource can be protected from being overwritten by those imported from private modules? Is the security concept totally orthogonal to this kind of modularity change?
(0003791)
BrianH
7-Apr-2013 02:45

Precedence isn't really overwriting. If a private module takes precedence over lib, that means that the word your script sees is derived from the private module rather than from the runtime library.

For "regular" modules (regular = non-isolated when it comes to import), the exports of all private modules you ask for are all imported into an object that is like a private runtime library, just for your module. Then your module's code is bound to that object just like it is to lib. This proposal would have your module's code be bound to that object after it is bound to lib, which makes those bindings take precedence (they are currently bount to the object before lib, which makes lib take precedence). The code would still be bound to the module's context itself afterwards, making the module's own words take precedence over both.

For isolated modules (and scripts, which sort of share the same isolated context for all scripts run by the same task) all of the words in the module's code are added to the isolated context ahead of time, before any values are added. Then that context is filled in by values from lib and that private runtime library object. Values are only filled into words that aren't unset, so later stuff doesn't overwrite words set earlier unless you do so yourself with assignment statements. This proposal would have the private runtime library set those words first, then lib afterwards, which would make the values from private modules take precedence over those from lib.

As for your security issue, R3 doesn't have anything like that. However, what you ask is probably not even possible in theory. We can protect resources from being written to at all (with PROTECT), and prevent words from being bound to particular contexts (with PROTECT/hide), but there is really no such thing as privileged code in Rebol. The closest thing we have to privileged code is code that has access to certain data (usually words in certain contexts). We can restrict access to contexts by not letting them leak, and we to certain words by blocking binding going forward, but there isn't really any way in our semantic model to do privileged code.

The closest thing we can do is disallow functions from being called unless an unforgeable token is provided as a parameter somehow. One standard way to make such a token is to have it be a word bound to a context that isn't publically available. Across machines though, you'll just have to use something cryptographic.

But, nonetheless, exporting a word from a module is not something that can be restricted to code that is more privileged than other code. The only privilege is whether a module will be loaded at all, and what environmental situation it sees when it is loaded.
(0003793)
BrianH
7-Apr-2013 02:56

If you want to do privileged code in something like Rebol, the only real way to do this is with a sandbox. You make a safe subset of Rebol in a context, then bind the relatively untrusted code to that context before you run it, and don't give it any access to stuff you don't want to give it access to. Barring security holes, they shouldn't be able to break out of the sandbox without resorting to native code (which is why you shouldn't let them use untrusted native code in the sandbox either).

There are ways that the underlying OS could make an even better sandbox, blocking even native code, but that is another issue :)
(0003795)
BrianH
7-Apr-2013 04:05

Pull request here: https://github.com/rebol/r3/pull/114
(0003797)
BrianH
7-Apr-2013 04:45

Note that this problem doesn't affect script imports, because the shared isolated context that scripts run in is a really weird thing.

For a given script A, which followed a set of previously run scripts A-, the Needs header or IMPORT function will act like this:
- It resolves imports in order, one module at a time.
- Regular module import affects lib in order the way you'd expect.
- After each module is imported, it will export from that module to the user context.
- If the module is private, all words exported from the module are added to the user context and imported directly.
- If the module is regular, only words that were defined in A- will be imported at this time.
- After all of the imports are done, it then adds any new words in A that weren't in A- or exported from the private modules to the user context, and fills them in from lib.

This has the effect of making private module exports have priority for new words, but have in-order precedence for any old words that haven't been set yet. There's really no way around this that I can see, since the user context is built incrementally with every script run. In practice it ends up as private-module-precedence most of the time.

Date User Field Action Change
17-Feb-2014 22:01 BrianH Fixedin Modified => r3 master
17-Feb-2014 22:01 BrianH Status Modified pending => built
7-Apr-2013 04:45 BrianH Comment : 0003797 Added -
7-Apr-2013 04:05 BrianH Status Modified submitted => pending
7-Apr-2013 04:05 BrianH Comment : 0003795 Added -
7-Apr-2013 02:56 BrianH Comment : 0003793 Added -
7-Apr-2013 02:45 BrianH Comment : 0003792 Removed -
7-Apr-2013 02:45 BrianH Comment : 0003791 Added -
7-Apr-2013 02:45 BrianH Comment : 0003792 Added -
7-Apr-2013 01:59 adrians Comment : 0003790 Added -
7-Apr-2013 01:53 abolka Comment : 0003789 Modified -
7-Apr-2013 01:47 abolka Comment : 0003789 Added -
16-Mar-2013 05:15 BrianH Description Modified -
16-Mar-2013 05:07 BrianH Ticket Added -