mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] mm/secretmem: Keep locked memory accounting until inode eviction
@ 2026-10-30 15:24 Baek Kyu, Kim
  0 siblings, 0 replies; only message in thread
From: Baek Kyu, Kim @ 2026-10-30 15:24 UTC (permalink / raw)
  To: Andrew Morton, Mike Rapoport; +Cc: Baek Kyu, Kim, linux-mm, linux-kernel

A secretmem inode can outlive its original file. An O_PATH descriptor
opened through /proc/self/fd keeps the inode and its unevictable folios
alive after the mapping and original descriptor are closed. The file
release path nevertheless drops the locked-memory charge, allowing the
same user to reuse RLIMIT_MEMLOCK while those folios remain allocated.

Move private-state and locked-memory accounting cleanup to inode eviction,
after truncating the page cache. Keep secretmem_users active over the same
lifetime so that the hibernation guard covers retained secret pages. Let
iput() handle file-creation failures and tolerate an inode with no private
state.

Fixes: 97d34aa65c29 ("mm/secretmem: properly account locked pages")
Signed-off-by: Baek Kyu, Kim <pocj8ur4in@gmail.com>
---
On an arm64 QEMU guest with an 8 KiB RLIMIT_MEMLOCK, an O_PATH reference
retained two secretmem pages. The baseline dropped the charge to zero and
allowed a further one-page fault; the patch kept both pages charged and
rejected that fault until the last path reference closed. The Image
was built with KASAN and lockdep. Hibernation, other architectures,
and long-running concurrency were not tested.

 mm/secretmem.c | 31 ++++++++++++++++++-------------
 1 file changed, 18 insertions(+), 13 deletions(-)

diff --git a/mm/secretmem.c b/mm/secretmem.c
index 384f5cfc457f..fa8be360bd2a 100644
--- a/mm/secretmem.c
+++ b/mm/secretmem.c
@@ -185,18 +185,14 @@ static void secretmem_destroy_inode_priv(struct inode *inode)
 {
 	struct secretmem_inode_state *state = inode->i_private;
 
+	if (!state)
+		return;
+
 	secretmem_unaccount_all_folios(state);
 	free_uid(state->user);
 	kfree(state);
 	inode->i_private = NULL;
-}
-
-static int secretmem_release(struct inode *inode, struct file *file)
-{
 	atomic_dec(&secretmem_users);
-	secretmem_destroy_inode_priv(inode);
-
-	return 0;
 }
 
 static int secretmem_mmap_prepare(struct vm_area_desc *desc)
@@ -216,7 +212,6 @@ bool vma_is_secretmem(struct vm_area_struct *vma)
 }
 
 static const struct file_operations secretmem_fops = {
-	.release	= secretmem_release,
 	.mmap_prepare	= secretmem_mmap_prepare,
 };
 
@@ -274,6 +269,7 @@ static int secretmem_init_inode_priv(struct inode *inode)
 
 	state->user = get_uid(current_user());
 	inode->i_private = state;
+	atomic_inc(&secretmem_users);
 	return 0;
 }
 
@@ -296,7 +292,7 @@ static struct file *secretmem_file_create(unsigned long flags)
 				 O_RDWR | O_LARGEFILE, &secretmem_fops);
 	if (IS_ERR(file)) {
 		err = PTR_ERR(file);
-		goto err_free_priv;
+		goto err_free_inode;
 	}
 
 	mapping_set_gfp_mask(inode->i_mapping, GFP_USER);
@@ -309,11 +305,7 @@ static struct file *secretmem_file_create(unsigned long flags)
 	inode->i_mode |= S_IFREG;
 	inode->i_size = 0;
 
-	atomic_inc(&secretmem_users);
-
 	return file;
-err_free_priv:
-	secretmem_destroy_inode_priv(inode);
 err_free_inode:
 	iput(inode);
 	return ERR_PTR(err);
@@ -335,6 +327,18 @@ SYSCALL_DEFINE1(memfd_secret, unsigned int, flags)
 	return FD_ADD(flags & O_CLOEXEC, secretmem_file_create(flags));
 }
 
+static void secretmem_evict_inode(struct inode *inode)
+{
+	truncate_inode_pages_final(&inode->i_data);
+	clear_inode(inode);
+	secretmem_destroy_inode_priv(inode);
+}
+
+static const struct super_operations secretmem_super_ops = {
+	.statfs		= simple_statfs,
+	.evict_inode	= secretmem_evict_inode,
+};
+
 static int secretmem_init_fs_context(struct fs_context *fc)
 {
 	struct pseudo_fs_context *ctx;
@@ -342,6 +346,7 @@ static int secretmem_init_fs_context(struct fs_context *fc)
 	ctx = init_pseudo(fc, SECRETMEM_MAGIC);
 	if (!ctx)
 		return -ENOMEM;
+	ctx->ops = &secretmem_super_ops;
 
 	return 0;
 }
-- 
2.55.0


^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2026-10-30 15:24 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-30 15:24 [PATCH] mm/secretmem: Keep locked memory accounting until inode eviction Baek Kyu, Kim

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®