public inbox for linux-mm@kvack.org
 help / color / mirror / Atom feed
From: Christian Brauner <brauner@kernel.org>
To: pasha.tatashin@soleen.com
Cc: kexec@lists.infradead.org, linux-mm@kvack.org, graf@amazon.com,
	 rppt@kernel.org, pratyush@kernel.org,
	linux-kernel@vger.kernel.org,  luca.boccassi@gmail.com
Subject: Re: [PATCH v9 3/6] liveupdate: add LUO_SESSION_MAGIC magic inode type
Date: Wed, 22 Apr 2026 13:58:08 +0200	[thread overview]
Message-ID: <20260422-liege-klotz-cfd84db12d91@brauner> (raw)
In-Reply-To: <20260420141741.2688371-4-luca.boccassi@gmail.com>

On Mon, Apr 20, 2026 at 03:15:11PM +0100, luca.boccassi@gmail.com wrote:
> From: Luca Boccassi <luca.boccassi@gmail.com>
> 
> In userspace when managing LUO sessions we want to be able to identify
> a FD as a LUO session, in order to be able to do the special handling
> that they require in order to function as intended on kexec.
> 
> Currently this requires scraping procfs and doing string matching on
> the prefix of the dname, which is not an ideal interface.
> 
> Add a singleton inode type with a magic value, so that we can
> programmatically identify a fd as a LUO session via fstatfs().
> 
> Signed-off-by: Luca Boccassi <luca.boccassi@gmail.com>
> Reviewed-by: Pasha Tatashin <pasha.tatashin@soleen.com>
> ---

Fold the following diff [1] into this commit (and the test), please.

Btw, I see that currently you only allow to retrieve one file per
session. If you ever want to allow multiple files for a session
but single shared inode amongst the same session so that different files
for the same session still compare as identical I added a mechanism
called path_from_stashed() which would easily allow for this. The luo
session just needs to stash a dentry pointer to achieve this. Just a
heads-up.

[1]:
From 7a11a931eaf4766e70c81d32093668ecd60f4952 Mon Sep 17 00:00:00 2001
From: Christian Brauner <brauner@kernel.org>
Date: Wed, 22 Apr 2026 12:41:25 +0200
Subject: [PATCH] liveupdate: allocate per-session inodes

The luo_session pseudo-fs handed every session the same singleton inode,
so fstat() on two session fds could not tell them apart. Give each
session its own inode via new_inode_pseudo(), with a unique cookie for
i_ino (and the upper bits in i_generation so 32-bit configs still get
distinct inode numbers).

Leave inode->i_fop unset. Session file descriptors must only come from
the LIVEUPDATE_IOCTL_{CREATE,RETRIEVE}_SESSION ioctls, so an unset i_fop
makes open() on /proc/<pid>/fd/N fail.

Lifetime continues to hang off file->private_data and the .release
callback; this patch only changes where the inode comes from.

Rename LUO_SESSION_MAGIC to LUO_FS_MAGIC and flip the session_fstat
selftest to assert distinct inode numbers.

Signed-off-by: Christian Brauner <brauner@kernel.org>
---
 include/uapi/linux/magic.h                    |  2 +-
 kernel/liveupdate/luo_session.c               | 59 +++++++++++++------
 .../testing/selftests/liveupdate/liveupdate.c | 13 ++--
 3 files changed, 48 insertions(+), 26 deletions(-)

diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h
index 4f51005522ff..afc3f935d00d 100644
--- a/include/uapi/linux/magic.h
+++ b/include/uapi/linux/magic.h
@@ -105,6 +105,6 @@
 #define PID_FS_MAGIC		0x50494446	/* "PIDF" */
 #define GUEST_MEMFD_MAGIC	0x474d454d	/* "GMEM" */
 #define NULL_FS_MAGIC		0x4E554C4C	/* "NULL" */
-#define LUO_SESSION_MAGIC	0x4c554f53	/* "LUOS" */
+#define LUO_FS_MAGIC		0x4c554f53	/* "LUOS" */
 
 #endif /* __LINUX_MAGIC_H__ */
diff --git a/kernel/liveupdate/luo_session.c b/kernel/liveupdate/luo_session.c
index 885e1f346caa..2484feaf102a 100644
--- a/kernel/liveupdate/luo_session.c
+++ b/kernel/liveupdate/luo_session.c
@@ -51,6 +51,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/cleanup.h>
+#include <linux/cookie.h>
 #include <linux/err.h>
 #include <linux/errno.h>
 #include <linux/file.h>
@@ -380,17 +381,43 @@ static const struct file_operations luo_session_fops = {
 };
 
 static struct vfsmount *luo_session_mnt __ro_after_init;
-static struct inode *luo_session_inode __ro_after_init;
 
-/*
- * Reject all attribute changes on the singleton session inode.
- * Without this the VFS falls back to simple_setattr(), allowing
- * fchmod()/fchown() to modify the shared inode.
- */
+DEFINE_COOKIE(luo_session_cookie);
+
+static u64 luo_session_alloc_ino(void)
+{
+	guard(preempt)();
+	return gen_cookie_next(&luo_session_cookie);
+}
+
+/* .setattr rejects attribute changes to prevent fchmod()/fchown(). */
 static const struct inode_operations luo_session_inode_operations = {
 	.setattr	= anon_inode_setattr,
 };
 
+static struct inode *luo_new_inode(struct super_block *sb)
+{
+	struct inode *inode;
+	u64 ino;
+
+	inode = new_inode_pseudo(sb);
+	if (!inode)
+		return ERR_PTR(-ENOMEM);
+
+	ino = luo_session_alloc_ino();
+	inode->i_ino		= ino;
+	inode->i_generation	= ino >> 32;
+	inode->i_flags		|= S_IMMUTABLE | S_PRIVATE | S_ANON_INODE;
+	inode->i_mode		|= S_IRUSR | S_IWUSR;
+	inode->i_uid		= current_fsuid();
+	inode->i_gid		= current_fsgid();
+	inode->i_op		= &luo_session_inode_operations;
+	/* i_fop left unset: session fds must not be reopenable via procfs. */
+	simple_inode_init_ts(inode);
+
+	return inode;
+}
+
 static char *luo_session_dname(struct dentry *dentry, char *buffer, int buflen)
 {
 	return dynamic_dname(buffer, buflen, "luo_session:[%s]",
@@ -410,7 +437,7 @@ static int luo_session_init_fs_context(struct fs_context *fc)
 {
 	struct pseudo_fs_context *ctx;
 
-	ctx = init_pseudo(fc, LUO_SESSION_MAGIC);
+	ctx = init_pseudo(fc, LUO_FS_MAGIC);
 	if (!ctx)
 		return -ENOMEM;
 
@@ -432,17 +459,20 @@ static struct file_system_type luo_session_fs_type = {
 static int luo_session_getfile(struct luo_session *session, struct file **filep)
 {
 	char name_buf[LIVEUPDATE_SESSION_NAME_LENGTH + 1];
+	struct inode *inode;
 	struct file *file;
 
 	lockdep_assert_held(&session->mutex);
 
-	ihold(luo_session_inode);
+	inode = luo_new_inode(luo_session_mnt->mnt_sb);
+	if (IS_ERR(inode))
+		return PTR_ERR(inode);
 
 	snprintf(name_buf, sizeof(name_buf), "%s", session->name);
-	file = alloc_file_pseudo(luo_session_inode, luo_session_mnt, name_buf,
+	file = alloc_file_pseudo(inode, luo_session_mnt, name_buf,
 				 O_RDWR, &luo_session_fops);
 	if (IS_ERR(file)) {
-		iput(luo_session_inode);
+		iput(inode);
 		return PTR_ERR(file);
 	}
 
@@ -731,19 +761,10 @@ int __init luo_session_fs_init(void)
 	luo_session_mnt = kern_mount(&luo_session_fs_type);
 	if (IS_ERR(luo_session_mnt))
 		panic("Cannot create LUO Session pseudo-fs");
-
-	luo_session_inode = alloc_anon_inode(luo_session_mnt->mnt_sb);
-	if (IS_ERR(luo_session_inode)) {
-		kern_unmount(luo_session_mnt);
-		return PTR_ERR(luo_session_inode);
-	}
-	luo_session_inode->i_op = &luo_session_inode_operations;
-
 	return 0;
 }
 
 void __init luo_session_fs_cleanup(void)
 {
-	iput(luo_session_inode);
 	kern_unmount(luo_session_mnt);
 }
diff --git a/tools/testing/selftests/liveupdate/liveupdate.c b/tools/testing/selftests/liveupdate/liveupdate.c
index c21354dc9b93..34f3ecb21396 100644
--- a/tools/testing/selftests/liveupdate/liveupdate.c
+++ b/tools/testing/selftests/liveupdate/liveupdate.c
@@ -410,8 +410,9 @@ TEST_F(liveupdate_device, create_session_empty_name)
  * Test Case: Session fstat
  *
  * Verifies that fstatfs() on a session file descriptor reports the
- * LUO_SESSION_MAGIC filesystem type, and that fstat() returns consistent
- * inode numbers across different sessions (shared singleton inode).
+ * LUO_FS_MAGIC filesystem type, and that fstat() returns distinct inode
+ * numbers across different sessions so userspace can compare two session
+ * file descriptors for equality using stat().
  */
 TEST_F(liveupdate_device, session_fstat)
 {
@@ -430,14 +431,14 @@ TEST_F(liveupdate_device, session_fstat)
 	session_fd2 = create_session(self->fd1, "fstat-session-2");
 	ASSERT_GE(session_fd2, 0);
 
-	/* Verify the filesystem type is LUO_SESSION_MAGIC */
+	/* Verify the filesystem type is LUO_FS_MAGIC */
 	ASSERT_EQ(fstatfs(session_fd1, &sfs), 0);
-	EXPECT_EQ(sfs.f_type, LUO_SESSION_MAGIC);
+	EXPECT_EQ(sfs.f_type, LUO_FS_MAGIC);
 
-	/* Verify both sessions share the same inode number */
+	/* Each session has its own inode, so inode numbers must differ. */
 	ASSERT_EQ(fstat(session_fd1, &st1), 0);
 	ASSERT_EQ(fstat(session_fd2, &st2), 0);
-	EXPECT_EQ(st1.st_ino, st2.st_ino);
+	EXPECT_NE(st1.st_ino, st2.st_ino);
 
 	ASSERT_EQ(close(session_fd1), 0);
 	ASSERT_EQ(close(session_fd2), 0);
-- 
2.47.3



  parent reply	other threads:[~2026-04-22 11:58 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-04-20 14:15 [PATCH v9 0/6] liveupdate: new ioctl, change session inode type, bug fixes luca.boccassi
2026-04-20 14:15 ` [PATCH v9 1/6] liveupdate: reject LIVEUPDATE_IOCTL_CREATE_SESSION with invalid name length luca.boccassi
2026-04-21 10:24   ` Mike Rapoport
2026-04-20 14:15 ` [PATCH v9 2/6] selftests/liveupdate: add test cases for LIVEUPDATE_IOCTL_CREATE_SESSION calls with invalid length luca.boccassi
2026-04-21 10:25   ` Mike Rapoport
2026-04-20 14:15 ` [PATCH v9 3/6] liveupdate: add LUO_SESSION_MAGIC magic inode type luca.boccassi
2026-04-21 10:33   ` Mike Rapoport
2026-04-22 11:58   ` Christian Brauner [this message]
2026-04-20 14:15 ` [PATCH v9 4/6] selftests/liveupdate: add test case for LUO_SESSION_MAGIC luca.boccassi
2026-04-21 10:34   ` Mike Rapoport
2026-04-20 14:15 ` [PATCH v9 5/6] liveupdate: add LIVEUPDATE_SESSION_GET_NAME ioctl luca.boccassi
2026-04-21 10:34   ` Mike Rapoport
2026-04-20 14:15 ` [PATCH v9 6/6] selftests/liveupdate: add test cases for LIVEUPDATE_SESSION_GET_NAME luca.boccassi
2026-04-21 10:34   ` Mike Rapoport

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260422-liege-klotz-cfd84db12d91@brauner \
    --to=brauner@kernel.org \
    --cc=graf@amazon.com \
    --cc=kexec@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=luca.boccassi@gmail.com \
    --cc=pasha.tatashin@soleen.com \
    --cc=pratyush@kernel.org \
    --cc=rppt@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox