From a71d702d98d090eb0bc68fa7950a590967de8716 Mon Sep 17 00:00:00 2001 From: chenjiayi Date: Thu, 23 Nov 2023 14:23:46 +0800 Subject: [PATCH 082/103] fix(device): avoid panic on shallow clone when subsystem is not available Some special sysfs device, such as /sys/devices/platform, may not contain available subsystem. This leads to panic in shallow cloning such device object when getting its subsystem. --- libs/device/src/device.rs | 51 ++++++++++++++++++++++++--------------- 1 files changed, 32 insertions(+), 19 deletions(-) diff --git a/libs/device/src/device.rs b/libs/device/src/device.rs index e8e2dcc5..a9cb196c 100644 --- a/libs/device/src/device.rs +++ b/libs/device/src/device.rs @@ -2396,14 +2396,15 @@ impl Device { device.set_syspath(&syspath, false)?; - let subsystem = self.get_subsystem()?; + /* Some devices, such as /sys/devices/platform, do not have subsystem. */ + if let Ok(subsystem) = self.get_subsystem() { + device.set_subsystem(&subsystem); - device.set_subsystem(&subsystem); - - if subsystem == "drivers" { - device - .driver_subsystem - .replace(self.driver_subsystem.borrow().clone()); + if subsystem == "drivers" { + device + .driver_subsystem + .replace(self.driver_subsystem.borrow().clone()); + } } if let Ok(ifindex) = self.get_property_value("IFINDEX") { @@ -3506,19 +3507,31 @@ mod tests { #[test] fn test_shallow_clone() { - #[inline] - fn inner_test(dev: &mut Device) -> Result<(), Error> { - let s1 = dev.get_syspath().unwrap(); - - let dev_clone = dev.shallow_clone().unwrap(); - - assert_eq!(s1, dev_clone.get_syspath().unwrap()); - - Ok(()) - } + /* Enumerator merely collect devices with valid subsystems, + * while get_parent method may not, e.g., /sys/devices/platform. + */ + let mut e = DeviceEnumerator::new(); + e.set_enumerator_type(DeviceEnumerationType::All); + + for mut dev in e.iter() { + let dev_clone = dev.borrow().shallow_clone().unwrap(); + dev_clone.get_syspath().unwrap(); + dev_clone.get_subsystem().unwrap(); + + loop { + let ret = dev.borrow().get_parent(); + + if let Ok(parent) = ret { + parent.borrow().get_syspath().unwrap(); + if let Err(e) = parent.borrow().get_subsystem() { + assert_eq!(e.get_errno(), Errno::ENOENT); + } + dev = parent; + continue; + } - if let Err(e) = LoopDev::inner_process("/tmp/test_shallow_clone", 1024 * 10, inner_test) { - assert!(e.is_errno(nix::Error::EACCES) || e.is_errno(nix::Error::EBUSY)); + break; + } } } 2.33.0