The argument against introducing non-determinism (or GC-dependent determinism) 
from maybe a month ago seems much stronger than that of covert channels. A 
claim of a reasonable implementation of a production language to be free of 
covert channel is rather suspect. E.g., preventing covert communication through 
cache hierarchy properties (warm vs cold, full or not, ...) is no fun. 

Mark's example is strong in that it (arguably) attacks realistic benign code to 
steal a secret; it doesn't just achieve communication between two malicious 
codes. However, the existence of GC -- irrespective of weak maps -- already 
allows a similar attack pretty quickly when even rather restricted forms of 
mutable state are shared. This suggests that such channels are only feasibly 
prevented by non-extreme-experts or in heavily restricted scenarios similar to 
message passing isolated processes (frames, workers, ...) at which point 
skipping a typical+useful feature because of this point this particular use 
case loses significant steam. As weak maps seem to be a capability that can be 
disabled, this desired notion of language-level security be encapsulated as a 
library, further weakening the argument. This latter perspective might actually 
be a useful perspective for future controversial proposals given the variety of 
desirable security models, analyses, etc. I could be wrong on the impact here 
and would welcome reasoning on that!

That said, going back to the beginning: deterministic GC-independent semantics 
are a Good Thing. Whether this matters seems to be a crucial discussion. Is 
there a concern for basic correctness for more mundane code? Are those use 
cases similar to the above where a 'strictness' library suffices? Again, I'd 
point to the ActionScript experience for a reference: can anybody attack or 
break a flash program with weak maps, or is this FUD? I'm more concerned about 
the dangers of misuse in terms of memory leaks and event-oriented logic 
glitches between code running on different ES implementations (and suspect the 
answer has a reasonable chance of being 'yes' for these).

Regards,

- Leo



On Sep 1, 2010, at 12:00 PM, [email protected] wrote:

> Send es-discuss mailing list submissions to
>       [email protected]
> 
> To subscribe or unsubscribe via the World Wide Web, visit
>       https://mail.mozilla.org/listinfo/es-discuss
> or, via email, send a message with subject or body 'help' to
>       [email protected]
> 
> You can reach the person managing the list at
>       [email protected]
> 
> When replying, please edit your Subject line so it is more specific
> than "Re: Contents of es-discuss digest..."
> Today's Topics:
> 
>   1. Re: WeakMap API questions? (Mark S. Miller)
> 
> From: "Mark S. Miller" <[email protected]>
> Date: August 31, 2010 9:32:23 PM PDT
> To: Brendan Eich <[email protected]>, Bradley Meck 
> <[email protected]>, [email protected]
> Subject: Re: WeakMap API questions?
> 
> 
> On Thu, Aug 26, 2010 at 9:03 PM, Brendan Eich <[email protected]> wrote:
> On Aug 26, 2010, at 8:19 PM, Bradley Meck wrote:
> 
>> I am not sure that would make it a regular map. Having the keys available 
>> does not ensure that the keys will not be collected.
> 
> That's the crux of the matter. Mark Miller should weigh in, since he has 
> argued this point in the past with some good arguments.
> 
> The issue is that enumeration or even a weakmap.length property would convey 
> what has been collected as garbage, and what has not yet been collected even 
> though weakly referenced by a map entry. There could be strong refs 
> elsewhere, or the GC might just not have gotten around to collecting the 
> still-enumerated or counted-by-length entry.
> 
> This makes a covert channel from the implementation's garbage collector, and 
> it can be abused. The GC schedule may be deterministic, so as I understand it 
> the issue is not non-determinism (or it's more than ND vs. D -- it's really 
> the ability of attackers to tell what the GC considers live still).
> 
> Thanks Brendan, that's an elegant summary. To make the covert channel problem 
> here more concrete for those interested, here's an example:
> 
> Say a.js wishes to mashup two libraries, b.js and c.js, and to keep them 
> isolated. Using our new SES prototype 
> <https://mail.mozilla.org/pipermail/es-discuss/2010-August/011684.html> to 
> make this concrete,
> 
> a.js:
> -----------------
>   // cajaVM.protect freezes its argument and all data transitively 
> reflectively 
>   // reachable from that argument. For the simple json data resulting from a  
>   // one-arg JSON.parse, the result is transitively immutable, as so is safe
>   // to share among isolated components such as b.js and c.js
>   var immutableData = cajaVM.protect(JSON.parse(dataFromSomewhere));
> 
>   var bSrc = //... Text of b.js
>   var cSrc = //... Text of c.js
> 
>   // For simplicity, let secretBits by a frozen array of 0s and 1s. Let's say 
> that immutableData
>   // happens to be a pair of arrays of unique objects, just as long. 
>   // Since b and c are isolated, it's ok to give b the secrets because b 
> can't communicate.
>   // And it is ok to give c the ability to communicate, since it doesn't know 
> the secret.
> 
>   var b = eval(bSrc)(immutableData, secretBits);
>   var c = eval(cSrc)(immutableData, internetAccess, setInterval);
> 
>   // ... for whatever reason, a happens to retain both b and c. 
> 
> 
> b.js
> ----------------------
>   (function(data, secretBits) {
>     return secretBits.map(function(bit, i) {
>       return immutableData[bit][i];
>     });
>   });
> 
> 
> c.js
> -------------------
>   (function(data, internetAccess, setInterval) {
>     var len = data.length;
>     var wm = WeakMapWithEnumerableKeys();
>     for (var i = 0; i < len; i++) {
>       for (var bit = 0; bit < 2; bit++) {
>         wm.set(data[bit][i], {bit:bit, i:i});
>       }
>     }
>   
>     function poll() {
>       var clues = [];
>       var keys = wm.getKeys(); // only those not yet collected
>       for (var j = 0; j < keys.length; j++) {
>         var v = wm.get(keys[j]);
>         clues[v.i] = (clues[v.i] || 0) | (1 << v.bit);
>       }
>       internetAccess(clues); // 1 ==> 0, 2 ==> 1, 3 ==> don't know
>     }
>     setInterval(poll, 10000);
>   });
> 
> 
> Note that the "security critical code", a.js, did everything right. By the 
> normal reasoning we use to think about object computation, b.js and c.js are 
> indeed isolated, in the sense that there is no vert communications possible 
> between them. With WeakMaps as currently specified, gc is unobservable and 
> c.js evil job is harder. With the addition of a getKeys() operation, c.js 
> could observe which shared immutable objects b.js has dropped. 
> 
> The example above is of a covert channel, in the sense that b.js *intends* to 
> send a signal that c.js can read. When b.js does not intend to signal, we 
> have a side channel rather than a covert channel. Preventing a covert channel 
> is generally much harder than preventing a side channel, so one might argue 
> that the addition of this covert channel doesn't matter much. 
> 
> But JavaScript currently doesn't have any side channels as juicy as this one. 
> If b.js is not intending to signal to c.js, but rather is just innocently 
> doing some internal data-dependent algorithmic task, how much can c.js 
> ascertain about b.js's internals by seeing which shared immutable objects get 
> dropped? Securing JavaScript is already hard enough as it is. I'd rather not 
> have to add to it the burden of trying to answer this very hard question.
> 
> Ok, say you don't buy this whole safe mashup fantasy and think we should just 
> depend on the next and future generations of browsers to secure iframes from 
> different origins against each other. Well, these are able to communicate 
> with postMessage. Currently, postMessage just passes copies of JSON data so 
> there are no object to share. When the frames in communication are in the 
> same address space and the JSON data is (somehow cheaply known to be) 
> transitively immutable, a natural and safe optimization is to pass these by 
> pointer sharing rather than copying. If transitively immutable data is 
> thread-safe, as it probably is, then this optimization even works between 
> workers that are running in separate threads in the same address space. (E 
> does this optimization and I believe it is important. See section 14.3 of 
> <http://erights.org/talks/thesis/>.)
> 
> But if WeakMaps with getKeys() makes gc observable, then this optimization 
> would open up this juicy side-channel for spying between frames and workers 
> from different origins.
> 
> 
> 
> 
> 
>> I personally use the keys on a personal implementation to check and see what 
>> callbacks may be outstanding, and if I need to reference all the Objects of 
>> a given type at once.
> 
> How does your implementation work (or is it native code)?
> 
> /be
> 
>> 
>> On Thu, Aug 26, 2010 at 8:14 PM, Waldemar Horwat <[email protected]> wrote:
>> Erik Arvidsson wrote:
>> 3. Why isn't there a way to iterate over the keys?
>> 
>> Because then it would be a regular map, not a weak map.  This is something 
>> that only a debugger should be able to do.
>> 
>>   Waldemar
>> 
>> _______________________________________________
>> es-discuss mailing list
>> [email protected]
>> https://mail.mozilla.org/listinfo/es-discuss
>> 
>> _______________________________________________
>> es-discuss mailing list
>> [email protected]
>> https://mail.mozilla.org/listinfo/es-discuss
> 
> 
> _______________________________________________
> es-discuss mailing list
> [email protected]
> https://mail.mozilla.org/listinfo/es-discuss
> 
> 
> 
> 
> -- 
>     Cheers,
>     --MarkM
> 
> 
> _______________________________________________
> es-discuss mailing list
> [email protected]
> https://mail.mozilla.org/listinfo/es-discuss

_______________________________________________
es-discuss mailing list
[email protected]
https://mail.mozilla.org/listinfo/es-discuss

Reply via email to