Skip to content

Commit 106d594

Browse files
Danilo Krummrichgregkh
authored andcommitted
s390/cio: use generic driver_override infrastructure
[ Upstream commit ac4d8bb ] 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> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent 13d201b commit 106d594

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
@@ -160,7 +160,6 @@ static void css_subchannel_release(struct device *dev)
160160

161161
sch->config.intparm = 0;
162162
cio_commit_config(sch);
163-
kfree(sch->driver_override);
164163
kfree(sch);
165164
}
166165

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

325324
static DEVICE_ATTR_RO(modalias);
326325

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

@@ -1358,9 +1329,11 @@ static int css_bus_match(struct device *dev, const struct device_driver *drv)
13581329
struct subchannel *sch = to_subchannel(dev);
13591330
const struct css_driver *driver = to_cssdriver(drv);
13601331
struct css_device_id *id;
1332+
int ret;
13611333

13621334
/* When driver_override is set, only bind to the matching driver */
1363-
if (sch->driver_override && strcmp(sch->driver_override, drv->name))
1335+
ret = device_match_driver_override(dev, drv);
1336+
if (ret == 0)
13641337
return 0;
13651338

13661339
for (id = driver->subchannel_type; id->match_flags; id++) {
@@ -1417,6 +1390,7 @@ static int css_uevent(const struct device *dev, struct kobj_uevent_env *env)
14171390

14181391
static const struct bus_type css_bus_type = {
14191392
.name = "css",
1393+
.driver_override = true,
14201394
.match = css_bus_match,
14211395
.probe = css_probe,
14221396
.remove = css_remove,

0 commit comments

Comments
 (0)