Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

liveupdate: prevent double management of files

Patch series "liveupdate: prevent double preservation", v4.

Currently, LUO does not prevent the same file from being managed twice
across different active sessions.

Because LUO preserves files of absolutely different types: memfd, and
upcoming vfiofd [1], iommufd [2], guestmefd (and possible kvmfd/cpufd).
There is no common private data or guarantee on how to prevent that the
same file is not preserved twice beside using inode or some slower and
expensive method like hashtables.


This patch (of 4)

Currently, LUO does not prevent the same file from being managed twice
across different active sessions.

Use a global xarray luo_preserved_files to keep track of file identifiers
being preserved by LUO. Update luo_preserve_file() to check and insert
the file identifier into this xarray when it is preserved, and erase it in
luo_file_unpreserve_files() when it is released.

To allow handlers to define what constitutes a "unique" file (e.g.,
different struct file objects pointing to the same hardware resource), add
a get_id() callback to struct liveupdate_file_ops. If not provided, the
default identifier is the struct file pointer itself.

This ensures that the same file (or resource) cannot be managed by
multiple sessions. If another session attempts to preserve an already
managed file, it will now fail with -EBUSY.

Link: https://lore.kernel.org/20260326163943.574070-1-pasha.tatashin@soleen.com
Link: https://lore.kernel.org/20260326163943.574070-2-pasha.tatashin@soleen.com
Link: https://lore.kernel.org/all/20260129212510.967611-1-dmatlack@google.com [1]
Link: https://lore.kernel.org/all/20260203220948.2176157-1-skhawaja@google.com [2]
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
Reviewed-by: Samiullah Khawaja <skhawaja@google.com>
Reviewed-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
Cc: David Matlack <dmatlack@google.com>
Cc: Pratyush Yadav <pratyush@kernel.org>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Christian Brauner <brauner@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Pasha Tatashin and committed by
Andrew Morton
00d0b372 e524feaa

+32 -2
+2
include/linux/liveupdate.h
··· 63 63 * finish, in order to do successful finish calls for all 64 64 * resources in the session. 65 65 * @finish: Required. Final cleanup in the new kernel. 66 + * @get_id: Optional. Returns a unique identifier for the file. 66 67 * @owner: Module reference 67 68 * 68 69 * All operations (except can_preserve) receive a pointer to a ··· 79 78 int (*retrieve)(struct liveupdate_file_op_args *args); 80 79 bool (*can_finish)(struct liveupdate_file_op_args *args); 81 80 void (*finish)(struct liveupdate_file_op_args *args); 81 + unsigned long (*get_id)(struct file *file); 82 82 struct module *owner; 83 83 }; 84 84
+30 -2
kernel/liveupdate/luo_file.c
··· 108 108 #include <linux/liveupdate.h> 109 109 #include <linux/module.h> 110 110 #include <linux/sizes.h> 111 + #include <linux/xarray.h> 111 112 #include <linux/slab.h> 112 113 #include <linux/string.h> 113 114 #include "luo_internal.h" 114 115 115 116 static LIST_HEAD(luo_file_handler_list); 117 + 118 + /* Keep track of files being preserved by LUO */ 119 + static DEFINE_XARRAY(luo_preserved_files); 116 120 117 121 /* 2 4K pages, give space for 128 files per file_set */ 118 122 #define LUO_FILE_PGCNT 2ul ··· 207 203 file_set->files = NULL; 208 204 } 209 205 206 + static unsigned long luo_get_id(struct liveupdate_file_handler *fh, 207 + struct file *file) 208 + { 209 + return fh->ops->get_id ? fh->ops->get_id(file) : (unsigned long)file; 210 + } 211 + 210 212 static bool luo_token_is_used(struct luo_file_set *file_set, u64 token) 211 213 { 212 214 struct luo_file *iter; ··· 258 248 * Context: Can be called from an ioctl handler during normal system operation. 259 249 * Return: 0 on success. Returns a negative errno on failure: 260 250 * -EEXIST if the token is already used. 251 + * -EBUSY if the file descriptor is already preserved by another session. 261 252 * -EBADF if the file descriptor is invalid. 262 253 * -ENOSPC if the file_set is full. 263 254 * -ENOENT if no compatible handler is found. ··· 299 288 if (err) 300 289 goto err_free_files_mem; 301 290 302 - err = luo_flb_file_preserve(fh); 291 + err = xa_insert(&luo_preserved_files, luo_get_id(fh, file), 292 + file, GFP_KERNEL); 303 293 if (err) 304 294 goto err_free_files_mem; 295 + 296 + err = luo_flb_file_preserve(fh); 297 + if (err) 298 + goto err_erase_xa; 305 299 306 300 luo_file = kzalloc_obj(*luo_file); 307 301 if (!luo_file) { ··· 336 320 kfree(luo_file); 337 321 err_flb_unpreserve: 338 322 luo_flb_file_unpreserve(fh); 323 + err_erase_xa: 324 + xa_erase(&luo_preserved_files, luo_get_id(fh, file)); 339 325 err_free_files_mem: 340 326 luo_free_files_mem(file_set); 341 327 err_fput: ··· 381 363 luo_file->fh->ops->unpreserve(&args); 382 364 luo_flb_file_unpreserve(luo_file->fh); 383 365 366 + xa_erase(&luo_preserved_files, 367 + luo_get_id(luo_file->fh, luo_file->file)); 384 368 list_del(&luo_file->list); 385 369 file_set->count--; 386 370 ··· 626 606 luo_file->file = args.file; 627 607 /* Get reference so we can keep this file in LUO until finish */ 628 608 get_file(luo_file->file); 609 + 610 + WARN_ON(xa_insert(&luo_preserved_files, 611 + luo_get_id(luo_file->fh, luo_file->file), 612 + luo_file->file, GFP_KERNEL)); 613 + 629 614 *filep = luo_file->file; 630 615 luo_file->retrieve_status = 1; 631 616 ··· 726 701 727 702 luo_file_finish_one(file_set, luo_file); 728 703 729 - if (luo_file->file) 704 + if (luo_file->file) { 705 + xa_erase(&luo_preserved_files, 706 + luo_get_id(luo_file->fh, luo_file->file)); 730 707 fput(luo_file->file); 708 + } 731 709 list_del(&luo_file->list); 732 710 file_set->count--; 733 711 mutex_destroy(&luo_file->mutex);