Skip to content

Commit 4c363c8

Browse files
mikechristiemstsirkin
authored andcommitted
vhost-scsi: Fix crash during LUN unmapping
We normally clear the endpoint then unmap LUNs so the devices are fully shutdown when the LUN is unmapped, but it's legal to unmap before clearing. If the user does that while TMFs are running then we can end up crashing. vhost_scsi_port_unlink assumes that the LUN's tmf struct will always be on the tmf_queue list. However, if a TMF is running then it will have been removed while it's executing. If we do a LUN unmap at this time, then we assume the entry is on the list and just start accessing it and free it. This fixes the bug by just allocating the vhost_scsi_tmf struct when it's needed like is done with the se_tmr struct that's needed when we submit the TMF. In this path perf is not an issue and we can use GFP_KERNEL since it won't swing directly back on us, so we don't need to preallocate the struct. Signed-off-by: Mike Christie <[email protected]> Message-Id: <[email protected]> Signed-off-by: Michael S. Tsirkin <[email protected]>
1 parent e508efc commit 4c363c8

File tree

1 file changed

+4
-32
lines changed

1 file changed

+4
-32
lines changed

drivers/vhost/scsi.c

Lines changed: 4 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,6 @@ struct vhost_scsi_tpg {
125125
struct se_portal_group se_tpg;
126126
/* Pointer back to vhost_scsi, protected by tv_tpg_mutex */
127127
struct vhost_scsi *vhost_scsi;
128-
struct list_head tmf_queue;
129128
};
130129

131130
struct vhost_scsi_tport {
@@ -206,10 +205,8 @@ struct vhost_scsi {
206205

207206
struct vhost_scsi_tmf {
208207
struct vhost_work vwork;
209-
struct vhost_scsi_tpg *tpg;
210208
struct vhost_scsi *vhost;
211209
struct vhost_scsi_virtqueue *svq;
212-
struct list_head queue_entry;
213210

214211
struct se_cmd se_cmd;
215212
u8 scsi_resp;
@@ -352,12 +349,9 @@ static void vhost_scsi_release_cmd_res(struct se_cmd *se_cmd)
352349

353350
static void vhost_scsi_release_tmf_res(struct vhost_scsi_tmf *tmf)
354351
{
355-
struct vhost_scsi_tpg *tpg = tmf->tpg;
356352
struct vhost_scsi_inflight *inflight = tmf->inflight;
357353

358-
mutex_lock(&tpg->tv_tpg_mutex);
359-
list_add_tail(&tpg->tmf_queue, &tmf->queue_entry);
360-
mutex_unlock(&tpg->tv_tpg_mutex);
354+
kfree(tmf);
361355
vhost_scsi_put_inflight(inflight);
362356
}
363357

@@ -1194,19 +1188,11 @@ vhost_scsi_handle_tmf(struct vhost_scsi *vs, struct vhost_scsi_tpg *tpg,
11941188
goto send_reject;
11951189
}
11961190

1197-
mutex_lock(&tpg->tv_tpg_mutex);
1198-
if (list_empty(&tpg->tmf_queue)) {
1199-
pr_err("Missing reserve TMF. Could not handle LUN RESET.\n");
1200-
mutex_unlock(&tpg->tv_tpg_mutex);
1191+
tmf = kzalloc(sizeof(*tmf), GFP_KERNEL);
1192+
if (!tmf)
12011193
goto send_reject;
1202-
}
1203-
1204-
tmf = list_first_entry(&tpg->tmf_queue, struct vhost_scsi_tmf,
1205-
queue_entry);
1206-
list_del_init(&tmf->queue_entry);
1207-
mutex_unlock(&tpg->tv_tpg_mutex);
12081194

1209-
tmf->tpg = tpg;
1195+
vhost_work_init(&tmf->vwork, vhost_scsi_tmf_resp_work);
12101196
tmf->vhost = vs;
12111197
tmf->svq = svq;
12121198
tmf->resp_iov = vq->iov[vc->out];
@@ -2035,19 +2021,11 @@ static int vhost_scsi_port_link(struct se_portal_group *se_tpg,
20352021
{
20362022
struct vhost_scsi_tpg *tpg = container_of(se_tpg,
20372023
struct vhost_scsi_tpg, se_tpg);
2038-
struct vhost_scsi_tmf *tmf;
2039-
2040-
tmf = kzalloc(sizeof(*tmf), GFP_KERNEL);
2041-
if (!tmf)
2042-
return -ENOMEM;
2043-
INIT_LIST_HEAD(&tmf->queue_entry);
2044-
vhost_work_init(&tmf->vwork, vhost_scsi_tmf_resp_work);
20452024

20462025
mutex_lock(&vhost_scsi_mutex);
20472026

20482027
mutex_lock(&tpg->tv_tpg_mutex);
20492028
tpg->tv_tpg_port_count++;
2050-
list_add_tail(&tmf->queue_entry, &tpg->tmf_queue);
20512029
mutex_unlock(&tpg->tv_tpg_mutex);
20522030

20532031
vhost_scsi_hotplug(tpg, lun);
@@ -2062,16 +2040,11 @@ static void vhost_scsi_port_unlink(struct se_portal_group *se_tpg,
20622040
{
20632041
struct vhost_scsi_tpg *tpg = container_of(se_tpg,
20642042
struct vhost_scsi_tpg, se_tpg);
2065-
struct vhost_scsi_tmf *tmf;
20662043

20672044
mutex_lock(&vhost_scsi_mutex);
20682045

20692046
mutex_lock(&tpg->tv_tpg_mutex);
20702047
tpg->tv_tpg_port_count--;
2071-
tmf = list_first_entry(&tpg->tmf_queue, struct vhost_scsi_tmf,
2072-
queue_entry);
2073-
list_del(&tmf->queue_entry);
2074-
kfree(tmf);
20752048
mutex_unlock(&tpg->tv_tpg_mutex);
20762049

20772050
vhost_scsi_hotunplug(tpg, lun);
@@ -2332,7 +2305,6 @@ vhost_scsi_make_tpg(struct se_wwn *wwn, const char *name)
23322305
}
23332306
mutex_init(&tpg->tv_tpg_mutex);
23342307
INIT_LIST_HEAD(&tpg->tv_tpg_list);
2335-
INIT_LIST_HEAD(&tpg->tmf_queue);
23362308
tpg->tport = tport;
23372309
tpg->tport_tpgt = tpgt;
23382310

0 commit comments

Comments
 (0)