Skip to content

Commit 72761a7

Browse files
committed
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
2 parents 818444a + 2eead19 commit 72761a7

File tree

6 files changed

+109
-69
lines changed

6 files changed

+109
-69
lines changed

drivers/base/arch_topology.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ bool __init topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu)
292292
* frequency (by keeping the initial capacity_freq_ref value).
293293
*/
294294
cpu_clk = of_clk_get(cpu_node, 0);
295-
if (!PTR_ERR_OR_ZERO(cpu_clk)) {
295+
if (!IS_ERR_OR_NULL(cpu_clk)) {
296296
per_cpu(capacity_freq_ref, cpu) =
297297
clk_get_rate(cpu_clk) / HZ_PER_KHZ;
298298
clk_put(cpu_clk);

drivers/base/core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1784,7 +1784,7 @@ static int fw_devlink_dev_sync_state(struct device *dev, void *data)
17841784
return 0;
17851785

17861786
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",
17881788
dev_name(link->consumer));
17891789
return 0;
17901790
}

drivers/base/devcoredump.c

Lines changed: 83 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -23,50 +23,46 @@ struct devcd_entry {
2323
void *data;
2424
size_t datalen;
2525
/*
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.
3127
*
28+
* The first race is between device creation and userspace writing to
29+
* schedule immediately destruction.
3230
*
31+
* This race is handled by arming the timer before device creation, but
32+
* when device creation fails the timer still exists.
3333
*
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.
3536
*
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.
4040
*
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.
6343
*/
6444
struct mutex mutex;
65-
bool delete_work;
45+
bool init_completed, deleted;
6646
struct module *owner;
6747
ssize_t (*read)(char *buffer, loff_t offset, size_t count,
6848
void *data, size_t datalen);
6949
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+
*/
7066
struct delayed_work del_wk;
7167
struct device *failing_dev;
7268
};
@@ -95,14 +91,27 @@ static void devcd_dev_release(struct device *dev)
9591
kfree(devcd);
9692
}
9793

94+
static void __devcd_del(struct devcd_entry *devcd)
95+
{
96+
devcd->deleted = true;
97+
device_del(&devcd->devcd_dev);
98+
put_device(&devcd->devcd_dev);
99+
}
100+
98101
static void devcd_del(struct work_struct *wk)
99102
{
100103
struct devcd_entry *devcd;
104+
bool init_completed;
101105

102106
devcd = container_of(wk, struct devcd_entry, del_wk.work);
103107

104-
device_del(&devcd->devcd_dev);
105-
put_device(&devcd->devcd_dev);
108+
/* devcd->mutex serializes against dev_coredumpm_timeout */
109+
mutex_lock(&devcd->mutex);
110+
init_completed = devcd->init_completed;
111+
mutex_unlock(&devcd->mutex);
112+
113+
if (init_completed)
114+
__devcd_del(devcd);
106115
}
107116

108117
static ssize_t devcd_data_read(struct file *filp, struct kobject *kobj,
@@ -122,12 +131,12 @@ static ssize_t devcd_data_write(struct file *filp, struct kobject *kobj,
122131
struct device *dev = kobj_to_dev(kobj);
123132
struct devcd_entry *devcd = dev_to_devcd(dev);
124133

125-
mutex_lock(&devcd->mutex);
126-
if (!devcd->delete_work) {
127-
devcd->delete_work = true;
128-
mod_delayed_work(system_wq, &devcd->del_wk, 0);
129-
}
130-
mutex_unlock(&devcd->mutex);
134+
/*
135+
* Although it's tempting to use mod_delayed work here,
136+
* that will cause a reschedule if the timer already fired.
137+
*/
138+
if (cancel_delayed_work(&devcd->del_wk))
139+
schedule_delayed_work(&devcd->del_wk, 0);
131140

132141
return count;
133142
}
@@ -151,11 +160,21 @@ static int devcd_free(struct device *dev, void *data)
151160
{
152161
struct devcd_entry *devcd = dev_to_devcd(dev);
153162

163+
/*
164+
* To prevent a race with devcd_data_write(), disable work and
165+
* complete manually instead.
166+
*
167+
* We cannot rely on the return value of
168+
* disable_delayed_work_sync() here, because it might be in the
169+
* middle of a cancel_delayed_work + schedule_delayed_work pair.
170+
*
171+
* devcd->mutex here guards against multiple parallel invocations
172+
* of devcd_free().
173+
*/
174+
disable_delayed_work_sync(&devcd->del_wk);
154175
mutex_lock(&devcd->mutex);
155-
if (!devcd->delete_work)
156-
devcd->delete_work = true;
157-
158-
flush_delayed_work(&devcd->del_wk);
176+
if (!devcd->deleted)
177+
__devcd_del(devcd);
159178
mutex_unlock(&devcd->mutex);
160179
return 0;
161180
}
@@ -179,12 +198,10 @@ static ssize_t disabled_show(const struct class *class, const struct class_attri
179198
* put_device() <- last reference
180199
* error = fn(dev, data) devcd_dev_release()
181200
* devcd_free(dev, data) kfree(devcd)
182-
* mutex_lock(&devcd->mutex);
183201
*
184202
*
185203
* In the above diagram, it looks like disabled_store() would be racing with parallelly
186-
* running devcd_del() and result in memory abort while acquiring devcd->mutex which
187-
* is called after kfree of devcd memory after dropping its last reference with
204+
* running devcd_del() and result in memory abort after dropping its last reference with
188205
* put_device(). However, this will not happens as fn(dev, data) runs
189206
* with its own reference to device via klist_node so it is not its last reference.
190207
* so, above situation would not occur.
@@ -374,7 +391,7 @@ void dev_coredumpm_timeout(struct device *dev, struct module *owner,
374391
devcd->read = read;
375392
devcd->free = free;
376393
devcd->failing_dev = get_device(dev);
377-
devcd->delete_work = false;
394+
devcd->deleted = false;
378395

379396
mutex_init(&devcd->mutex);
380397
device_initialize(&devcd->devcd_dev);
@@ -383,8 +400,14 @@ void dev_coredumpm_timeout(struct device *dev, struct module *owner,
383400
atomic_inc_return(&devcd_count));
384401
devcd->devcd_dev.class = &devcd_class;
385402

386-
mutex_lock(&devcd->mutex);
387403
dev_set_uevent_suppress(&devcd->devcd_dev, true);
404+
405+
/* devcd->mutex prevents devcd_del() completing until init finishes */
406+
mutex_lock(&devcd->mutex);
407+
devcd->init_completed = false;
408+
INIT_DELAYED_WORK(&devcd->del_wk, devcd_del);
409+
schedule_delayed_work(&devcd->del_wk, timeout);
410+
388411
if (device_add(&devcd->devcd_dev))
389412
goto put_device;
390413

@@ -401,13 +424,20 @@ void dev_coredumpm_timeout(struct device *dev, struct module *owner,
401424

402425
dev_set_uevent_suppress(&devcd->devcd_dev, false);
403426
kobject_uevent(&devcd->devcd_dev.kobj, KOBJ_ADD);
404-
INIT_DELAYED_WORK(&devcd->del_wk, devcd_del);
405-
schedule_delayed_work(&devcd->del_wk, timeout);
427+
428+
/*
429+
* Safe to run devcd_del() now that we are done with devcd_dev.
430+
* Alternatively we could have taken a ref on devcd_dev before
431+
* dropping the lock.
432+
*/
433+
devcd->init_completed = true;
406434
mutex_unlock(&devcd->mutex);
407435
return;
408436
put_device:
409-
put_device(&devcd->devcd_dev);
410437
mutex_unlock(&devcd->mutex);
438+
cancel_delayed_work_sync(&devcd->del_wk);
439+
put_device(&devcd->devcd_dev);
440+
411441
put_module:
412442
module_put(owner);
413443
free:

fs/sysfs/group.c

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -498,17 +498,26 @@ int compat_only_sysfs_link_entry_to_kobj(struct kobject *kobj,
498498
}
499499
EXPORT_SYMBOL_GPL(compat_only_sysfs_link_entry_to_kobj);
500500

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,
502503
const struct attribute_group *grp,
503504
struct iattr *newattrs)
504505
{
505506
struct kernfs_node *kn;
506-
int error;
507+
int error, i;
508+
umode_t mode;
507509

508510
if (grp->attrs) {
509511
struct attribute *const *attr;
510512

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+
}
512521
kn = kernfs_find_and_get(grp_kn, (*attr)->name);
513522
if (!kn)
514523
return -ENOENT;
@@ -523,7 +532,14 @@ static int sysfs_group_attrs_change_owner(struct kernfs_node *grp_kn,
523532
if (grp->bin_attrs) {
524533
const struct bin_attribute *const *bin_attr;
525534

526-
for (bin_attr = grp->bin_attrs; *bin_attr; bin_attr++) {
535+
for (i = 0, bin_attr = grp->bin_attrs; *bin_attr; i++, bin_attr++) {
536+
if (grp->is_bin_visible) {
537+
mode = grp->is_bin_visible(kobj, *bin_attr, i);
538+
if (mode & SYSFS_GROUP_INVISIBLE)
539+
break;
540+
if (!mode)
541+
continue;
542+
}
527543
kn = kernfs_find_and_get(grp_kn, (*bin_attr)->attr.name);
528544
if (!kn)
529545
return -ENOENT;
@@ -573,7 +589,7 @@ int sysfs_group_change_owner(struct kobject *kobj,
573589

574590
error = kernfs_setattr(grp_kn, &newattrs);
575591
if (!error)
576-
error = sysfs_group_attrs_change_owner(grp_kn, grp, &newattrs);
592+
error = sysfs_group_attrs_change_owner(kobj, grp_kn, grp, &newattrs);
577593

578594
kernfs_put(grp_kn);
579595

rust/kernel/auxiliary.rs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -217,13 +217,7 @@ impl<Ctx: device::DeviceContext> Device<Ctx> {
217217

218218
/// Returns a reference to the parent [`device::Device`], if any.
219219
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()
227221
}
228222
}
229223

rust/kernel/device.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ impl<Ctx: DeviceContext> Device<Ctx> {
251251

252252
/// Returns a reference to the parent device, if any.
253253
#[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> {
255255
// SAFETY:
256256
// - By the type invariant `self.as_raw()` is always valid.
257257
// - The parent device is only ever set at device creation.
@@ -264,7 +264,7 @@ impl<Ctx: DeviceContext> Device<Ctx> {
264264
// - Since `parent` is not NULL, it must be a valid pointer to a `struct device`.
265265
// - `parent` is valid for the lifetime of `self`, since a `struct device` holds a
266266
// reference count of its parent.
267-
Some(unsafe { Self::from_raw(parent) })
267+
Some(unsafe { Device::from_raw(parent) })
268268
}
269269
}
270270

0 commit comments

Comments
 (0)