Re: [PATCH v3 01/10] liveupdate: Pass user argument to file preserve and retrieve

From: Pratyush Yadav

Date: Wed Nov 04 2026 - 08:23:29 EST


Hi David,

On Tue, Nov 03 2026, David Matlack wrote:

> From: Pasha Tatashin <pasha.tatashin@xxxxxxxxxx>
>
> Allow userspace to pass a file-handler-specific argument structure when
> preserving or retrieving an FD via LUO. File handlers may need
> additional context during preservation or retrieval, such as a target
> FD, device location, or handler-specific parameters, without introducing
> separate ioctls for each file type. Whether the argument is required,
> optional, or unused is defined by the file handler.
>
> Extend struct liveupdate_session_preserve_fd and
> struct liveupdate_session_retrieve_fd with a 64-bit arg field pointing
> to a handler-defined argument structure that begins with a 32-bit size
> field. Because IOCTL_OP validates a minimum size up to the token field,
> existing callers passing the 16-byte struct remain compatible and have
> arg zero-filled by copy_struct_from_user().
>
> Add parg and rarg (struct liveupdate_arg_spec) to
> struct liveupdate_file_ops, initialized via LIVEUPDATE_ARG(_struct,
> _min_last), which records the full struct size and minimum required size
> while enforcing at compile time that handler argument structures begin
> with a 32-bit size field. When arg is non-zero, LUO validates the
> minimum size and copies the user argument via copy_struct_from_user() up
> to the handler's expected size and passes the kernel copy in
> struct liveupdate_file_op_args, or returns -EOPNOTSUPP if the handler
> does not accept an argument.
>
> The argument only applies to the retrieve that restores the file.
> Retrieving a token that was already retrieved returns the existing file,
> so fail with -EBUSY if a non-zero argument is passed then, instead of
> silently ignoring it.
>
> Signed-off-by: Pasha Tatashin <pasha.tatashin@xxxxxxxxxx>
> Signed-off-by: David Matlack <dmatlack@xxxxxxxxxx>

LGTM for the most part, only a couple nitpicks below.

[...]
> @@ -173,12 +178,17 @@ struct liveupdate_session_preserve_fd {
> * attempts to retrieve the token fail with the same error code. Failed
> * retrieves are not retried.
> *
> + * Retrieving a token that was already retrieved successfully returns a new file
> + * descriptor for the same file. The @arg only applies to the retrieve that
> + * restores the file, so passing a non-zero @arg then fails with -EBUSY.
> + *

Hmm, let's see how that plays out in practice. I would guess that code
which does multiple retrieves isn't smart enough to know the file was
already retrieved by someone else.

Anyway, that's not really a kernel problem, so no need to change
anything. Just thinking out loud.

[...]
> /**
> * luo_preserve_file - Initiate the preservation of a file descriptor.
> * @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.
> + * @arg: User-space pointer to the handler argument structure, or 0.
> *
> * 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
> @@ -222,9 +257,11 @@ static bool luo_token_is_used(struct luo_file_set *file_set, u64 token)
> * (allocates if needed).
> * 3. Iterates through registered handlers, calling can_preserve() to find one
> * compatible with the given @fd.
> - * 4. Calls the handler's .preserve() operation, which saves the file's state
> + * 4. Copies the user argument structure (if @arg is non-zero) according to the
> + * handler's parg specification.
> + * 5. Calls the handler's .preserve() operation, which saves the file's state
> * and returns an opaque private data handle.
> - * 5. Adds the new instance to the file_set's internal list.
> + * 6. Adds the new instance to the file_set's internal list.

TBH, I think this whole list is pointless. There is no reason to list
what the code does in a comment. It's only purpose would be to go stale.
The comment should be a high level description of the function, and the
details are already in the code.

It would be very nice if you add a preparatory patch deleting the whole
thing, but since it isn't something added by your patch, I won't insist
on it. It's optional for this series.

> *
> * On success, LUO takes a reference to the 'struct file' and considers it
> * under its management until it is unpreserved or finished.
> @@ -239,10 +276,12 @@ static bool luo_token_is_used(struct luo_file_set *file_set, u64 token)
> * -EBADF if the file descriptor is invalid.
> * -ENOSPC if the file_set is full.
> * -ENOENT if no compatible handler is found.
> + * -EOPNOTSUPP if @arg is non-zero and the handler does not accept an arg.
> * -ENOMEM on memory allocation failure.
> * Other erros might be returned by .preserve().
> */
[...]
> diff --git a/kernel/liveupdate/luo_session.c b/kernel/liveupdate/luo_session.c
> index f48e9a4185f9..ed9d53c7db77 100644
> --- a/kernel/liveupdate/luo_session.c
> +++ b/kernel/liveupdate/luo_session.c
> @@ -267,7 +267,8 @@ static int luo_session_preserve_fd(struct luo_session *session,
> int err;
>
> 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->arg);

Nit: I would prefer to start marking this as __user from here on out,
instead of keeping it u64 and hiding the fact that this is a user
pointer.

So luo_preserve_file() should take a "const void __user *arg" as
argument, instead of "u64 arg". And here we should pass
u64_to_user_ptr(argp->arg). Same for retrieve.

> if (err)
> return err;
>
> @@ -290,7 +291,8 @@ static int luo_session_retrieve_fd(struct luo_session *session,
> return argp->fd;
>
> mutex_lock(&session->mutex);
> - err = luo_retrieve_file(&session->file_set, argp->token, &file);
> + err = luo_retrieve_file(&session->file_set, argp->token, argp->arg,
> + &file);
> mutex_unlock(&session->mutex);
> if (err < 0)
> goto err_put_fd;

--
Regards,
Pratyush Yadav