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: protect file handler list with rwsem

Because liveupdate file handlers will no longer hold a module reference
when registered, we must ensure that the access to the handler list is
protected against concurrent module unloading.

Utilize the global luo_register_rwlock to protect the global registry of
file handlers. Read locks are taken during list traversals in
luo_preserve_file() and luo_file_deserialize(). Write locks are taken
during registration and unregistration.

Link: https://lore.kernel.org/20260327033335.696621-4-pasha.tatashin@soleen.com
Signed-off-by: Pasha Tatashin <pasha.tatashin@soleen.com>
Reviewed-by: Pratyush Yadav (Google) <pratyush@kernel.org>
Cc: David Matlack <dmatlack@google.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Samiullah Khawaja <skhawaja@google.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>

authored by

Pasha Tatashin and committed by
Andrew Morton
9e1e1858 38fb71ac

+25 -5
+6
kernel/liveupdate/luo_core.c
··· 54 54 #include <linux/liveupdate.h> 55 55 #include <linux/miscdevice.h> 56 56 #include <linux/mm.h> 57 + #include <linux/rwsem.h> 57 58 #include <linux/sizes.h> 58 59 #include <linux/string.h> 59 60 #include <linux/unaligned.h> ··· 68 67 void *fdt_in; 69 68 u64 liveupdate_num; 70 69 } luo_global; 70 + 71 + /* 72 + * luo_register_rwlock - Protects registration of file handlers and FLBs. 73 + */ 74 + DECLARE_RWSEM(luo_register_rwlock); 71 75 72 76 static int __init early_liveupdate_param(char *buf) 73 77 {
+17 -5
kernel/liveupdate/luo_file.c
··· 288 288 goto err_fput; 289 289 290 290 err = -ENOENT; 291 + down_read(&luo_register_rwlock); 291 292 list_private_for_each_entry(fh, &luo_file_handler_list, list) { 292 293 if (fh->ops->can_preserve(fh, file)) { 293 294 err = 0; 294 295 break; 295 296 } 296 297 } 298 + up_read(&luo_register_rwlock); 297 299 298 300 /* err is still -ENOENT if no handler was found */ 299 301 if (err) ··· 807 805 bool handler_found = false; 808 806 struct luo_file *luo_file; 809 807 808 + down_read(&luo_register_rwlock); 810 809 list_private_for_each_entry(fh, &luo_file_handler_list, list) { 811 810 if (!strcmp(fh->compatible, file_ser[i].compatible)) { 812 811 handler_found = true; 813 812 break; 814 813 } 815 814 } 815 + up_read(&luo_register_rwlock); 816 816 817 817 if (!handler_found) { 818 818 pr_warn("No registered handler for compatible '%.*s'\n", ··· 883 879 if (!luo_session_quiesce()) 884 880 return -EBUSY; 885 881 882 + down_write(&luo_register_rwlock); 886 883 /* Check for duplicate compatible strings */ 887 884 list_private_for_each_entry(fh_iter, &luo_file_handler_list, list) { 888 885 if (!strcmp(fh_iter->compatible, fh->compatible)) { 889 886 pr_err("File handler registration failed: Compatible string '%s' already registered.\n", 890 887 fh->compatible); 891 888 err = -EEXIST; 892 - goto err_resume; 889 + goto err_unlock; 893 890 } 894 891 } 895 892 896 893 /* Pin the module implementing the handler */ 897 894 if (!try_module_get(fh->ops->owner)) { 898 895 err = -EAGAIN; 899 - goto err_resume; 896 + goto err_unlock; 900 897 } 901 898 902 899 INIT_LIST_HEAD(&ACCESS_PRIVATE(fh, flb_list)); 903 900 INIT_LIST_HEAD(&ACCESS_PRIVATE(fh, list)); 904 901 list_add_tail(&ACCESS_PRIVATE(fh, list), &luo_file_handler_list); 902 + up_write(&luo_register_rwlock); 903 + 905 904 luo_session_resume(); 906 905 907 906 liveupdate_test_register(fh); 908 907 909 908 return 0; 910 909 911 - err_resume: 910 + err_unlock: 911 + up_write(&luo_register_rwlock); 912 912 luo_session_resume(); 913 913 return err; 914 914 } ··· 946 938 if (!luo_session_quiesce()) 947 939 goto err_register; 948 940 941 + down_write(&luo_register_rwlock); 949 942 if (!list_empty(&ACCESS_PRIVATE(fh, flb_list))) 950 - goto err_resume; 943 + goto err_unlock; 951 944 952 945 list_del(&ACCESS_PRIVATE(fh, list)); 946 + up_write(&luo_register_rwlock); 947 + 953 948 module_put(fh->ops->owner); 954 949 luo_session_resume(); 955 950 956 951 return 0; 957 952 958 - err_resume: 953 + err_unlock: 954 + up_write(&luo_register_rwlock); 959 955 luo_session_resume(); 960 956 err_register: 961 957 liveupdate_test_register(fh);
+2
kernel/liveupdate/luo_internal.h
··· 77 77 struct mutex mutex; 78 78 }; 79 79 80 + extern struct rw_semaphore luo_register_rwlock; 81 + 80 82 int luo_session_create(const char *name, struct file **filep); 81 83 int luo_session_retrieve(const char *name, struct file **filep); 82 84 int __init luo_session_setup_outgoing(void *fdt);