Skip to content

Commit ac4d8bb

Browse files
author
Danilo Krummrich
committed
s390/cio: use generic driver_override infrastructure
When a driver is probed through __driver_attach(), the bus' match() callback is called without the device lock held, thus accessing the driver_override field without a lock, which can cause a UAF. Fix this by using the driver-core driver_override infrastructure taking care of proper locking internally. Note that calling match() from __driver_attach() without the device lock held is intentional. [1] Link: https://lore.kernel.org/driver-core/DGRGTIRHA62X.3RY09D9SOK77P@kernel.org/ [1] Reported-by: Gui-Dong Han <hanguidong02@gmail.com> Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220789 Fixes: ebc3d17 ("s390/cio: introduce driver_override on the css bus") Reviewed-by: Vineeth Vijayan <vneethv@linux.ibm.com> Link: https://patch.msgid.link/20260324005919.2408620-10-dakr@kernel.org Signed-off-by: Danilo Krummrich <dakr@kernel.org>
1 parent 85bb534 commit ac4d8bb

2 files changed

Lines changed: 4 additions & 35 deletions

File tree

drivers/s390/cio/cio.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,11 +103,6 @@ struct subchannel {
103103
struct work_struct todo_work;
104104
struct schib_config config;
105105
u64 dma_mask;
106-
/*
107-
* Driver name to force a match. Do not set directly, because core
108-
* frees it. Use driver_set_override() to set or clear it.
109-
*/
110-
const char *driver_override;
111106
} __attribute__ ((aligned(8)));
112107

113108
DECLARE_PER_CPU_ALIGNED(struct irb, cio_irb);

drivers/s390/cio/css.c

Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,6 @@ static void css_subchannel_release(struct device *dev)
159159

160160
sch->config.intparm = 0;
161161
cio_commit_config(sch);
162-
kfree(sch->driver_override);
163162
kfree(sch);
164163
}
165164

@@ -323,37 +322,9 @@ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
323322

324323
static DEVICE_ATTR_RO(modalias);
325324

326-
static ssize_t driver_override_store(struct device *dev,
327-
struct device_attribute *attr,
328-
const char *buf, size_t count)
329-
{
330-
struct subchannel *sch = to_subchannel(dev);
331-
int ret;
332-
333-
ret = driver_set_override(dev, &sch->driver_override, buf, count);
334-
if (ret)
335-
return ret;
336-
337-
return count;
338-
}
339-
340-
static ssize_t driver_override_show(struct device *dev,
341-
struct device_attribute *attr, char *buf)
342-
{
343-
struct subchannel *sch = to_subchannel(dev);
344-
ssize_t len;
345-
346-
device_lock(dev);
347-
len = sysfs_emit(buf, "%s\n", sch->driver_override);
348-
device_unlock(dev);
349-
return len;
350-
}
351-
static DEVICE_ATTR_RW(driver_override);
352-
353325
static struct attribute *subch_attrs[] = {
354326
&dev_attr_type.attr,
355327
&dev_attr_modalias.attr,
356-
&dev_attr_driver_override.attr,
357328
NULL,
358329
};
359330

@@ -1356,9 +1327,11 @@ static int css_bus_match(struct device *dev, const struct device_driver *drv)
13561327
struct subchannel *sch = to_subchannel(dev);
13571328
const struct css_driver *driver = to_cssdriver(drv);
13581329
struct css_device_id *id;
1330+
int ret;
13591331

13601332
/* When driver_override is set, only bind to the matching driver */
1361-
if (sch->driver_override && strcmp(sch->driver_override, drv->name))
1333+
ret = device_match_driver_override(dev, drv);
1334+
if (ret == 0)
13621335
return 0;
13631336

13641337
for (id = driver->subchannel_type; id->match_flags; id++) {
@@ -1415,6 +1388,7 @@ static int css_uevent(const struct device *dev, struct kobj_uevent_env *env)
14151388

14161389
static const struct bus_type css_bus_type = {
14171390
.name = "css",
1391+
.driver_override = true,
14181392
.match = css_bus_match,
14191393
.probe = css_probe,
14201394
.remove = css_remove,

0 commit comments

Comments
 (0)