Fwd: Are Zones Global State? Do they provide a dangerous communications channel?

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view

Fwd: Are Zones Global State? Do they provide a dangerous communications channel?

Mark S. Miller-2
Are Zones Global State? Do they provide a dangerous communications channel? 

At a long meeting we had last Wednesday I gave Misko a hard time because I thought the answers were yes and yes. I normally assume that the first implies the second. In a wonderful hours long meeting, we came up with some solutions to cope with the dangers I saw (ZoneRef, ...). These changes to the API had some additional expense, but Misko and I talked ourselves into thinking the expense was affordable. Daniel Ehrenberg then separately expressed worry about this expense.

I was going to take the time today to record the outcome of that meeting. After a long conversation I just had with Dean, I no longer think that is necessary. Despite having an API that requires global state, Dean convinced me that the answers are yes and no. I am tremendously surprised. Zones does have observable global state that enables information to be communicated "by magic" in violation of normal oo rules. But Dean also convinced me that this does not add an ability to communicate to any scenario that could safely be assumed free of other communications channels. I still find this result quite bizarre, but I think I believe it.

I apologize to Misko. I now see that the big insight I got from Dean is one that Misko tried to explain to me early in our session. For whatever reason, I didn't see it till now. I will try to listen better next time.

The one change that is required is the one Misko was perfectly comfortable with -- that the naming objects used to name dynamic variables be genuine objects, not strings and not symbols. Let's say these naming objects are NameVar objects. We could use NameVars as mere tokens as in the current Zones API (which seems absent from <https://github.com/domenic/zones> btw), or we could give NameVars a .get() operation to look up the value currently bound to that dynamic variable. I return to this below.

The apparent problem I was worried about:

Zone is a global. This global has a "current" property that changes state over time. Therefore, the Zone global is not transitively immutable. However, it cannot be assigned to, only rebound. Alice and Bob have no direct contact, but instead talk only through a trusted membrane-like intermediate, Tom, that enforces some enforceable policy limiting interaction between Alice and Bob. Alice wants to communicate a bit to Bob that the trusted intermediary would wish Bob not to learn. Alice creates two zones, x and y. She invokes Bob once through the Tom in zone x once, so that Bob can "const x = Zone.current" during the call to remember zone x's identity. Then, depending on the setting of the bit, she invokes him again, still necessarily through Tom, using either x or y to indicate whether the bit is zero or one. Bob then does

if (x === Zone.current) {

to learn the bit Alice wants to communicate. This is indeed a communications channel using the mutable state of a global object. Similar apparent problems arise with the dynamic variables themselves, but we'll come back to that. This case is adequate to explain my mistake.

The observation:

Because Zone.current is unassignable, but can only be rebound in operations like run, fork, and wrap, it can only be used to communicate forward, from invoker to invokee, once we generalize the notion of invocation beyond direct function call. Bob can only see a new Zone.current when invoked by Alice. Outside of any such invocation, Alice has no magic way to communicate to Bob. In any scenario where Alice invokes Bob, even with this extended notion of invocation, we must assume that Alice can encode information in the very act of invocation. She could have not invoked. Or invoked something else. Or invoked in a different order. Once a forward invocation path from Alice to Bob is enabled, it is a fools errand to try to reason about limits of what Alice might encode on this path for Bob to read. The restriction we were worried about is actually unenforceable anyway for other reasons.

This is true for bits in the downward invocation direction, such as the outcome of Bob's "if" test, but not true for bits in the upward direction. I do not spot any upward communications dangers here, so I think we can put that to bed. 


It is also not true of capabilities. Using membranes, Tom is in a position to prevent the passing of any mutable objects that he does not wish to cross. The key here is that we can account for the interaction between Zone instances and NameVar instances by placing all the needed mutable state in the NameVar, with an encapsulated weak mapping from zone identity to the value of this variable in that zone. Usual caveat: it need not be implemented this way as long as we preserve observational equivalence. Each zone instance can then be considered a transitively immutable instance, used only to look up state in NameVars by zone identity. If we refactored the API, we could even make the zone instances be symbols with no loss of functionality.

Misko and I also talked about cross-realm problems and solutions. I think what we came up with is still valid, but will reexamine in light of these new insights

Since the Zone global is both mutable and SES-safe, it breaks with the rest of the SES document and will require a careful explanation.


es-discuss mailing list
[hidden email]