Hacker News new | past | comments | ask | show | jobs | submit login
Memfd_secret() in 5.14 (lwn.net)
121 points by todsacerdoti 66 days ago | hide | past | favorite | 51 comments

I'm most amused by this comment in the original post:

(Context: the discussion is around the drawback that memfd_secret must disable hibernation)

> That's why the only way to introduce new security feature is with “more security” choice being the only option.

> ... eventually, Chrome and Firefox would join the crowd. At that point it would become a moot point if you want to use hibernation or not: you system wouldn't be much useful if you would choose the hibernation.

Always interesting to see how ignorant some "security experts" are and how they love to hijack users and sabotage user experience using the excuse of "security".

The solution is to either encrypt or evict the secret memory on hibernation, and then decrypt it or have the app derive the secrets again when the user enters their password.

This would require some cooperation with the login program, and maybe with the user app, so it's hard to organize in the Linux world. I think something like this is available on Windows, but I'm not sure.

It would be also great if you could use the graphical login (greeter) to decrypt your disk (at boot or after sleep). I think some of the neccessary infrastructure would be the same for both features.

Here's how your typical Linux desktop app can be notified of an upcoming hibernation, and prepare accordingly: https://www.freedesktop.org/wiki/Software/systemd/inhibit/

(I'm assuming hibernation is not a requirement outside of the desktop space.)

Why can’t the kernel just generate a random secret at boot and encrypt swap and hibernate files automatically? MacOS does this. I thought Linux did already. With AES in hardware it’s not much more costly than memcpy.

This is done for Linux Lockdown. For memfd_secret, it might not be considered good enough; I think the memory needs to be evicted.

What is the threat model for this? If it’s a highly advanced attacker with physical access not even that is good enough. The best we can do is a true hardware enclave.

> The solution is to either encrypt or evict the secret memory on hibernation, and then decrypt it or have the app derive the secrets again when the user enters their password

A third option: do neither, and just accept that hibernation temporarily drops the security guarantees that the feature usually offers.

I would think that a temporary loss of security guarantee is tantamount to a complete loss of security guarantee.

Isn't this built to protect against stuff like Spectre, not arbitrary kernel code execution? Couldn't the order of operations be suspend all user processes, do CPUID on every core (i.e., stop all speculative execution), unprotect the memory, save everything to disk, and then the reverse to wake back up?

Good security experts know a security feature can’t sabotage usefulness or usability or people won’t use it.

Another gripe I have about infosec people is that they tend to fear the wrong things. They tend to be paranoid about the minutia of network firewalls and encryption while ignoring the fact that most compromises are inbound and due to malware or phishing.

They will obsess over how “smooth” the firewall is, then type “npm install” as root on production.

There's a lot of "security experts" getting thrown around here. None of my peers in security would tell you that malware/ phishing are anything other than the #1 threat to your organization 99% of the time.

We all have dealt with stupid security people just as we've all dealt with stupid people in general. It's unfortunate but competency is on a power curve across disciplines.

Real "security experts" do know that a security feature had to be usable :)

Per an earlier article in this series, https://lwn.net/Articles/812325/, this syscall is meant for protecting against disclosure of secrets via things like speculative execution and cache attacks, by ensuring that the kernel does not have the secret memory mapped at all. It does not protect against other kinds of attacks, like malicious code in the kernel. Thus, it will not keep your memory secret in every possible case; for that, you’d want to use something like Intel SGX (modulo the many vulnerabilities in that technology) which uses a combination of memory encryption and processor features to keep memory secret even from malicious kernels, hypervisors, etc.

Newbie question: multiple articles on this topic state that "even the kernel cannot access this memory" [because it is not in the direct map].

But surely, under assumption of arbitrary kernel code execution, a determined payload could restore the relevant direct map mappings, and still access this memory?

My understanding is this would protect against arbitrary reads in the kernel (but not arbitrary code execution as you pointed out).

Correct. The idea tthough is thay th4 mapping isn't in the places that are usually accessible so the normal gadgets thay get used won't work. In the future combinjng this with something like sev would make even more difficult to exploit.

This seems pretty cool, but I'm pretty sure that malware creators are going to be one of the main users.

What about the most important secrets of all, DRM keys?

> What about the most important secrets of all, DRM keys?

That falls squarely under malware, surely?

DRM has long since trusted the kernel. Utilizing the TEE or other hardware based mechanisms for hiding the keys is common. For situations where that's not available they just simply don't offer degraded service.

If you wanted DRM keys, couldn't you just patch memfd_secret() to remove its security features, let the program use it, then have a look at the assigned memory?

Sure, on paper, that will always be possible - just not in the age of signed kernel images that are cryptographically verified by your immutable bootloader.

Do we live in that age? Are there any computers that can't be made to boot an unsigned image? My experience is that Secure Boot is optional.

Windows Hardware Compatibility Program Specification mandates that Secure Boot can be disabled and customized, by a physically present user, on non-ARM platforms, in early versions of the Windows 10 spec.

Disabling Secure Boot must not be possible on ARM systems. - WHCP-Systems-Specification-1511.pdf

However, looking at the -2004 spec, both customization and enable/disable sections are prefaced with (Optional for systems intended to be locked down) so it is no longer mandatory, even on x86_64 systems, to provide a physically present user with the ability to disable or customize UEFI Secure Boot. The same language is used in the -21H2 spec for Windows 11.


You can't score full marks on Android SafetyNet if you aren't using an unmodified stock ROM.


So yes, some apps will refuse to run and in theory some services could refuse to accept requests from devices that aren't running unmodified images.

I can definitely imagine something like Snapchat using this as they have actually been fairly aggressive at trying to prevent "unauthorized clients" that can save images without notification to the user.

Win11 requiring TPM2.0 feels like it's edging ever closer to such an age...

Can the latest iPhones boot unsigned OSs yet? I'm guessing the jailbreakers aren't _that_ fast.

Isn't that a special case of the former?

If they're visible to children surely you can inject a DLL and exec into a new child process with access to the key?

The file is closed on exec, I believe.

I dislike the forced disablement of hibernation. That should have been something you could opt out of with a kernel command line parameter.

I don't think it's really annoying in practice.

First, most Linux servers don't care about hibernation, so the issue really just happens for desktops/laptops.

Second, there are at least 3 or 4 suspend states that Linux can offer, hibernation happens to be the most efficient one, but downgrading to a slightly less power efficient suspend state that keeps power in the RAM shouldn't make that much difference.

See https://01.org/linuxgraphics/gfx-docs/drm/admin-guide/pm/sle... for more information.

“Shouldn’t make that much difference?” It utterly kills various perfectly reasonable use-cases. Here are a few that I’ve personally experienced and seen others experience:

1. Laptop that can sleep for a week or ten days, and you’re going on holiday for a fortnight and leaving your laptop behind, and don’t want to leave it plugged in unattended (fire hazard) but don’t want to lose your session.

2. You’re off-grid for days on end (e.g. cycling tour with mostly tent camping, which I’ve done several times), and want to be able to use your laptop occasionally without its battery having been drained by being asleep instead of off, and want to keep using the same session.

3. You’re using a device with no battery (desktop computer or laptop with dud battery so that it dies as soon as you unplug it), but you need to move it from point A to point B without losing your session.

These are all straightforward examples where hibernate is essential.

Back when I checked it's a massive, multi-hour difference.

On the one hand hibernate could just zero out the secret memory instead of storing it, which would be trivial to detect by an application by checking if guard values were set to zero. On the other hand using hibernate significantly increases the risk of leaking parts of the secret that might temporarily end up on the stack or other less protected memory regions. So the tradeoff in program complexity might not be worth it, of course at that point you could still disable hibernate system wide.

> which would be trivial to detect by an application by checking if guard values were set to zero.

    if(data->guard != 0) {
        // Hibernation happens here.

You would have to check the guard after process and throw away the result if guard changed.

Edit: I think something similar is used to avoid time related system calls, the values are just mapped into the application address space and the kernel updates time and guard values concurrent to the application.

> just zero out the secret memory

Or pipe in /dev/urandom for that matter

Honestly hibernation never worked out perfectly in Linux. I have desktops to laptops running with different hardware, every once in a while the hibernation goes for toss and need to reboot

Works fine for me. I believe the only time I've seen issues is when I upgrade the kernel, forget to restart, and then hibernate the old (running) kernel. But then it just ignores the image and boots like normal

Works fine for me. I believe the only time I've seen issues is when I upgrade the kernel, forget to restart, and then hibernate the old (running) kernel. But it just ignores the image and boots like normal

i had hibernation problem with one specific network card,i guess atheros,it would make the whole system hang

This is a big capability. Right now it's quite difficult (requiring pinning together a few pieces of technology) to protect one process from another, especially if the other process is root. This isn't enough to get quite there, but it's a good start.

Windows has been working on similar tech via Protected Processes[0], notably used for both LSASS and their new eBPF verifier. That's been a tricky technology to get right but I think it's interesting.

> Andy Lutomirski repeatedly opposed making uncached mappings available, objecting to the performance cost and more;

Interesting. I'll want to read more into this.

My guess is that for the next 5 years there will be endless ways to leak these secrets and maybe, if we're lucky, things will improve over that time.

[0] https://www.alex-ionescu.com/?p=97

I wonder about the swap behaviour. If it's going to go to swap, it means the secret might remain on the hard disk. If the swap is on an SSD, you might not have a way to securely delete it at all due to the wear levelling layer. If it's not going to swap, you piss off the people with laptops who want hibernation. You might need to encrypt it and store the key in the TPM or something. Not sure if that's implemented though.

The article says that hibernation is completely disabled when a secret memory area is active and the memory area is locked into RAM. They designed it so the secret would never be written to persistent storage.

As noted in other comments it is locked in memory and hibernation is disabled, but generally encrypted swap is even easier to use than encrypted FS - a key can be generated on each boot (one-time random swap key is not compatible with hibernation though, for this you'd need a fixed one).

There's a whole section on the memory implications: "Another change, which created a bit of controversy over the life of the patch, disables hibernation when a secret memory area is active."

Based on that, I doubt they ignored the problem of swap space. My guess is that the region of memory is designated unswappable, as was already possible before.

Ideally there would be a way for the OS to signal that it's going to hibernate, so that the application can get rid of the secret stuff (overwrite with zeroes etc) and go to a state that, when back from hibernation, would ask for a password again.

Or even, disable this when hibernating to a swap inside an encrypted luks partition (which also asks for a password when it wakes up)

Perhaps a reasonable way would be to have a memfd_secret() flag which requests "kill this process if you're going to hibernate".

Then you could do the operations involving the secret in a dedicated subprocess.

This sounds usable to me and also promotes process-based isolation of application subcomponents.

I guess it should be theorically possible already for processes to do that. Systemd for instance is monitoring the suspend state.

mlock already allows you to do this so they likely did consider it

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact