From: Tarun Sahu <tarunsahu@google.com>
To: Andrew Morton <akpm@linux-foundation.org>,
joro@8bytes.org, Mike Rapoport <rppt@kernel.org>,
Pratyush Yadav <pratyush@kernel.org>,
maz@kernel.org, arnd@arndb.de,
David Matlack <dmatlack@google.com>,
jgg@nvidia.com, robin.murphy@arm.com, loganodell@google.com,
oupton@kernel.org, kevin.tian@intel.com, alex@shazbot.org,
dwmw2@infradead.org, pbonzini@redhat.com, seanjc@google.com,
will@kernel.org, Pasha Tatashin <pasha.tatashin@soleen.com>,
Alexander Graf <graf@amazon.com>,
Bjorn Helgaas <bhelgaas@google.com>,
baolu.lu@linux.intel.com
Cc: linux-arm-kernel@lists.infradead.org, linux-arch@vger.kernel.org,
sagis@google.com, linux-mm@kvack.org, kvmarm@lists.linux.dev,
iommu@lists.linux.dev, linux-pci@vger.kernel.org,
kexec@lists.infradead.org, skhawaja@google.com,
kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
Tarun Sahu <tarunsahu@google.com>
Subject: [RFC PATCH v2 2/4] liveupdate: Select file handler by name in the preserve ioctl
Date: Wed, 21 Oct 2026 15:25:25 +0000 [thread overview]
Message-ID: <20261021152527.375070-3-tarunsahu@google.com> (raw)
In-Reply-To: <20261021152527.375070-1-tarunsahu@google.com>
Currently luo_preserve_file() iterates over luo_file_handler_list and
picks the first registered handler whose .can_preserve() callback
returns true. When a subsystem introduces a new, backwards-incompatible
file handler alongside an existing one for the same file type, userspace
has no way to choose which handler preserves a file descriptor, nor can
the kernel keep the existing rollback-safe handler as the default while
allowing callers to opt into the new handler.
Append char handler[LIVEUPDATE_HNDL_NAME_LENGTH] to struct
liveupdate_session_preserve_fd immediately after token, keeping
IOCTL_OP min_size at offsetofend(..., token) so callers passing the
original 16-byte structure continue to work:
- When handler is empty (all-zero, or zero-filled when userspace
passes the 16-byte structure), luo_preserve_file() selects the first
registered handler whose .can_preserve() callback accepts the fd.
- When handler is non-empty, it must be null-terminated within
LIVEUPDATE_HNDL_NAME_LENGTH bytes (returning -EINVAL otherwise);
luo_preserve_file() looks up the registered handler with that exact
name (returning -ENOENT if unknown) and verifies that its
.can_preserve() callback accepts the fd (returning -EINVAL if not).
The retrieve ioctl is unchanged because the handler is identified by the
name stored in the serialized payload from the source kernel.
Signed-off-by: Tarun Sahu <tarunsahu@google.com>
---
include/uapi/linux/liveupdate.h | 12 +++++++++---
kernel/liveupdate/luo_file.c | 21 ++++++++++++++++++---
kernel/liveupdate/luo_internal.h | 3 ++-
kernel/liveupdate/luo_session.c | 7 ++++++-
4 files changed, 35 insertions(+), 8 deletions(-)
diff --git a/include/uapi/linux/liveupdate.h b/include/uapi/linux/liveupdate.h
index 509c6236720d..2413b19dabc1 100644
--- a/include/uapi/linux/liveupdate.h
+++ b/include/uapi/linux/liveupdate.h
@@ -126,9 +126,14 @@ struct liveupdate_ioctl_retrieve_session {
/**
* struct liveupdate_session_preserve_fd - ioctl(LIVEUPDATE_SESSION_PRESERVE_FD)
- * @size: Input; sizeof(struct liveupdate_session_preserve_fd)
- * @fd: Input; The user-space file descriptor to be preserved.
- * @token: Input; An opaque, unique token for preserved resource.
+ * @size: Input; sizeof(struct liveupdate_session_preserve_fd)
+ * @fd: Input; The user-space file descriptor to be preserved.
+ * @token: Input; An opaque, unique token for preserved resource.
+ * @handler: Input; Optional null-terminated file handler name (max length
+ * %LIVEUPDATE_HNDL_NAME_LENGTH including null terminator) selecting
+ * which registered handler preserves @fd. If empty (all-zero, or
+ * omitted when passing the 16-byte structure), the kernel selects
+ * the first registered handler whose .can_preserve() accepts @fd.
*
* Holds parameters for preserving a file descriptor.
*
@@ -152,6 +157,7 @@ struct liveupdate_session_preserve_fd {
__u32 size;
__s32 fd;
__aligned_u64 token;
+ char handler[LIVEUPDATE_HNDL_NAME_LENGTH];
};
#define LIVEUPDATE_SESSION_PRESERVE_FD \
diff --git a/kernel/liveupdate/luo_file.c b/kernel/liveupdate/luo_file.c
index fb81239bedf3..be20e0f1e0aa 100644
--- a/kernel/liveupdate/luo_file.c
+++ b/kernel/liveupdate/luo_file.c
@@ -207,6 +207,8 @@ static bool luo_token_is_used(struct luo_file_set *file_set, u64 token)
* @file_set: The file_set to which the preserved file will be added.
* @token: A unique, user-provided identifier for the file.
* @fd: The file descriptor to be preserved.
+ * @handler: Optional NUL-terminated handler name. If NULL or empty, the first
+ * registered handler whose .can_preserve() accepts @fd is selected.
*
* This function orchestrates the first phase of preserving a file. Upon entry,
* it takes a reference to the 'struct file' via fget(), effectively making LUO
@@ -238,11 +240,13 @@ static bool luo_token_is_used(struct luo_file_set *file_set, u64 token)
* -EBUSY if the file descriptor is already preserved by another session.
* -EBADF if the file descriptor is invalid.
* -ENOSPC if the file_set is full.
- * -ENOENT if no compatible handler is found for the file type.
+ * -ENOENT if no matching handler is registered or accepts @fd.
+ * -EINVAL if the named handler cannot preserve @fd.
* -ENOMEM on memory allocation failure.
* Other erros might be returned by .preserve().
*/
-int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd)
+int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd,
+ const char *handler)
{
struct liveupdate_file_op_args args = {0};
struct liveupdate_file_handler *fh;
@@ -266,6 +270,18 @@ int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd)
err = -ENOENT;
down_read(&luo_register_rwlock);
list_private_for_each_entry(fh, &luo_file_handler_list, list) {
+ if (handler && handler[0]) {
+ if (strcmp(fh->name, handler))
+ continue;
+ if (!fh->ops->can_preserve(fh, file)) {
+ err = -EINVAL;
+ break;
+ }
+ if (try_module_get(fh->ops->owner))
+ err = 0;
+ break;
+ }
+
if (fh->ops->can_preserve(fh, file)) {
if (try_module_get(fh->ops->owner))
err = 0;
@@ -274,7 +290,6 @@ int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd)
}
up_read(&luo_register_rwlock);
- /* err is still -ENOENT if no handler was found */
if (err)
goto err_fput;
diff --git a/kernel/liveupdate/luo_internal.h b/kernel/liveupdate/luo_internal.h
index dac6644bfb18..911ffedec9f3 100644
--- a/kernel/liveupdate/luo_internal.h
+++ b/kernel/liveupdate/luo_internal.h
@@ -101,7 +101,8 @@ int __init luo_session_setup_incoming(u64 sessions_pa);
int luo_session_serialize(void);
int luo_session_deserialize(void);
-int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd);
+int luo_preserve_file(struct luo_file_set *file_set, u64 token, int fd,
+ const char *handler);
void luo_file_unpreserve_files(struct luo_file_set *file_set);
int luo_file_freeze(struct luo_file_set *file_set,
struct luo_file_set_ser *file_set_ser);
diff --git a/kernel/liveupdate/luo_session.c b/kernel/liveupdate/luo_session.c
index f48e9a4185f9..194ef45907c1 100644
--- a/kernel/liveupdate/luo_session.c
+++ b/kernel/liveupdate/luo_session.c
@@ -266,8 +266,13 @@ static int luo_session_preserve_fd(struct luo_session *session,
struct liveupdate_session_preserve_fd *argp = ucmd->cmd;
int err;
+ if (strnlen(argp->handler, sizeof(argp->handler)) ==
+ sizeof(argp->handler))
+ return -EINVAL;
+
guard(mutex)(&session->mutex);
- err = luo_preserve_file(&session->file_set, argp->token, argp->fd);
+ err = luo_preserve_file(&session->file_set, argp->token, argp->fd,
+ argp->handler);
if (err)
return err;
--
2.56.0.212.g129ede20d9-goog
next prev parent reply other threads:[~2026-10-21 15:25 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-21 15:25 [RFC PATCH v2 0/4] liveupdate: Feature header ABI and named handler Tarun Sahu
2026-10-21 15:25 ` [RFC PATCH v2 1/4] liveupdate: Rename handler compatible to name Tarun Sahu
2026-10-21 15:25 ` Tarun Sahu [this message]
2026-10-21 15:25 ` [RFC PATCH v2 3/4] liveupdate: Replace compatibility string with a 2-bit pair feature header Tarun Sahu
2026-10-21 15:25 ` [RFC PATCH v2 4/4] mm: memfd_luo: Add the " Tarun Sahu
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=20261021152527.375070-3-tarunsahu@google.com \
--to=tarunsahu@google.com \
--cc=akpm@linux-foundation.org \
--cc=alex@shazbot.org \
--cc=arnd@arndb.de \
--cc=baolu.lu@linux.intel.com \
--cc=bhelgaas@google.com \
--cc=dmatlack@google.com \
--cc=dwmw2@infradead.org \
--cc=graf@amazon.com \
--cc=iommu@lists.linux.dev \
--cc=jgg@nvidia.com \
--cc=joro@8bytes.org \
--cc=kevin.tian@intel.com \
--cc=kexec@lists.infradead.org \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arch@vger.kernel.org \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=linux-pci@vger.kernel.org \
--cc=loganodell@google.com \
--cc=maz@kernel.org \
--cc=oupton@kernel.org \
--cc=pasha.tatashin@soleen.com \
--cc=pbonzini@redhat.com \
--cc=pratyush@kernel.org \
--cc=robin.murphy@arm.com \
--cc=rppt@kernel.org \
--cc=sagis@google.com \
--cc=seanjc@google.com \
--cc=skhawaja@google.com \
--cc=will@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
all inboxes | Powered by JetHome®