From ee5c416f208a048c87025f40b914981b0b287947 Mon Sep 17 00:00:00 2001 From: wuguanghao Date: Fri, 17 Jul 2026 09:48:08 +0800 Subject: [PATCH] udev: prevent interruption by thread cancellation Using mutexes only guarantees no concurrency during normal runtime. However, if a thread is cancelled mid-execution, a libudev API call might be interrupted halfway (partially executed), leaving memory values in an inconsistent or abnormal state. Furthermore, this change aligns with the requirement that libudev interfaces are not thread-safe and must not be called from multiple threads. Signed-off-by: Wu Guanghao --- libmpathutil/mt-libudev.c | 121 +++++++++++++++++++++----------------- 1 file changed, 66 insertions(+), 55 deletions(-) diff --git a/libmpathutil/mt-libudev.c b/libmpathutil/mt-libudev.c index 2e37c7d9d..1667673b9 100644 --- a/libmpathutil/mt-libudev.c +++ b/libmpathutil/mt-libudev.c @@ -3,6 +3,16 @@ #include #include "util.h" +#define MT_NO_CANCEL(call) \ + ({ \ + int __oldstate; \ + pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &__oldstate); \ + __typeof__(call) __ret = (call); \ + pthread_setcancelstate(__oldstate, NULL); \ + pthread_testcancel(); \ + __ret; \ + }) + static pthread_mutex_t libudev_mutex = PTHREAD_MUTEX_INITIALIZER; struct udev *mt_udev_ref(struct udev *udev) @@ -12,7 +22,7 @@ struct udev *mt_udev_ref(struct udev *udev) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_ref(udev); + ret = MT_NO_CANCEL((udev_ref)(udev)); pthread_cleanup_pop(1); return ret; @@ -25,7 +35,7 @@ struct udev *mt_udev_unref(struct udev *udev) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_unref(udev); + ret = MT_NO_CANCEL((udev_unref)(udev)); pthread_cleanup_pop(1); return ret; @@ -38,7 +48,7 @@ struct udev *mt_udev_new(void) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_new(); + ret = MT_NO_CANCEL((udev_new)()); pthread_cleanup_pop(1); return ret; @@ -51,7 +61,7 @@ struct udev_list_entry *mt_udev_list_entry_get_next(struct udev_list_entry *list pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_list_entry_get_next(list_entry); + ret = MT_NO_CANCEL((udev_list_entry_get_next)(list_entry)); pthread_cleanup_pop(1); return ret; @@ -65,7 +75,7 @@ mt_udev_list_entry_get_by_name(struct udev_list_entry *list_entry, const char *n pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_list_entry_get_by_name(list_entry, name); + ret = MT_NO_CANCEL((udev_list_entry_get_by_name)(list_entry, name)); pthread_cleanup_pop(1); return ret; @@ -78,7 +88,7 @@ const char *mt_udev_list_entry_get_name(struct udev_list_entry *list_entry) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_list_entry_get_name(list_entry); + ret = MT_NO_CANCEL((udev_list_entry_get_name)(list_entry)); pthread_cleanup_pop(1); return ret; @@ -91,7 +101,7 @@ const char *mt_udev_list_entry_get_value(struct udev_list_entry *list_entry) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_list_entry_get_value(list_entry); + ret = MT_NO_CANCEL((udev_list_entry_get_value)(list_entry)); pthread_cleanup_pop(1); return ret; @@ -105,7 +115,7 @@ mt_udev_device_new_from_syspath(struct udev *udev, const char *syspath) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_device_new_from_syspath(udev, syspath); + ret = MT_NO_CANCEL((udev_device_new_from_syspath)(udev, syspath)); pthread_cleanup_pop(1); return ret; @@ -119,7 +129,7 @@ mt_udev_device_new_from_devnum(struct udev *udev, char type, dev_t devnum) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_device_new_from_devnum(udev, type, devnum); + ret = MT_NO_CANCEL((udev_device_new_from_devnum)(udev, type, devnum)); pthread_cleanup_pop(1); return ret; @@ -134,7 +144,8 @@ mt_udev_device_new_from_subsystem_sysname(struct udev *udev, const char *subsyst pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_device_new_from_subsystem_sysname(udev, subsystem, sysname); + ret = MT_NO_CANCEL((udev_device_new_from_subsystem_sysname)(udev, + subsystem, sysname)); pthread_cleanup_pop(1); return ret; @@ -147,7 +158,7 @@ struct udev_device *mt_udev_device_new_from_device_id(struct udev *udev, char *i pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_device_new_from_device_id(udev, id); + ret = MT_NO_CANCEL((udev_device_new_from_device_id)(udev, id)); pthread_cleanup_pop(1); return ret; @@ -160,7 +171,7 @@ struct udev_device *mt_udev_device_new_from_environment(struct udev *udev) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_device_new_from_environment(udev); + ret = MT_NO_CANCEL((udev_device_new_from_environment)(udev)); pthread_cleanup_pop(1); return ret; @@ -173,7 +184,7 @@ struct udev_device *mt_udev_device_ref(struct udev_device *udev_device) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_device_ref(udev_device); + ret = MT_NO_CANCEL((udev_device_ref)(udev_device)); pthread_cleanup_pop(1); return ret; @@ -186,7 +197,7 @@ struct udev_device *mt_udev_device_unref(struct udev_device *udev_device) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_device_unref(udev_device); + ret = MT_NO_CANCEL((udev_device_unref)(udev_device)); pthread_cleanup_pop(1); return ret; @@ -199,7 +210,7 @@ struct udev *mt_udev_device_get_udev(struct udev_device *udev_device) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_device_get_udev(udev_device); + ret = MT_NO_CANCEL((udev_device_get_udev)(udev_device)); pthread_cleanup_pop(1); return ret; @@ -212,7 +223,7 @@ struct udev_device *mt_udev_device_get_parent(struct udev_device *udev_device) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_device_get_parent(udev_device); + ret = MT_NO_CANCEL((udev_device_get_parent)(udev_device)); pthread_cleanup_pop(1); return ret; @@ -226,8 +237,8 @@ struct udev_device *mt_udev_device_get_parent_with_subsystem_devtype( pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_device_get_parent_with_subsystem_devtype(udev_device, - subsystem, devtype); + ret = MT_NO_CANCEL((udev_device_get_parent_with_subsystem_devtype)(udev_device, + subsystem, devtype)); pthread_cleanup_pop(1); return ret; @@ -240,7 +251,7 @@ const char *mt_udev_device_get_devpath(struct udev_device *udev_device) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_device_get_devpath(udev_device); + ret = MT_NO_CANCEL((udev_device_get_devpath)(udev_device)); pthread_cleanup_pop(1); return ret; @@ -253,7 +264,7 @@ const char *mt_udev_device_get_subsystem(struct udev_device *udev_device) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_device_get_subsystem(udev_device); + ret = MT_NO_CANCEL((udev_device_get_subsystem)(udev_device)); pthread_cleanup_pop(1); return ret; @@ -266,7 +277,7 @@ const char *mt_udev_device_get_devtype(struct udev_device *udev_device) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_device_get_devtype(udev_device); + ret = MT_NO_CANCEL((udev_device_get_devtype)(udev_device)); pthread_cleanup_pop(1); return ret; @@ -279,7 +290,7 @@ const char *mt_udev_device_get_syspath(struct udev_device *udev_device) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_device_get_syspath(udev_device); + ret = MT_NO_CANCEL((udev_device_get_syspath)(udev_device)); pthread_cleanup_pop(1); return ret; @@ -292,7 +303,7 @@ const char *mt_udev_device_get_sysname(struct udev_device *udev_device) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_device_get_sysname(udev_device); + ret = MT_NO_CANCEL((udev_device_get_sysname)(udev_device)); pthread_cleanup_pop(1); return ret; @@ -305,7 +316,7 @@ dev_t mt_udev_device_get_devnum(struct udev_device *udev_device) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_device_get_devnum(udev_device); + ret = MT_NO_CANCEL((udev_device_get_devnum)(udev_device)); pthread_cleanup_pop(1); return ret; @@ -318,7 +329,7 @@ unsigned long long mt_udev_device_get_seqnum(struct udev_device *udev_device) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_device_get_seqnum(udev_device); + ret = MT_NO_CANCEL((udev_device_get_seqnum)(udev_device)); pthread_cleanup_pop(1); return ret; @@ -331,7 +342,7 @@ const char *mt_udev_device_get_driver(struct udev_device *udev_device) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_device_get_driver(udev_device); + ret = MT_NO_CANCEL((udev_device_get_driver)(udev_device)); pthread_cleanup_pop(1); return ret; @@ -344,7 +355,7 @@ const char *mt_udev_device_get_devnode(struct udev_device *udev_device) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_device_get_devnode(udev_device); + ret = MT_NO_CANCEL((udev_device_get_devnode)(udev_device)); pthread_cleanup_pop(1); return ret; @@ -357,7 +368,7 @@ int mt_udev_device_get_is_initialized(struct udev_device *udev_device) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_device_get_is_initialized(udev_device); + ret = MT_NO_CANCEL((udev_device_get_is_initialized)(udev_device)); pthread_cleanup_pop(1); return ret; @@ -371,7 +382,7 @@ mt_udev_device_get_property_value(struct udev_device *udev_device, const char *k pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_device_get_property_value(udev_device, key); + ret = MT_NO_CANCEL((udev_device_get_property_value)(udev_device, key)); pthread_cleanup_pop(1); return ret; @@ -385,7 +396,7 @@ const char *mt_udev_device_get_sysattr_value(struct udev_device *udev_device, pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_device_get_sysattr_value(udev_device, sysattr); + ret = MT_NO_CANCEL((udev_device_get_sysattr_value)(udev_device, sysattr)); pthread_cleanup_pop(1); return ret; @@ -399,7 +410,7 @@ int mt_udev_device_set_sysattr_value(struct udev_device *udev_device, pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_device_set_sysattr_value(udev_device, sysattr, value); + ret = MT_NO_CANCEL((udev_device_set_sysattr_value)(udev_device, sysattr, value)); pthread_cleanup_pop(1); return ret; @@ -413,7 +424,7 @@ mt_udev_device_get_properties_list_entry(struct udev_device *udev_device) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_device_get_properties_list_entry(udev_device); + ret = MT_NO_CANCEL((udev_device_get_properties_list_entry)(udev_device)); pthread_cleanup_pop(1); return ret; @@ -485,7 +496,7 @@ mt_udev_monitor_new_from_netlink(struct udev *udev, const char *name) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_monitor_new_from_netlink(udev, name); + ret = MT_NO_CANCEL((udev_monitor_new_from_netlink)(udev, name)); pthread_cleanup_pop(1); return ret; @@ -498,7 +509,7 @@ struct udev_monitor *mt_udev_monitor_ref(struct udev_monitor *udev_monitor) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_monitor_ref(udev_monitor); + ret = MT_NO_CANCEL((udev_monitor_ref)(udev_monitor)); pthread_cleanup_pop(1); return ret; @@ -511,7 +522,7 @@ struct udev_monitor *mt_udev_monitor_unref(struct udev_monitor *udev_monitor) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_monitor_unref(udev_monitor); + ret = MT_NO_CANCEL((udev_monitor_unref)(udev_monitor)); pthread_cleanup_pop(1); return ret; @@ -524,7 +535,7 @@ int mt_udev_monitor_enable_receiving(struct udev_monitor *udev_monitor) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_monitor_enable_receiving(udev_monitor); + ret = MT_NO_CANCEL((udev_monitor_enable_receiving)(udev_monitor)); pthread_cleanup_pop(1); return ret; @@ -537,7 +548,7 @@ int mt_udev_monitor_get_fd(struct udev_monitor *udev_monitor) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_monitor_get_fd(udev_monitor); + ret = MT_NO_CANCEL((udev_monitor_get_fd)(udev_monitor)); pthread_cleanup_pop(1); return ret; @@ -550,7 +561,7 @@ struct udev_device *mt_udev_monitor_receive_device(struct udev_monitor *udev_mon pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_monitor_receive_device(udev_monitor); + ret = MT_NO_CANCEL((udev_monitor_receive_device)(udev_monitor)); pthread_cleanup_pop(1); return ret; @@ -564,8 +575,8 @@ int mt_udev_monitor_filter_add_match_subsystem_devtype( pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_monitor_filter_add_match_subsystem_devtype(udev_monitor, - subsystem, devtype); + ret = MT_NO_CANCEL((udev_monitor_filter_add_match_subsystem_devtype)(udev_monitor, + subsystem, devtype)); pthread_cleanup_pop(1); return ret; @@ -578,7 +589,7 @@ int mt_udev_monitor_set_receive_buffer_size(struct udev_monitor *udev_monitor, i pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_monitor_set_receive_buffer_size(udev_monitor, size); + ret = MT_NO_CANCEL((udev_monitor_set_receive_buffer_size)(udev_monitor, size)); pthread_cleanup_pop(1); return ret; @@ -591,7 +602,7 @@ struct udev_enumerate *mt_udev_enumerate_new(struct udev *udev) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_enumerate_new(udev); + ret = MT_NO_CANCEL((udev_enumerate_new)(udev)); pthread_cleanup_pop(1); return ret; @@ -604,7 +615,7 @@ struct udev_enumerate *mt_udev_enumerate_ref(struct udev_enumerate *udev_enumera pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_enumerate_ref(udev_enumerate); + ret = MT_NO_CANCEL((udev_enumerate_ref)(udev_enumerate)); pthread_cleanup_pop(1); return ret; @@ -617,7 +628,7 @@ struct udev_enumerate *mt_udev_enumerate_unref(struct udev_enumerate *udev_enume pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_enumerate_unref(udev_enumerate); + ret = MT_NO_CANCEL((udev_enumerate_unref)(udev_enumerate)); pthread_cleanup_pop(1); return ret; @@ -631,7 +642,7 @@ int mt_udev_enumerate_add_match_subsystem(struct udev_enumerate *udev_enumerate, pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_enumerate_add_match_subsystem(udev_enumerate, subsystem); + ret = MT_NO_CANCEL((udev_enumerate_add_match_subsystem)(udev_enumerate, subsystem)); pthread_cleanup_pop(1); return ret; @@ -645,7 +656,7 @@ int mt_udev_enumerate_add_nomatch_subsystem(struct udev_enumerate *udev_enumerat pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_enumerate_add_nomatch_subsystem(udev_enumerate, subsystem); + ret = MT_NO_CANCEL((udev_enumerate_add_nomatch_subsystem)(udev_enumerate, subsystem)); pthread_cleanup_pop(1); return ret; @@ -659,7 +670,7 @@ int mt_udev_enumerate_add_match_sysattr(struct udev_enumerate *udev_enumerate, pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_enumerate_add_match_sysattr(udev_enumerate, sysattr, value); + ret = MT_NO_CANCEL((udev_enumerate_add_match_sysattr)(udev_enumerate, sysattr, value)); pthread_cleanup_pop(1); return ret; @@ -673,7 +684,7 @@ int mt_udev_enumerate_add_nomatch_sysattr(struct udev_enumerate *udev_enumerate, pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_enumerate_add_nomatch_sysattr(udev_enumerate, sysattr, value); + ret = MT_NO_CANCEL((udev_enumerate_add_nomatch_sysattr)(udev_enumerate, sysattr, value)); pthread_cleanup_pop(1); return ret; @@ -687,7 +698,7 @@ int mt_udev_enumerate_add_match_property(struct udev_enumerate *udev_enumerate, pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_enumerate_add_match_property(udev_enumerate, property, value); + ret = MT_NO_CANCEL((udev_enumerate_add_match_property)(udev_enumerate, property, value)); pthread_cleanup_pop(1); return ret; @@ -701,7 +712,7 @@ int mt_udev_enumerate_add_match_tag(struct udev_enumerate *udev_enumerate, pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_enumerate_add_match_tag(udev_enumerate, tag); + ret = MT_NO_CANCEL((udev_enumerate_add_match_tag)(udev_enumerate, tag)); pthread_cleanup_pop(1); return ret; @@ -715,7 +726,7 @@ int mt_udev_enumerate_add_match_parent(struct udev_enumerate *udev_enumerate, pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_enumerate_add_match_parent(udev_enumerate, parent); + ret = MT_NO_CANCEL((udev_enumerate_add_match_parent)(udev_enumerate, parent)); pthread_cleanup_pop(1); return ret; @@ -728,7 +739,7 @@ int mt_udev_enumerate_add_match_is_initialized(struct udev_enumerate *udev_enume pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_enumerate_add_match_is_initialized(udev_enumerate); + ret = MT_NO_CANCEL((udev_enumerate_add_match_is_initialized)(udev_enumerate)); pthread_cleanup_pop(1); return ret; @@ -742,7 +753,7 @@ int mt_udev_enumerate_add_syspath(struct udev_enumerate *udev_enumerate, pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_enumerate_add_syspath(udev_enumerate, syspath); + ret = MT_NO_CANCEL((udev_enumerate_add_syspath)(udev_enumerate, syspath)); pthread_cleanup_pop(1); return ret; @@ -755,7 +766,7 @@ int mt_udev_enumerate_scan_devices(struct udev_enumerate *udev_enumerate) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_enumerate_scan_devices(udev_enumerate); + ret = MT_NO_CANCEL((udev_enumerate_scan_devices)(udev_enumerate)); pthread_cleanup_pop(1); return ret; @@ -769,7 +780,7 @@ mt_udev_enumerate_get_list_entry(struct udev_enumerate *udev_enumerate) pthread_mutex_lock(&libudev_mutex); pthread_cleanup_push(cleanup_mutex, &libudev_mutex); - ret = udev_enumerate_get_list_entry(udev_enumerate); + ret = MT_NO_CANCEL((udev_enumerate_get_list_entry)(udev_enumerate)); pthread_cleanup_pop(1); return ret;