File handlers do not need to pin modules indefinitely or during active
live update sessions. The VFS 'struct file' pins the file handler's module
via f_op->owner during active sessions, making dynamic reference counting
unnecessary for handlers.
When a file is preserved, the live update core obtains a 'struct file'
via fdget(). As long as the file is kept open within the live update
session, the module is pinned by the VFS and cannot be unloaded.
Similarly, during deserialization, file handlers are matched based on
the compatible string. Because the handler list is protected by
luo_file_handler_lock, there is no race that requires dynamic
module refcounting.
Removing these module references ensures that modules implementing file
handlers can be unloaded when no longer providing active files.
Suggested-by: David Matlack <dmatlack@google.com>
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
---
kernel/liveupdate/luo_file.c | 28 +++++++---------------------
1 file changed, 7 insertions(+), 21 deletions(-)
diff --git a/kernel/liveupdate/luo_file.c b/kernel/liveupdate/luo_file.c
index 96fdd5790dcc..b124fd747841 100644
--- a/kernel/liveupdate/luo_file.c
+++ b/kernel/liveupdate/luo_file.c
@@ -836,7 +836,6 @@ void luo_file_set_destroy(struct luo_file_set *file_set)
int liveupdate_register_file_handler(struct liveupdate_file_handler *fh)
{
struct liveupdate_file_handler *fh_iter;
- int err;
if (!liveupdate_enabled())
return -EOPNOTSUPP;
@@ -861,17 +860,11 @@ int liveupdate_register_file_handler(struct liveupdate_file_handler *fh)
if (!strcmp(fh_iter->compatible, fh->compatible)) {
pr_err("File handler registration failed: Compatible string '%s' already registered.\n",
fh->compatible);
- err = -EEXIST;
- goto err_resume;
+ luo_session_resume();
+ return -EEXIST;
}
}
- /* Pin the module implementing the handler */
- if (!try_module_get(fh->ops->owner)) {
- err = -EAGAIN;
- goto err_resume;
- }
-
INIT_LIST_HEAD(&ACCESS_PRIVATE(fh, flb_list));
init_rwsem(&ACCESS_PRIVATE(fh, flb_lock));
INIT_LIST_HEAD(&ACCESS_PRIVATE(fh, list));
@@ -882,10 +875,6 @@ int liveupdate_register_file_handler(struct liveupdate_file_handler *fh)
liveupdate_test_register(fh);
return 0;
-
-err_resume:
- luo_session_resume();
- return err;
}
/**
@@ -907,8 +896,6 @@ int liveupdate_register_file_handler(struct liveupdate_file_handler *fh)
*/
int liveupdate_unregister_file_handler(struct liveupdate_file_handler *fh)
{
- int err = -EBUSY;
-
if (!liveupdate_enabled())
return -EOPNOTSUPP;
@@ -918,19 +905,18 @@ int liveupdate_unregister_file_handler(struct liveupdate_file_handler *fh)
goto err_register;
scoped_guard(rwsem_write, &luo_file_handler_lock) {
- if (!list_empty(&ACCESS_PRIVATE(fh, flb_list)))
- goto err_resume;
+ if (!list_empty(&ACCESS_PRIVATE(fh, flb_list))) {
+ luo_session_resume();
+ goto err_register;
+ }
list_del(&ACCESS_PRIVATE(fh, list));
}
- module_put(fh->ops->owner);
luo_session_resume();
return 0;
-err_resume:
- luo_session_resume();
err_register:
liveupdate_test_register(fh);
- return err;
+ return -EBUSY;
}
--
2.53.0.851.ga537e3e6e9-goog
On Wed, Mar 18, 2026 at 7:17 AM Pasha Tatashin <pasha.tatashin@soleen.com> wrote: > > File handlers do not need to pin modules indefinitely or during active > live update sessions. The VFS 'struct file' pins the file handler's module > via f_op->owner during active sessions, making dynamic reference counting > unnecessary for handlers. > > When a file is preserved, the live update core obtains a 'struct file' > via fdget(). As long as the file is kept open within the live update > session, the module is pinned by the VFS and cannot be unloaded. After invoking the file handler's retrieve(), LUO should probably check that the created file's owner matches the file handler's owner, since this scheme relies on that being true. If there is a mismatch, LUO can put the file that was just created, log a warning, and return an error up to the user.
On Tue, Mar 24, 2026 at 5:24 PM David Matlack <dmatlack@google.com> wrote: > > On Wed, Mar 18, 2026 at 7:17 AM Pasha Tatashin > <pasha.tatashin@soleen.com> wrote: > > > > File handlers do not need to pin modules indefinitely or during active > > live update sessions. The VFS 'struct file' pins the file handler's module > > via f_op->owner during active sessions, making dynamic reference counting > > unnecessary for handlers. > > > > When a file is preserved, the live update core obtains a 'struct file' > > via fdget(). As long as the file is kept open within the live update > > session, the module is pinned by the VFS and cannot be unloaded. > > After invoking the file handler's retrieve(), LUO should probably > check that the created file's owner matches the file handler's owner, > since this scheme relies on that being true. > > If there is a mismatch, LUO can put the file that was just created, > log a warning, and return an error up to the user. Is there a reason why taking a file handler module reference is problematic for vfio or iommu? Could we take it while files are present in incoming or outgoing sessions? Overall, it is because it cover corener cases such as if the file struct owner is the same as LUO file handler and also this approach covers the deserialziation side nicely. Pasha
On Tue, Mar 24, 2026 at 7:49 PM Pasha Tatashin <pasha.tatashin@soleen.com> wrote: > > On Tue, Mar 24, 2026 at 5:24 PM David Matlack <dmatlack@google.com> wrote: > > > > On Wed, Mar 18, 2026 at 7:17 AM Pasha Tatashin > > <pasha.tatashin@soleen.com> wrote: > > > > > > File handlers do not need to pin modules indefinitely or during active > > > live update sessions. The VFS 'struct file' pins the file handler's module > > > via f_op->owner during active sessions, making dynamic reference counting > > > unnecessary for handlers. > > > > > > When a file is preserved, the live update core obtains a 'struct file' > > > via fdget(). As long as the file is kept open within the live update > > > session, the module is pinned by the VFS and cannot be unloaded. > > > > After invoking the file handler's retrieve(), LUO should probably > > check that the created file's owner matches the file handler's owner, > > since this scheme relies on that being true. > > > > If there is a mismatch, LUO can put the file that was just created, > > log a warning, and return an error up to the user. > > Is there a reason why taking a file handler module reference is > problematic for vfio or iommu? Could we take it while files are > present in incoming or outgoing sessions? Overall, it is because it > cover corener cases such as if the file struct owner is the same as > LUO file handler and also this approach covers the deserialziation > side nicely. I see no problem with LUO taking a reference to the file handle module owner while a file associated with it is preserved in an incoming or outgoing session. And I realized that VFIO can have different owners for the file (vfio module) and file handler (vfio-pci module), as it is currently implemented. It should still be safe to rely on the file reference, but explicitly taking a reference to the file handler would be simpler to reason about. So I am ok with going back to what you had in v1 [1]. [1] https://lore.kernel.org/lkml/20260317025049.494931-4-pasha.tatashin@soleen.com/
On Wed, Mar 25, 2026 at 9:15 AM David Matlack <dmatlack@google.com> wrote: > > On Tue, Mar 24, 2026 at 7:49 PM Pasha Tatashin > <pasha.tatashin@soleen.com> wrote: > > > > On Tue, Mar 24, 2026 at 5:24 PM David Matlack <dmatlack@google.com> wrote: > > > > > > On Wed, Mar 18, 2026 at 7:17 AM Pasha Tatashin > > > <pasha.tatashin@soleen.com> wrote: > > > > > > > > File handlers do not need to pin modules indefinitely or during active > > > > live update sessions. The VFS 'struct file' pins the file handler's module > > > > via f_op->owner during active sessions, making dynamic reference counting > > > > unnecessary for handlers. > > > > > > > > When a file is preserved, the live update core obtains a 'struct file' > > > > via fdget(). As long as the file is kept open within the live update > > > > session, the module is pinned by the VFS and cannot be unloaded. > > > > > > After invoking the file handler's retrieve(), LUO should probably > > > check that the created file's owner matches the file handler's owner, > > > since this scheme relies on that being true. > > > > > > If there is a mismatch, LUO can put the file that was just created, > > > log a warning, and return an error up to the user. > > > > Is there a reason why taking a file handler module reference is > > problematic for vfio or iommu? Could we take it while files are > > present in incoming or outgoing sessions? Overall, it is because it > > cover corener cases such as if the file struct owner is the same as > > LUO file handler and also this approach covers the deserialziation > > side nicely. > > I see no problem with LUO taking a reference to the file handle module > owner while a file associated with it is preserved in an incoming or > outgoing session. > > And I realized that VFIO can have different owners for the file (vfio > module) and file handler (vfio-pci module), as it is currently > implemented. It should still be safe to rely on the file reference, > but explicitly taking a reference to the file handler would be simpler > to reason about. So I am ok with going back to what you had in v1 [1]. Great, I will include this in v3, together with Sami's suggestion for lock simplifications. Pasha > > [1] https://lore.kernel.org/lkml/20260317025049.494931-4-pasha.tatashin@soleen.com/
On 2026-03-18 10:16 AM, Pasha Tatashin wrote: > File handlers do not need to pin modules indefinitely or during active > live update sessions. The VFS 'struct file' pins the file handler's module > via f_op->owner during active sessions, making dynamic reference counting > unnecessary for handlers. > > When a file is preserved, the live update core obtains a 'struct file' > via fdget(). As long as the file is kept open within the live update > session, the module is pinned by the VFS and cannot be unloaded. > > Similarly, during deserialization, file handlers are matched based on > the compatible string. Because the handler list is protected by > luo_file_handler_lock, there is no race that requires dynamic > module refcounting. Sashiko found a potential bug here when reviewing my VFIO patch series: . If luo_file_deserialize() reconstructs preserved file structures and . assigns the handler to luo_file->fh without calling try_module_get() . to lock the module in memory, could the module be unloaded before the . file descriptor is actually retrieved? . . This would cause liveupdate_unregister_file_handler() to run on module exit. . If userspace subsequently calls luo_retrieve_file(), could it result . in a use-after-free by dereferencing the dangling luo_file->fh->ops pointer? https://sashiko.dev/#/patchset/20260323235817.1960573-1-dmatlack%40google.com?patch=7973 I think LUO would need to take a module reference in luo_file_deserialize() and drop it once the file is retrieved. At that point LUO can rely on the file's reference to the module to keep it from being unloaded while LUO still has references to it.
© 2016 - 2026 Red Hat, Inc.