From 09d719a009c149414c8c2b1b5deee87f19236ed4 Mon Sep 17 00:00:00 2001 From: Israel Rukshin Date: Wed, 17 Aug 2016 07:28:29 +0000 Subject: [PATCH] isert: fix races between conn fops read/write and disconnect flow read/write events may arive after the isert connection has started the teardown flow. This scenario may occur on login logout stress. It may lead to NULL derefrence bugs. Signed-off-by: Israel Rukshin git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@6953 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- iscsi-scst/kernel/isert-scst/isert_login.c | 40 +++++++++++++++++----- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/iscsi-scst/kernel/isert-scst/isert_login.c b/iscsi-scst/kernel/isert-scst/isert_login.c index 30ca54915..af45f4595 100644 --- a/iscsi-scst/kernel/isert-scst/isert_login.c +++ b/iscsi-scst/kernel/isert-scst/isert_login.c @@ -594,23 +594,33 @@ static ssize_t isert_read(struct file *filp, char __user *buf, size_t count, struct isert_conn_dev *dev = filp->private_data; size_t to_read; - if (dev->state == CS_DISCONNECTED) + mutex_lock(&conn_mgmt_mutex); + + if (dev->state == CS_DISCONNECTED) { + mutex_unlock(&conn_mgmt_mutex); return -EPIPE; + } if (will_read_block(dev)) { int ret; - if (filp->f_flags & O_NONBLOCK) + if (filp->f_flags & O_NONBLOCK) { + mutex_unlock(&conn_mgmt_mutex); return -EAGAIN; + } ret = wait_event_freezable(dev->waitqueue, !will_read_block(dev)); - if (ret < 0) + if (ret < 0) { + mutex_unlock(&conn_mgmt_mutex); return ret; + } } to_read = min(count, dev->read_len); - if (copy_to_user(buf, dev->read_buf, to_read)) + if (copy_to_user(buf, dev->read_buf, to_read)) { + mutex_unlock(&conn_mgmt_mutex); return -EFAULT; + } dev->read_len -= to_read; dev->read_buf += to_read; @@ -622,8 +632,10 @@ static ssize_t isert_read(struct file *filp, char __user *buf, size_t count, dev->sg_virt = isert_vmap_sg(dev->pages, dev->login_req->sg, dev->login_req->sg_cnt); - if (!dev->sg_virt) + if (!dev->sg_virt) { + mutex_unlock(&conn_mgmt_mutex); return -ENOMEM; + } dev->read_buf = dev->sg_virt + ISER_HDRS_SZ; dev->state = CS_REQ_DATA; } @@ -646,6 +658,8 @@ static ssize_t isert_read(struct file *filp, char __user *buf, size_t count, to_read = 0; } + mutex_unlock(&conn_mgmt_mutex); + return to_read; } @@ -655,12 +669,18 @@ static ssize_t isert_write(struct file *filp, const char __user *buf, struct isert_conn_dev *dev = filp->private_data; size_t to_write; - if (dev->state == CS_DISCONNECTED) + mutex_lock(&conn_mgmt_mutex); + + if (dev->state == CS_DISCONNECTED) { + mutex_unlock(&conn_mgmt_mutex); return -EPIPE; + } to_write = min(count, dev->write_len); - if (copy_from_user(dev->write_buf, buf, to_write)) + if (copy_from_user(dev->write_buf, buf, to_write)) { + mutex_unlock(&conn_mgmt_mutex); return -EFAULT; + } dev->write_len -= to_write; dev->write_buf += to_write; @@ -672,8 +692,10 @@ static ssize_t isert_write(struct file *filp, const char __user *buf, dev->sg_virt = isert_vmap_sg(dev->pages, dev->login_rsp->sg, dev->login_rsp->sg_cnt); - if (!dev->sg_virt) + if (!dev->sg_virt) { + mutex_unlock(&conn_mgmt_mutex); return -ENOMEM; + } dev->write_buf = dev->sg_virt + ISER_HDRS_SZ; dev->write_len = dev->login_rsp->bufflen - sizeof(dev->login_rsp->pdu.bhs); @@ -689,6 +711,8 @@ static ssize_t isert_write(struct file *filp, const char __user *buf, to_write = 0; } + mutex_unlock(&conn_mgmt_mutex); + return to_write; }