mmc: vub300: fix use-after-free in vub300 teardown
Subsystems (2)
PATCH v2 1/1 mmc: vub300: fix use-after-free in vub300 teardown
mmc_host_classdev_release() reads host->parent->of_node, but the parent is not guaranteed to outlive the host. Instead, store host->index_is_alias to avoid reading the parent at release time.
Also, call kref_put() after mmc_request_done(), as the latter dereferences the host pointer.
--- drivers/mmc/core/host.c | 3 ++- drivers/mmc/host/vub300.c | 4 ++-- include/linux/mmc/host.h | 1 + 3 files changed, 5 insertions(+), 3 deletions(-)
drivers/mmc/core/host.c +2 -1
@@ -67,7 +67,7 @@ static void mmc_host_classdev_release(struct device *dev) {struct mmc_host *host =cls_dev_to_mmc_host (dev);wakeup_source_unregister (host->ws); -if (of_alias_get_id (host->parent->of_node,"mmc" ) <0 ) +if (!host->index_is_alias)ida_free (&mmc_host_ida, host->index);kfree (host); }
@@ -538,6 +538,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev) } host->index = index; + host->index_is_alias = (alias_id >=0 );dev_set_name (&host->class_dev,"mmc%d" , host->index); host->ws =wakeup_source_register (NULL ,dev_name (&host->class_dev));
drivers/mmc/host/vub300.c +2 -2
@@ -1794,8 +1794,8 @@ static void vub300_cmndwork_thread(struct work_struct *work)construct_request_response (vub300, cmd); vub300->resp_len =0 ;mutex_unlock (&vub300->cmd_mutex); -kref_put (&vub300->kref, vub300_delete);mmc_request_done (vub300->mmc, req); +kref_put (&vub300->kref, vub300_delete);return ; } }
@@ -1946,8 +1946,8 @@ static void vub300_mmc_request(struct mmc_host *mmc, struct mmc_request *req) satisfy_request_from_offloaded_data(vub300, cmd)) { cmd->error = 0; mutex_unlock(&vub300->cmd_mutex); - kref_put(&vub300->kref, vub300_delete); mmc_request_done(mmc, req); + kref_put(&vub300->kref, vub300_delete); return; } else { vub300->cmd = cmd;
include/linux/mmc/host.h +1 -0
@@ -356,6 +356,7 @@ struct mmc_host {struct device *parent;struct device class_dev;int index; +bool index_is_alias;const struct mmc_host_ops *ops;struct mmc_pwrseq *pwrseq;unsigned int f_min;
Signature · 1 line
2.51.0
Quoted 6 lines · Adriano Cordova
mmc_host_classdev_release()readshost->parent->of_node, but the parent is not guaranteed to outlive the host. Instead, storehost->index_is_aliasto avoid reading the parent at release time.Also, call
kref_put()aftermmc_request_done(), as the latter dereferences the host pointer.
These are two separate issues and should be fixed separately.
Quoted 1 line
Fixes 88095e7b473a ("mmc: Add new VUB300 USB-to-SD/SDIO/MMC driver")
This is not the commit that introduced the of_node issue.
Quoted 10 lines
Reported-by [email protected]Assisted-by opencode: deepseek v4 flashSigned-off-by Adriano Cordova <[email protected]>--- drivers/mmc/core/host.c | 3 ++- drivers/mmc/host/vub300.c | 4 ++-- include/linux/mmc/host.h | 1 + 3 files changed, 5 insertions(+), 3 deletions(-)
Johan