|
|
Log in / Subscribe / Register

Dropping the page cache for filesystems

LWN.net needs you!

Without subscribers, LWN would simply not exist. Please consider signing up for a subscription and helping to keep LWN publishing.

By Jake Edge
June 11, 2024

LSFMM+BPF

VFS maintainer Christian Brauner led a discussion about the possibility of selectively dropping the contents of the page cache for a filesystem in a session at the 2024 Linux Storage, Filesystem, Memory Management, and BPF Summit. As he described in his topic proposal, the use case that started him down this path comes from GNOME, which wants to be able to safely suspend access to an encrypted home directory. While it is known to kernel developers, it is surprising to others that reads from encrypted filesystems that have been suspended will succeed if the data to be read still exists in the page cache.

Secrets exposed

Brauner began the session by quickly describing the test case that reproduces the problem, which he included in his proposal (and in his slides). It creates an image file, uses the LUKS cryptsetup tool to turn it into an encrypted volume, makes an XFS filesystem on it, and mounts it. The next step is to write the string "secrets" to a file on the filesystem and use the luksSuspend operation to suspend the encrypted block device—a simple cat on the file will still show the secret data.

[Christian Brauner]

He asked if there was some way to add an API that would drop the contents of the page cache so that reading the file would give an error. He went through a list of the objections (and other ideas) that had been posted in the topic-proposal thread, which he had collected onto a slide.

On the mailing list, Jan Kara had raised the problem of referenced folios in the page cache, which could come from a vmsplice() call; those pages cannot be dropped. Kara also asked about the interaction of a page-cache-drop operation with mlock() and noted that pages mapping executable code "are practically unevictable". Beyond that, if the intent is to defend against cold boot attacks, there will be a need to zero-out the memory, since dropping the page-cache entries does not change the memory contents, Kara added.

Matthew Wilcox had suggested using the security_file_permission() hook for Linux security modules (LSMs) to inhibit reading the data. So a new BPF LSM program, say, could be attached when the suspend operation is done to return an error for any reads, Brauner said. He thinks there is value in considering some kind of API for page-cache dropping for other use cases, beyond just cold-boot protection. For example, David Howells has told him that he would use an API of that sort for AFS; systemd may also have a use case for it, so it is at least something to consider adding.

Amir Goldstein said that there are some tests that are part of the Linux Test Project (LTP) that currently do "some gymnastics" to try to drop the page cache for a filesystem; it is not reliable, however, so an API would also be useful for testing. Jeff Layton pointed out that Trond Myklebust has posted patches for NFS that will drop the page cache for individual inodes, which might provide part of the solution. Brauner said that Kent Overstreet mentioned a similar feature for subvolume deletion in bcachefs. Dave Chinner pointed out that posix_fadvise() can drop the page cache for a particular inode already.

Dumb idea?

"You can say it's a dumb idea", Brauner said with a grin. Layton disagreed, saying that it is useful. Wilcox agreed with that: "I can see the use case, it makes sense, it is a reasonable thing to want, it is just a hard thing to implement". There are ways to deal with vmsplice() and mlock(), he said, by marking those pages as "not up to date" and zeroing them. But it is "really tricky" for things like pages that have been handed off to an RDMA driver, which is maintaining the state of those pages.

"Is it okay to just fail?", Brauner asked; maybe the operation can just return an error if it cannot be done fully. Wilcox said that probably 99% of the pages could be dropped without encountering one of the corner cases.

Ted Ts'o said that perhaps part of the problem was that the feature had been introduced as a security feature, which causes developers to immediately focus on the corner cases. Fscrypt has a "best effort" mechanism that tries to remove all of the directory entries and flush all of the inodes whenever the key gets removed from the keyring. There was no effort to deal with the possibility that encrypted files were still open, because the feature originally targeted ChromeOS, where it only happened after the user session ended. It was not a complete solution and was not advertised as a feature, nor documented.

That is a possible path forward for this feature, he said, but if there is a need to try to handle all of the corner cases, it is going to be difficult to do. Wilcox said that if you need to ensure that your LibreOffice documents on the filesystem are no longer accessible, that would be fairly straightforward, but if you want to guarantee that for every single file on the filesystem, it is much harder.

Overstreet said that it was "yet another revoke() discussion", which really needs to be resolved at some point. The revoke() system call has been a topic in filesystem circles for more than a decade (at least); it is meant to close all open file descriptors for a given file, but has run aground on a myriad of corner cases. There are multiple places where revoke() is needed (fsck in corner cases, debugfs), Overstreet said, so someone should tackle the problem. Kara said that he would be reluctant to give guarantees for dropping the page cache, because it greatly depends on the context of how the filesystem is being used, but in many cases it should work fine.

Systemd use

Lennart Poettering said that systemd would like to use this feature, similar to the way that fscrypt does. A best-effort solution would be fine, though he wants to get some kind of error indication when it fails; the filesystem should try to drop as many pages as it can from the cache and, perhaps, report the number that could not be dropped. Systemd will use the control-groups interface to freeze the user session before invoking the operation, which should make for fewer corner-case problems. The systemd use case should not be conflated with the cold-boot-protection case, where the encrypted device needs to be suspended and the pages need to be zeroed out, which is more than what systemd (and others) need, he said.

Ts'o said that fscrypt reports the number of inodes it was not able to evict. It puts out a log message with that number along with a single inode number as a sample; the information is mostly for ChromeOS developers to use for debugging. It is "half-assed, but that's what we did".

There is a question of what to do with dirty pages that are in need of writeback when this page-cache removal is done, Chinner said. Are they thrown away, or does the operation wait for the writeback to be done? And where would writeback errors be reported? Brauner said that the belief is that the device has been suspended, so there will be no dirty pages. Ts'o said that when the key gets removed, fscrypt writes all of its dirty inodes, because it will not be able to once the key is gone. If user space has been suspended, as in the systemd use case, there is no one to report any errors to anyway, so a console message is all that can be done.

Chinner said that it is important to make it clear to users of any new API that they are responsible for ensuring that the filesystem is frozen before dropping its page cache. Dropping the page cache for filesystems that have executable files mapped into memory will not work well, for example. But those are not the types of files people are looking to protect with a feature of this sort, Wilcox said; it is things like document files and web-browser history that people are concerned about. Brauner said that the feature would be targeted at system-level software that is assumed to know what it is doing; Wilcox said that a 99% solution will increase the security for everyone, but it is important not to claim that it is a 100% solution.

Goldstein wondered about the inode cache; is file data the only concern or should there be protections for metadata as well? Chinner said that trying to purge the inode cache while the filesystem is frozen will deadlock. Wilcox said that the directory-entry cache should also be purged, but did not think that purging the inode cache was needed; Chinner said that could still deadlock, however.

Ts'o noted that the order used by fscrypt was to get rid of all of the directory entries, shrink the inode cache, do any writeback needed, and, only then, freeze the filesystem and purge the page cache; that is the right order to do those things, but it is all done on a best-effort basis. He suggested that perhaps the luksSuspend operation could add some of these extra steps, since suspending an encrypted device would generally benefit from removing this extra data from memory.

Shrinkers

The current mechanisms available for clearing out the directory-entry and inode caches are the shrinkers, Chinner said, but there is no way to confine them to a single superblock; in addition, those caches are partitioned by memory control groups, so any clearing operation will need to take those into account, as well. Wilcox said that an unmount operation would obviously clear all of this information, so perhaps that could be used. But Chinner said that is not workable for this use case because the users are suspending the system to RAM, and have user-space applications running; an unmount would disrupt all of that.

Overstreet said that the feature could mesh well with the idea of live filesystem migration. Bcachefs developers are getting ready to release synchronous send and receive for the filesystem, so combining that with a page-cache flush/drop operation would provide the ability to live-migrate a container and its filesystems to another host. Overstreet clarified that he was talking about the same idea as the Btrfs send and receive.

There was some discussion of use cases for cleaning up caches on a per-superblock basis, though it is seen as a difficult problem by some. Chinner said that the shrinker interface could be used, with per-superblock functionality added; it would not be hugely difficult, since much of the mechanism for the cleanup is already done there. He has been looking at using shrinkers as a way to implement dropping the caches because the existing ways to do so (using /proc/sys/vm/drop_caches) take a long time. That runs as a single thread, so it can take up to 15 minutes to run for large caches ("with a few hundred million cached inodes"), he said, which is problematic for benchmarking and other uses.

Kara wondered whether the shrinker was the right interface or whether something based on what is done at unmount time might be better. There is an inherent problem that shrinkers are focused on memory reclaim, rather than on the task needed for this feature. He thought there might be value in a new interface that was somewhat "saner". Chinner acknowledged that there was more to do beyond what the shrinkers do, but thought that they might be part of the solution.

Luis Chamberlain asked why this new mechanism would not be used whenever a filesystem is frozen. Chinner said that filesystems are often frozen for backup purposes, so the page-cache entries are still important. There was some discussion of the API and whether it should be an ioctl() command or something else. Chinner thinks that some new API, probably via a system call, that is not tied to filesystem freezing or anything else, is likely to be the right way forward; that gives the most flexibility if the internals need to change along the way.


Index entries for this article
KernelFilesystems/Page cache
ConferenceStorage, Filesystem, Memory-Management and BPF Summit/2024


to post comments

What is the use case ?

Posted Jun 11, 2024 14:54 UTC (Tue) by ju3Ceemi (subscriber, #102464) [Link] (7 responses)

I do not understand the use case
Is it not OK when I umount the filesystem ?

Why would I freeze instead of umounting ?

What is the use case ?

Posted Jun 11, 2024 15:09 UTC (Tue) by mageta (subscriber, #89696) [Link]

I can imagine 1 or 2 scenarios from the top of my head - no idea whether those are the ones Gnome has in mind. If you want to lock you laptop/whatever device (screen lock), or do suspend-to-ram (S2, S3), you might want to add a bit more safety and freeze encrypted file systems until someone enters a valid authentication again to signal the owner is back. In that intermitted time frame it's probably unfeasible to actually unmount the FS as it might be in use by something.

Again, I don't know whether that's the scenario aimed at here.

Screen lock confidentiality

Posted Jun 11, 2024 16:06 UTC (Tue) by Tobu (subscriber, #24111) [Link] (5 responses)

Unmounting requires the mounted filesystem to be entirely unused, or to be willing to kill any processes holding references to it. For protecting user data, you'd want a way to make filesystem data and metadata inaccessible cheaply and frequently, maybe whenever a screen (desktop, phone…) is locked, so it can't disrupt running processes and the filesystem must appear in the same state after unlock.

Thinking along those lines, dropping caches does have a visible impact in terms of performance, so it would be nice to have the page cache encrypted instead. But decrypting on every access would be a much more intrusive change.

Screen lock confidentiality

Posted Jun 11, 2024 20:49 UTC (Tue) by willy (subscriber, #9762) [Link] (4 responses)

The point of the pagecache is to support mmap(). That's not compatible with "keep all data in the page cache encrypted".

Screen lock confidentiality

Posted Jun 12, 2024 1:16 UTC (Wed) by intelfx (subscriber, #130118) [Link] (3 responses)

> The point of the pagecache is to support mmap(). That's not compatible with "keep all data in the page cache encrypted".

It's not compatible with _keeping_ all the data encrypted, but perhaps the GP meant the en-/decryption of the pagecache contents as a one-off operation (same semantics as suspending/resuming the LUKS volume).

I don't see an immediate reason why that wouldn't work — just mark all the PTEs as not present, similar to them being swapped out.

Screen lock confidentiality

Posted Jun 12, 2024 1:34 UTC (Wed) by willy (subscriber, #9762) [Link] (2 responses)

What's annoying about this whole proposal is how under specified it is.

It starts out with "we want the page cache to be inaccessible". Then it turns out to be OK if 99% of pages are inaccessible, but 1% are still accessible. But a purely programmatic prohibition is unacceptable because evilmaid attacks. But we don't care enough about evilmaid attacks to zero pages which are being evicted from the pagecache.

It all feels like "we want to feel secure but we don't want to pay very much for it".

Screen lock confidentiality

Posted Jun 12, 2024 20:10 UTC (Wed) by stevie-oh (subscriber, #130795) [Link] (1 responses)

I disagree. I believe it's a matter of "we should take feasible steps towards maximizing security."

Treating anything less than exactly 100% secure as being the same as 0% secure is the sort of thing the cryptography/security people frequently do, which tends to set Linus off (and I agree with him.)

The troublesome feature in question seems to be "cryptsetup-suspend", which (according to the documentation) flushes all pending writes to disk and then purges the encryption (more relevantly here, *decryption*) keys from memory. After this point, up until cryptsetup-luksresume is executed to reload the key (presumably the result of the user reauthenticating themselves), any attempt to read from the encrypted block device will fail.

However, not all attempts to read from the *filesystem* will result in reads from the *block device*. Sometimes everything needed to read a file on that filesystem is still in the page cache, in which case that file -- one that is nominally stored on an encrypted filesystem for which the system does not have the decryption keys available -- is still readable.

The request is simple: provide some sort of method to tell the kernel to evict as much information as possible from its own caches. The article points out that there are many cases where a page cannot be evicted:

1. It's part of an active vmsplice call
2. It's part of a DMA operation (especially an RDMA operation)
3. It's mapped as executable code (e.g. a running binary)

I would expect (and based on the article, the kernel devs agree with me) that the overwhelming majority of the files one would be interested in keeping secret don't fall into any of these categories. I'm not likely to be vmsplicing or RDMAing my SSH private key anywhere.

It *is* quite reasonable for me to be executing code from an encrypted block device -- as a software developer, a *lot* of the executables that I run are from my home directory, because I just compiled them. But I'm not super concerned about someone gaining access to such an executable via the page cache. And if I *am*, well, then it's on me to make sure I kill that process before I close the lid on my laptop.

Screen lock confidentiality

Posted Jun 12, 2024 20:27 UTC (Wed) by willy (subscriber, #9762) [Link]

FYI, I'm the Matthew Wilcox quoted in the above article.

Abililty to turn off pagecache

Posted Jun 11, 2024 17:08 UTC (Tue) by snajpa (guest, #73467) [Link] (11 responses)

It sure would be nice to have support for completely turning off any pagecache involvement from a filesystem implementation.

Abililty to turn off pagecache

Posted Jun 11, 2024 18:05 UTC (Tue) by acarno (subscriber, #123476) [Link] (4 responses)

I guess I could envision useful scenarios from a security perspective, but generally this seems like a bad idea. Turning off the page cache entirely for the filesystem would imply all read / write operations have to go directly through disk, which is orders of magnitude slower (generally) than DRAM. A quick bit of searching shows the O_DIRECT flag attempts to minimize the involvement of the page cache (though not completely avoiding it).

Out of curiosity, what use cases would you find this useful for?

Abililty to turn off pagecache

Posted Jun 11, 2024 20:06 UTC (Tue) by Cyberax (✭ supporter ✭, #52523) [Link]

A lot of databases or data-intensive applications just need to be able to write the data to disk, and they might not care about reading them at all. Or the other way around, they might read data only once, send it through the network, and then they might never need that particular piece of data again.

Abililty to turn off pagecache

Posted Jun 11, 2024 20:10 UTC (Tue) by pdewacht (subscriber, #47633) [Link]

See last week's article :) https://lwn.net/Articles/976856/

Abililty to turn off pagecache

Posted Jun 11, 2024 21:45 UTC (Tue) by snajpa (guest, #73467) [Link] (1 responses)

Or the filesystem might actually implement its own caching scheme, which might be better for some scenarios than what the kernel provides; if I were implementing a RDMA-based distributed FS, I'd want as much control over the memory I could possibly get. Pagecache is useful, but there is a huge potential for data duplication in memory between pagecache and the implementation's own details - even without RDMA, if the FS implementer has better ideas for cache management for a given use-case, duplication is currently unavoidable.

Abililty to turn off pagecache

Posted Jun 11, 2024 23:20 UTC (Tue) by Paf (subscriber, #91811) [Link]

It’s trivial if you want to write your own - nothing about the kernel and VFS forces you to use the page cache. Just don’t call those hooks.

It’s just an enormous pain to write your own and you’d better hope you’re better and can stay better because you get no benefit from general improvements from the community.

I *work* on an RDMA enabled distributed FS that uses the Linux page cache - Lustre, it’s the most popular one - and we don’t get any duplication from that. Nothing about the page cache gives us any trouble there - they’re just pages. You can do RDMA with them.

You’re also able to be selective about when you use the Linux page cache, as long as you’re willing to handle alignment issues yourself and cover conflicts (generally with flushing like DIO does),

Abililty to turn off pagecache

Posted Jun 11, 2024 21:46 UTC (Tue) by dezgeg (guest, #92243) [Link] (4 responses)

Page cache is also used for things like mmap() and allowing arbitrary sized/aligned IO. Such flag sounds like 'break most applications' flag to me.

Abililty to turn off pagecache

Posted Jun 11, 2024 22:15 UTC (Tue) by snajpa (guest, #73467) [Link] (3 responses)

I'd love to be able to provide my own memory that backs the mmaped file's data, speaking from the filesystem's perspective.

RDMA over IP is coming and that's not all - I believe CXL is going to eventually enable PCIe-link-layer based inter-CPU linking between different systems within a rack with even better latencies than what current RDMA world can do - and over time, possibly, I can imagine scaling out via fiber - which is now financially out of reach for most due to requiring on-chip transceivers, but that situation is also not static.

Currently, when I'm thinking about a FS that does in-kernel RDMA over some PCIe device - or even better, PCIe directly + let's say we add non-transparent bridging of different systems into the mix - truly taking things into own hands as far as I understand it, requires, that the really interesting memory with hot data is all in the PCIe controller window. As I currently understand it, where of course I might be wrong, my feeling is that implementing this with current NTBs seems hard because either they're lacking in DMA capabilities + pagecache in the loop, or they lack publicly available documentation. Going forward I think it should be manageable even with pagecache in the loop, but it still would be nice to not have to worry about it at all.

Abililty to turn off pagecache

Posted Jun 11, 2024 23:22 UTC (Tue) by Paf (subscriber, #91811) [Link]

I encourage anyone reading here to read my previous comment:
https://lwn.net/Articles/978025/

And there’s also some interesting work we’re doing in Lustre - a popular RDMA using distributed file system which is implemented kernel modules - on *when* we use the page cache. It’s totally possible with current Linux interfaces.

https://wiki.lustre.org/images/a/a0/LUG2024-Hybrid_IO_Pat...

Abililty to turn off pagecache

Posted Jun 11, 2024 23:24 UTC (Tue) by Paf (subscriber, #91811) [Link]

Note that providing your own memory is possible even for mmap. You just have to write a bunch of interfaces and code to do so.

Abililty to turn off pagecache

Posted Jun 12, 2024 12:06 UTC (Wed) by willy (subscriber, #9762) [Link]

Essentially you're asking for DAX which already exists.

Abililty to turn off pagecache

Posted Jun 11, 2024 23:13 UTC (Tue) by Paf (subscriber, #91811) [Link]

Do you plan to do exclusively direct IO? Or are you just talking about write through and immediate drop?

Also you’ll be *amazed* how great no readahead is. It’s really, really great for general use. *pained cough*

Unmounting filesystems with TimeoutIdleSec on suspend

Posted Jun 12, 2024 5:16 UTC (Wed) by viiru (subscriber, #53129) [Link]

I've been wondering why systemd doesn't currently unmount automounted filesystems that have TimeoutIdleSec set on suspend. That would be an easy win for some use-cases related to this.


Copyright © 2024, Eklektix, Inc.
This article may be redistributed under the terms of the Creative Commons CC BY-SA 4.0 license
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds