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.

Merge tag 'driver-core-6.18-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core

Pull driver core fixes from Danilo Krummrich:

- In Device::parent(), do not make any assumptions on the device
context of the parent device

- Check visibility before changing ownership of a sysfs attribute
group

- In topology_parse_cpu_capacity(), replace an incorrect usage of
PTR_ERR_OR_ZERO() with IS_ERR_OR_NULL()

- In devcoredump, fix a circular locking dependency between
struct devcd_entry::mutex and kernfs

- Do not warn about a pending fw_devlink sync state

* tag 'driver-core-6.18-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/driver-core/driver-core:
arch_topology: Fix incorrect error check in topology_parse_cpu_capacity()
rust: device: fix device context of Device::parent()
sysfs: check visibility before changing group attribute ownership
devcoredump: Fix circular locking dependency with devcd->mutex.
driver core: fw_devlink: Don't warn about sync_state() pending

+109 -69
+1 -1
drivers/base/arch_topology.c
··· 292 292 * frequency (by keeping the initial capacity_freq_ref value). 293 293 */ 294 294 cpu_clk = of_clk_get(cpu_node, 0); 295 - if (!PTR_ERR_OR_ZERO(cpu_clk)) { 295 + if (!IS_ERR_OR_NULL(cpu_clk)) { 296 296 per_cpu(capacity_freq_ref, cpu) = 297 297 clk_get_rate(cpu_clk) / HZ_PER_KHZ; 298 298 clk_put(cpu_clk);
+1 -1
drivers/base/core.c
··· 1784 1784 return 0; 1785 1785 1786 1786 if (fw_devlink_sync_state == FW_DEVLINK_SYNC_STATE_STRICT) { 1787 - dev_warn(sup, "sync_state() pending due to %s\n", 1787 + dev_info(sup, "sync_state() pending due to %s\n", 1788 1788 dev_name(link->consumer)); 1789 1789 return 0; 1790 1790 }
+83 -53
drivers/base/devcoredump.c
··· 23 23 void *data; 24 24 size_t datalen; 25 25 /* 26 - * Here, mutex is required to serialize the calls to del_wk work between 27 - * user/kernel space which happens when devcd is added with device_add() 28 - * and that sends uevent to user space. User space reads the uevents, 29 - * and calls to devcd_data_write() which try to modify the work which is 30 - * not even initialized/queued from devcoredump. 26 + * There are 2 races for which mutex is required. 31 27 * 28 + * The first race is between device creation and userspace writing to 29 + * schedule immediately destruction. 32 30 * 31 + * This race is handled by arming the timer before device creation, but 32 + * when device creation fails the timer still exists. 33 33 * 34 - * cpu0(X) cpu1(Y) 34 + * To solve this, hold the mutex during device_add(), and set 35 + * init_completed on success before releasing the mutex. 35 36 * 36 - * dev_coredump() uevent sent to user space 37 - * device_add() ======================> user space process Y reads the 38 - * uevents writes to devcd fd 39 - * which results into writes to 37 + * That way the timer will never fire until device_add() is called, 38 + * it will do nothing if init_completed is not set. The timer is also 39 + * cancelled in that case. 40 40 * 41 - * devcd_data_write() 42 - * mod_delayed_work() 43 - * try_to_grab_pending() 44 - * timer_delete() 45 - * debug_assert_init() 46 - * INIT_DELAYED_WORK() 47 - * schedule_delayed_work() 48 - * 49 - * 50 - * Also, mutex alone would not be enough to avoid scheduling of 51 - * del_wk work after it get flush from a call to devcd_free() 52 - * mentioned as below. 53 - * 54 - * disabled_store() 55 - * devcd_free() 56 - * mutex_lock() devcd_data_write() 57 - * flush_delayed_work() 58 - * mutex_unlock() 59 - * mutex_lock() 60 - * mod_delayed_work() 61 - * mutex_unlock() 62 - * So, delete_work flag is required. 41 + * The second race involves multiple parallel invocations of devcd_free(), 42 + * add a deleted flag so only 1 can call the destructor. 63 43 */ 64 44 struct mutex mutex; 65 - bool delete_work; 45 + bool init_completed, deleted; 66 46 struct module *owner; 67 47 ssize_t (*read)(char *buffer, loff_t offset, size_t count, 68 48 void *data, size_t datalen); 69 49 void (*free)(void *data); 50 + /* 51 + * If nothing interferes and device_add() was returns success, 52 + * del_wk will destroy the device after the timer fires. 53 + * 54 + * Multiple userspace processes can interfere in the working of the timer: 55 + * - Writing to the coredump will reschedule the timer to run immediately, 56 + * if still armed. 57 + * 58 + * This is handled by using "if (cancel_delayed_work()) { 59 + * schedule_delayed_work() }", to prevent re-arming after having 60 + * been previously fired. 61 + * - Writing to /sys/class/devcoredump/disabled will destroy the 62 + * coredump synchronously. 63 + * This is handled by using disable_delayed_work_sync(), and then 64 + * checking if deleted flag is set with &devcd->mutex held. 65 + */ 70 66 struct delayed_work del_wk; 71 67 struct device *failing_dev; 72 68 }; ··· 91 95 kfree(devcd); 92 96 } 93 97 98 + static void __devcd_del(struct devcd_entry *devcd) 99 + { 100 + devcd->deleted = true; 101 + device_del(&devcd->devcd_dev); 102 + put_device(&devcd->devcd_dev); 103 + } 104 + 94 105 static void devcd_del(struct work_struct *wk) 95 106 { 96 107 struct devcd_entry *devcd; 108 + bool init_completed; 97 109 98 110 devcd = container_of(wk, struct devcd_entry, del_wk.work); 99 111 100 - device_del(&devcd->devcd_dev); 101 - put_device(&devcd->devcd_dev); 112 + /* devcd->mutex serializes against dev_coredumpm_timeout */ 113 + mutex_lock(&devcd->mutex); 114 + init_completed = devcd->init_completed; 115 + mutex_unlock(&devcd->mutex); 116 + 117 + if (init_completed) 118 + __devcd_del(devcd); 102 119 } 103 120 104 121 static ssize_t devcd_data_read(struct file *filp, struct kobject *kobj, ··· 131 122 struct device *dev = kobj_to_dev(kobj); 132 123 struct devcd_entry *devcd = dev_to_devcd(dev); 133 124 134 - mutex_lock(&devcd->mutex); 135 - if (!devcd->delete_work) { 136 - devcd->delete_work = true; 137 - mod_delayed_work(system_wq, &devcd->del_wk, 0); 138 - } 139 - mutex_unlock(&devcd->mutex); 125 + /* 126 + * Although it's tempting to use mod_delayed work here, 127 + * that will cause a reschedule if the timer already fired. 128 + */ 129 + if (cancel_delayed_work(&devcd->del_wk)) 130 + schedule_delayed_work(&devcd->del_wk, 0); 140 131 141 132 return count; 142 133 } ··· 160 151 { 161 152 struct devcd_entry *devcd = dev_to_devcd(dev); 162 153 154 + /* 155 + * To prevent a race with devcd_data_write(), disable work and 156 + * complete manually instead. 157 + * 158 + * We cannot rely on the return value of 159 + * disable_delayed_work_sync() here, because it might be in the 160 + * middle of a cancel_delayed_work + schedule_delayed_work pair. 161 + * 162 + * devcd->mutex here guards against multiple parallel invocations 163 + * of devcd_free(). 164 + */ 165 + disable_delayed_work_sync(&devcd->del_wk); 163 166 mutex_lock(&devcd->mutex); 164 - if (!devcd->delete_work) 165 - devcd->delete_work = true; 166 - 167 - flush_delayed_work(&devcd->del_wk); 167 + if (!devcd->deleted) 168 + __devcd_del(devcd); 168 169 mutex_unlock(&devcd->mutex); 169 170 return 0; 170 171 } ··· 198 179 * put_device() <- last reference 199 180 * error = fn(dev, data) devcd_dev_release() 200 181 * devcd_free(dev, data) kfree(devcd) 201 - * mutex_lock(&devcd->mutex); 202 182 * 203 183 * 204 184 * In the above diagram, it looks like disabled_store() would be racing with parallelly 205 - * running devcd_del() and result in memory abort while acquiring devcd->mutex which 206 - * is called after kfree of devcd memory after dropping its last reference with 185 + * running devcd_del() and result in memory abort after dropping its last reference with 207 186 * put_device(). However, this will not happens as fn(dev, data) runs 208 187 * with its own reference to device via klist_node so it is not its last reference. 209 188 * so, above situation would not occur. ··· 391 374 devcd->read = read; 392 375 devcd->free = free; 393 376 devcd->failing_dev = get_device(dev); 394 - devcd->delete_work = false; 377 + devcd->deleted = false; 395 378 396 379 mutex_init(&devcd->mutex); 397 380 device_initialize(&devcd->devcd_dev); ··· 400 383 atomic_inc_return(&devcd_count)); 401 384 devcd->devcd_dev.class = &devcd_class; 402 385 403 - mutex_lock(&devcd->mutex); 404 386 dev_set_uevent_suppress(&devcd->devcd_dev, true); 387 + 388 + /* devcd->mutex prevents devcd_del() completing until init finishes */ 389 + mutex_lock(&devcd->mutex); 390 + devcd->init_completed = false; 391 + INIT_DELAYED_WORK(&devcd->del_wk, devcd_del); 392 + schedule_delayed_work(&devcd->del_wk, timeout); 393 + 405 394 if (device_add(&devcd->devcd_dev)) 406 395 goto put_device; 407 396 ··· 424 401 425 402 dev_set_uevent_suppress(&devcd->devcd_dev, false); 426 403 kobject_uevent(&devcd->devcd_dev.kobj, KOBJ_ADD); 427 - INIT_DELAYED_WORK(&devcd->del_wk, devcd_del); 428 - schedule_delayed_work(&devcd->del_wk, timeout); 404 + 405 + /* 406 + * Safe to run devcd_del() now that we are done with devcd_dev. 407 + * Alternatively we could have taken a ref on devcd_dev before 408 + * dropping the lock. 409 + */ 410 + devcd->init_completed = true; 429 411 mutex_unlock(&devcd->mutex); 430 412 return; 431 413 put_device: 432 - put_device(&devcd->devcd_dev); 433 414 mutex_unlock(&devcd->mutex); 415 + cancel_delayed_work_sync(&devcd->del_wk); 416 + put_device(&devcd->devcd_dev); 417 + 434 418 put_module: 435 419 module_put(owner); 436 420 free:
+21 -5
fs/sysfs/group.c
··· 498 498 } 499 499 EXPORT_SYMBOL_GPL(compat_only_sysfs_link_entry_to_kobj); 500 500 501 - static int sysfs_group_attrs_change_owner(struct kernfs_node *grp_kn, 501 + static int sysfs_group_attrs_change_owner(struct kobject *kobj, 502 + struct kernfs_node *grp_kn, 502 503 const struct attribute_group *grp, 503 504 struct iattr *newattrs) 504 505 { 505 506 struct kernfs_node *kn; 506 - int error; 507 + int error, i; 508 + umode_t mode; 507 509 508 510 if (grp->attrs) { 509 511 struct attribute *const *attr; 510 512 511 - for (attr = grp->attrs; *attr; attr++) { 513 + for (i = 0, attr = grp->attrs; *attr; i++, attr++) { 514 + if (grp->is_visible) { 515 + mode = grp->is_visible(kobj, *attr, i); 516 + if (mode & SYSFS_GROUP_INVISIBLE) 517 + break; 518 + if (!mode) 519 + continue; 520 + } 512 521 kn = kernfs_find_and_get(grp_kn, (*attr)->name); 513 522 if (!kn) 514 523 return -ENOENT; ··· 532 523 if (grp->bin_attrs) { 533 524 const struct bin_attribute *const *bin_attr; 534 525 535 - for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) { 526 + for (i = 0, bin_attr = grp->bin_attrs; *bin_attr; i++, bin_attr++) { 527 + if (grp->is_bin_visible) { 528 + mode = grp->is_bin_visible(kobj, *bin_attr, i); 529 + if (mode & SYSFS_GROUP_INVISIBLE) 530 + break; 531 + if (!mode) 532 + continue; 533 + } 536 534 kn = kernfs_find_and_get(grp_kn, (*bin_attr)->attr.name); 537 535 if (!kn) 538 536 return -ENOENT; ··· 589 573 590 574 error = kernfs_setattr(grp_kn, &newattrs); 591 575 if (!error) 592 - error = sysfs_group_attrs_change_owner(grp_kn, grp, &newattrs); 576 + error = sysfs_group_attrs_change_owner(kobj, grp_kn, grp, &newattrs); 593 577 594 578 kernfs_put(grp_kn); 595 579
+1 -7
rust/kernel/auxiliary.rs
··· 217 217 218 218 /// Returns a reference to the parent [`device::Device`], if any. 219 219 pub fn parent(&self) -> Option<&device::Device> { 220 - let ptr: *const Self = self; 221 - // CAST: `Device<Ctx: DeviceContext>` types are transparent to each other. 222 - let ptr: *const Device = ptr.cast(); 223 - // SAFETY: `ptr` was derived from `&self`. 224 - let this = unsafe { &*ptr }; 225 - 226 - this.as_ref().parent() 220 + self.as_ref().parent() 227 221 } 228 222 } 229 223
+2 -2
rust/kernel/device.rs
··· 251 251 252 252 /// Returns a reference to the parent device, if any. 253 253 #[cfg_attr(not(CONFIG_AUXILIARY_BUS), expect(dead_code))] 254 - pub(crate) fn parent(&self) -> Option<&Self> { 254 + pub(crate) fn parent(&self) -> Option<&Device> { 255 255 // SAFETY: 256 256 // - By the type invariant `self.as_raw()` is always valid. 257 257 // - The parent device is only ever set at device creation. ··· 264 264 // - Since `parent` is not NULL, it must be a valid pointer to a `struct device`. 265 265 // - `parent` is valid for the lifetime of `self`, since a `struct device` holds a 266 266 // reference count of its parent. 267 - Some(unsafe { Self::from_raw(parent) }) 267 + Some(unsafe { Device::from_raw(parent) }) 268 268 } 269 269 } 270 270