Re: [Factor-talk] Secure Memory

2020-04-12 Thread Alexander Ilin
(Sorry, I accidentally sent the previous message before it was finished.) I will revive this old thread of mine to say that any copying GC creates an issue with sensitive data, which higher level application code can't overcome. If there is a piece of sensitive data, which the application wants to keep hidden - for example, by only decrypting it briefly before use, or by zeroing it when it's no longer needed - the GC can enter at the worst possible moment and create a copy of such data when it's exposed - that is, after decryption or before zeroing. When this weakness is combined with other vulnerabilities, sensitive data can be leaked. Therefore, to mitigate such issues there has to be support on the GC level, it has to be a feature of the runtime environment. I agree that performance of the copying GC is proportional to the number of surviving objects. If we add the extra "sensitive" bit, the performance will be proportional to the number of surviving objects plus the number of the objects tagged with the bit. The latter number is typically very small. I agree that it's foolish to delay cleanup of the sensitive memory to the GC time, but on the other hand it's not always possible to know if all the clients are done with the data. In any case, if GC is able to copy the sensitive data during memory compaction, it prevents the application code from zeroing the old copy. I'd like to reply to the Doug's argument once again. He wrote: "if they could read your memory after a gc why not just read it before gc instead?"You see, normally "they" can't arbitrarily read my memory. But sometimes due to application bugs they can get some extra memory, or some uninitialized memory. Remember the Heartbleed vulnerability? The server would return a block of freshly allocated, uninitialized memory, and sometimes that memory would contain data previously submitted by other clients of the server, or even the server's own cryptographic secrets: https://en.wikipedia.org/wiki/Heartbleed#Behavior. So, it's important that freshly allocated, uninitialized memory doesn't contain any sensitive data, and the only way to assure that in a system with a relocating GC, is to make the GC wipe such data before returning it to the unallocated pool. It's not about preventing other applications on the same system from accessing the memory, and it's not about potential ability of reading random memory addresses by some Factor code that I can write. It's about mitigating the consequences of bugs that can occur in the normal course of the events. As the situation is now, I think it is not difficult, but impossible to adequately mitigate such security risks in the Factor's memory management. I would like it to be possible. Unfortunately, I lack the knowledge to change the Factor runtime/GC, having only some limited experience with it. That's why I'm trying to convince you guys to have another look at the matter. In the meantime I have added a library support for the secure memory, which requires libsodium. Essentially, it's a way to allocate memory outside of the Factor's GC, and then manage a wrapper to that memory with the destructors vocab. The memory is wiped on deallocation, it's possible to make it read-only or inaccessible, and it's marked in a way that prevents the OS from swapping it out to disk: https://libsodium.gitbook.io/doc/memory_management. Here's the PR: https://github.com/factor/factor/pull/2277I'm not sure if I should have tagged the subvocab with "not loaded", or if the tag in the parent is sufficient. 19.01.2018, 23:39, "Björn Lindqvist" :Yes, there is (byte-array) which allocates uninitialized memory. User code is not supposed to call that word. But there are many other ways to get hold of memory you don't own. For example, you can just read it:     1234  0 alien-cell That would attempt to read 4 or 8 bytes from address 1234. It will produce a memory protection fault because the process doesn't own the address at 1234, but it would have worked fine if it did. It is as doug says, if you can read it after the gc has run you can read it before too. Try running:     "it works" kernel.private:context vm:context memory>struct datastack>>      0 alien-cell alien-address 0xf unmask 32 +  alien>native-string 2018-01-17 23:11 GMT+01:00 Alexander Ilin :Doug and Björn, I'd like to point out the following use case for your consideration, and then you can tell me if the selective zeroing of sensitive memory buffers by the GC makes sense. Some sensitive data is stored in a networked application (let's say, a Web Server with its security certificates).The data in the application is surrounded with some `with-destructors` combinators that will clear it when it's no longer needed.But - the GC comes along and relocates the sensitive data in memory by copying it and not erasing it in the old place. The old location is marked as free memory. Now I assume that there is a way in Factor to allocate a `byte-array` without initializi

Re: [Factor-talk] Secure Memory

2020-04-12 Thread Alexander Ilin
I will revive this old thread of mine to say that any copying GC creates an issue with sensitive data, which application code can't overcome. If there is a piece of sensitive data, which the application wants to keep hidden - for example, by only decrypting it briefly before use, or by zeroing it when it's no longer needed - the GC can enter at the worst possible moment and create a copy of such data when it's exposed - that is, after decryption or before zeroing. 19.01.2018, 23:39, "Björn Lindqvist" :Yes, there is (byte-array) which allocates uninitialized memory. User code is not supposed to call that word. But there are many other ways to get hold of memory you don't own. For example, you can just read it:     1234  0 alien-cell That would attempt to read 4 or 8 bytes from address 1234. It will produce a memory protection fault because the process doesn't own the address at 1234, but it would have worked fine if it did. It is as doug says, if you can read it after the gc has run you can read it before too. Try running:     "it works" kernel.private:context vm:context memory>struct datastack>>      0 alien-cell alien-address 0xf unmask 32 +  alien>native-string 2018-01-17 23:11 GMT+01:00 Alexander Ilin :Doug and Björn, I'd like to point out the following use case for your consideration, and then you can tell me if the selective zeroing of sensitive memory buffers by the GC makes sense. Some sensitive data is stored in a networked application (let's say, a Web Server with its security certificates).The data in the application is surrounded with some `with-destructors` combinators that will clear it when it's no longer needed.But - the GC comes along and relocates the sensitive data in memory by copying it and not erasing it in the old place. The old location is marked as free memory. Now I assume that there is a way in Factor to allocate a `byte-array` without initializing the memory. This means that by requesting enough "free" memory from the runtime we will at some point get a hold of the block containing the released copy of the sensitive data. This is a problem, especially if our application is downloading and running scripts from the network, like, say, a Web Browser would do all the time. That combination of not clearing the memory on release and not clearing the memory on allocation (both expensive things to do if you do them all the time) creates the potential for the leakage. Adding a single bit flag that would tell GC to zero a particular object's memory on release (or reallocation) would be a great security feature, I think. Not a global command-line argument, but a per-object-instance flag.What do you think? Does it make sense? Is it difficult to implement? As to the Java finalizers argument - I'm not suggesting to rely on GC for the cleanup, as indeed it may never happen. I'd only want it not to leave old copies of some specific buffers hanging around when it's done its invisible (to the application code) magic. 17.01.2018, 22:40, "Doug Coleman" :We actually had a command-line argument to the vm to optionally zero the gc after collection but we removed the feature somewhere around when we dropped BSD support. It's probably better than nothing but if they could read your memory after a gc why not just read it before gc instead? Doug On Wed, Jan 17, 2018 at 1:34 PM Björn Lindqvist  wrote:Factor when run in debug mode actually clears memory. See bump_allocator.hpp. Unfortunately clearing memory is slow as hell. The time complexity of copying gc is proportional to the number of surviving objects. But if you want to clear memory too it becomes proportional to the total number of allocated objects.  Plus, relying on the gc to zero out sensitive memory is a bad idea. You never know when the gc runs or if it runs at all. That's why it is considered bad practice in Java to use finalizers. I think it would be better to use the destructors vocab to implement zeroing out of sensitive memory.     2018-01-16 23:17 GMT+01:00 Alexander Ilin :Hello!  I was reading a manual on the `8th` language, and noticed an interesting feature.  Apparently, it's possible to call a word on a memory buffer and thereby mark it as "sensitive information".  GC would zero the memory upon release.  Zeroing every bit of memory on release would add a lot of overhead (as I understand), but selectively clearing it like this could help with security applications that deal with certificates and passwords and stuff. This is especially useful, because in Factor GC can relocate (= copy) objects in memory. Does it clean up the memory it copied?  Do we have such a feature? Is it difficult to implement?  Bjourne, you've seen a lot of the runtime, can you comment?---=--- Александр--Check out the vibrant tech community on one of the world's mostengaging tech sites, Slashdot.org! http://s