mikeash.com pyblog/friday-qa-2014-05-23-a-heartbleed-inspired-paranoid-memory-allocator.html commentshttp://www.mikeash.com/?page=pyblog/friday-qa-2014-05-23-a-heartbleed-inspired-paranoid-memory-allocator.html#commentsmikeash.com Recent CommentsThu, 28 Mar 2024 16:45:27 GMTPyRSS2Gen-1.0.0http://blogs.law.harvard.edu/tech/rssWiper - 2014-11-26 14:39:02http://www.mikeash.com/?page=pyblog/friday-qa-2014-05-23-a-heartbleed-inspired-paranoid-memory-allocator.html#commentsThe question in the aftermath of something like this is whether Web companies will reform their security practices. There has been a move toward Perfect Forward Secrecy (PFS) by many of the major Web companies, but not all of them have implemented the practice. PFS means essentially that encryption keys get a very short shelf life, and are not used forever.3c30297010d4160442baadaa01db4390Wed, 26 Nov 2014 14:39:02 GMTinfo2@sbp-romania.com - 2014-06-20 07:58:07http://www.mikeash.com/?page=pyblog/friday-qa-2014-05-23-a-heartbleed-inspired-paranoid-memory-allocator.html#commentsWell, it's not C's fault, it's the guy that programmed the thing, right?1fe2870651af7a74b84428b1bea90203Fri, 20 Jun 2014 07:58:07 GMTmikeash - 2014-05-27 23:47:22http://www.mikeash.com/?page=pyblog/friday-qa-2014-05-23-a-heartbleed-inspired-paranoid-memory-allocator.html#commentsI'm not at all sure it's a good long-term approach. It's just an experiment and an interesting exercise. <br /> <br />However, it's fairly different from the scenario where OpenSSL's internal allocator defeated OpenBSD's protections. Their allocator was created purely for performance reasons, because some platforms had allocators that they felt didn't perform adequately. This one is the opposite: the paranoia makes it extremely slow and resource-hungry, to the extent that the stuff it does couldn't be applied to a general-purpose allocator because it's just too costly.8a1275a0faa54925a6256ebeefd59dc8Tue, 27 May 2014 23:47:22 GMTHugh Fisher - 2014-05-27 02:05:56http://www.mikeash.com/?page=pyblog/friday-qa-2014-05-23-a-heartbleed-inspired-paranoid-memory-allocator.html#commentsMike, I admire the effort you've put into this, but are you sure it's a good long term approach? <br /> <br />Theodore de Raadt points out that malloc on some platforms already had memory protection measures in place that would have caught the heartbleed exploit. The exploit only worked on those systems <b>because</b> the authors of OpenSSL had decided to write their own custom allocator. <br /> <br /><a href="http://article.gmane.org/gmane.os.openbsd.misc/211963">http://article.gmane.org/gmane.os.openbsd.misc/211963</a> <br /> <br />d5ce2f5e739ac39c49809f7ab86f5c4cTue, 27 May 2014 02:05:56 GMTmikeash - 2014-05-24 21:02:38http://www.mikeash.com/?page=pyblog/friday-qa-2014-05-23-a-heartbleed-inspired-paranoid-memory-allocator.html#commentsFor iOS, you can use <code>vm_read</code> and friends in <code>vm_map.h</code>. The <code>mach_*</code> versions of the functions are newer and better support 32-bit and 64-bit processes coexisting on the same system, but for this particular use the old ones will do fine.1012f02d907203c3d415f63e69a47bc1Sat, 24 May 2014 21:02:38 GMTZaph (Dan Grassi) - 2014-05-24 17:39:35http://www.mikeash.com/?page=pyblog/friday-qa-2014-05-23-a-heartbleed-inspired-paranoid-memory-allocator.html#commentsUnfortunately for iOS mach_vm.h seems to be unsupported. I am looking for a test to determine is memory is writable on iOS as well as OSX. <br /> <br />Any ideas?60998746393a9821d857fb45f3c95865Sat, 24 May 2014 17:39:35 GMTmikeash - 2014-05-24 03:46:13http://www.mikeash.com/?page=pyblog/friday-qa-2014-05-23-a-heartbleed-inspired-paranoid-memory-allocator.html#comments<b>Brian B.:</b> For (1), that's a good point. It should probably abort() if any exceptions are thrown through either method. I was thinking about exceptions and trying to clean up and ObjC's terrible exception safety made me shy away, but just bailing out would certainly be doable. For (2), I'm thinking of remote attackers rather than local ones, so between that and encrypted swap it's probably not necessary. Still, as you say, paranoia. It certainly could be done and would add another layer of protection. One downside is that it would mean you'd want to really limit how much memory you allocated with this thing, so as not to tie up too much RAM with wired data. (The OS should stop you before you go too far, but it's nice to be a good citizen.) <br /> <br /><b>Kevin Ballard:</b> I haven't looked at it much, but I've heard of Rust and what I've heard sounds great. I'd love to see the programming world move beyond this "full-up virtual machine, or nasal demons" dichotomy we've been stuck with for decades now. I'm sure that Rust code that uses the language's built-in memory allocation for buffers would inherently avoid Heartbleed, but if it tried to recycle buffers internally, couldn't it run afoul of the exact same problem? Perhaps the temptation would be less in a language like that, at least. <br /> <br />As for benchmarking, I haven't tried it at all, but I bet it's really really slow. Taking two system calls (and, I'd assume, a TLB flush) every time you want to access the memory is not going to be quick. The resizing stress test in my test code runs 1000 iterations in about a quarter of a second on my Mac Pro, which gives about 250µs per iteration, but I don't know how that's divided up among the resizing, the mprotect calls, the reads/writes.... <br /> <br /><b>Roger:</b> Since the code in the read/write blocks should be as short as possible, I think it's reasonable not to support reentrancy. An explicit check would be good as you say, but fortunately it fails safe the way it's written now, in that any bug will manifest as being unable to access the memory when you want to, rather than being able to access it when it's supposed to be locked away.541d02b61bbe7c7a0bc33482803fcd8aSat, 24 May 2014 03:46:13 GMTRoger - 2014-05-23 22:29:46http://www.mikeash.com/?page=pyblog/friday-qa-2014-05-23-a-heartbleed-inspired-paranoid-memory-allocator.html#commentsA scenario this gets wrong is recursive access. For example if a block accessing some memory calls another method that accesses the same memory. After the latter is called, the memory is reprotected but the first block hasn't finished execution. Multi-threaded access could cause similar problems. <br /> <br />I'd suggest either explicitly disallowing concurrent &amp; nested access (eg lock and exception) or making it work. Making it work is quite challenging since it would need to push/pop protections.52c8abbf23dc545cc812ffb65d7864e2Fri, 23 May 2014 22:29:46 GMTKevin Ballard - 2014-05-23 18:23:21http://www.mikeash.com/?page=pyblog/friday-qa-2014-05-23-a-heartbleed-inspired-paranoid-memory-allocator.html#commentsHave you seen Rust (<a href="http://www.rust-lang.org">http://www.rust-lang.org</a>)? It's a new language that aims for C++ performance, but with full memory safety. It would have prevented Heartbleed. <br /> <br />I'm also curious if you've done any benchmarking of MAParanoidAllocator. How much overhead does it introduce?e2e0473f1930e4d0acf9a3668224ea23Fri, 23 May 2014 18:23:21 GMTBrian B. - 2014-05-23 18:03:57http://www.mikeash.com/?page=pyblog/friday-qa-2014-05-23-a-heartbleed-inspired-paranoid-memory-allocator.html#commentsGreat article again, but a couple of issues: <br /> <br />1) the client callback could throw an exception leading to the buffer permissions being left open (assuming it was caught at some point up the stack). You should wrap the client block call in a try/catch handler to mitigate this. <br /> <br />2) The protected buffer can still be paged out and thus leak information. Not a big deal in most cases but for decrypted info it could be a problem. This is probably also never a problem on recent OSX versions as encrypted VM is enabled by default. However, being paranoid, you should add mlock() / munlock() to the allocation / deallocation; treating a failure as fatal only for root since mlock() may require root. Or just mlock/unlock for EUID root only.bb8436b7f709d23d3fba9e7cd1b09c40Fri, 23 May 2014 18:03:57 GMTLisa - 2014-05-23 13:57:13http://www.mikeash.com/?page=pyblog/friday-qa-2014-05-23-a-heartbleed-inspired-paranoid-memory-allocator.html#commentsThere's no reason to limit oneself to one heap - using one heap for user I/O and another disjunct memory space for the encryption engine would have added another degree of separation. Short of a massive buffer overrun, key data could never have leaked out that way.2fc838d27efe22d4a5027867d6b5d9f8Fri, 23 May 2014 13:57:13 GMT