es-discuss Digest, Vol 43, Issue 1

Leo Meyerovich lmeyerov at gmail.com
Thu Sep 2 00:08:40 PDT 2010


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, es-discuss-request at mozilla.org wrote:

> Send es-discuss mailing list submissions to
> 	es-discuss at mozilla.org
> 
> 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
> 	es-discuss-request at mozilla.org
> 
> You can reach the person managing the list at
> 	es-discuss-owner at mozilla.org
> 
> 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" <erights at google.com>
> Date: August 31, 2010 9:32:23 PM PDT
> To: Brendan Eich <brendan at mozilla.com>, Bradley Meck <bradley.meck at gmail.com>, es-discuss at mozilla.org
> Subject: Re: WeakMap API questions?
> 
> 
> On Thu, Aug 26, 2010 at 9:03 PM, Brendan Eich <brendan at mozilla.com> 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 <waldemar at google.com> 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
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>> 
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
> 
> 
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
> 
> 
> 
> 
> -- 
>     Cheers,
>     --MarkM
> 
> 
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20100902/a1fafcab/attachment-0001.html>


More information about the es-discuss mailing list