提交 6cbb097f 编写于 作者: A Alexander Usyskin 提交者: Greg Kroah-Hartman

mei: fix double freeing of a cb during link reset

Fix double freeing of the cb that can happen if link reset kicks  in the
middle of blocked write from a device on the cl bus.

Free cb inside mei_cl_write function on failure and drop cb free
operation from callers, during a link reset the mei_cl_write function
returns with an error,  but the caller doesn't know if the cb was
already queued or not so it doesn't know if the cb will be freed upon
queue reclaim or it has to free it itself.
Signed-off-by: NAlexander Usyskin <alexander.usyskin@intel.com>
Signed-off-by: NTomas Winkler <tomas.winkler@intel.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
上级 3ca9b1ac
......@@ -44,7 +44,7 @@ ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
bool blocking)
{
struct mei_device *bus;
struct mei_cl_cb *cb = NULL;
struct mei_cl_cb *cb;
ssize_t rets;
if (WARN_ON(!cl || !cl->dev))
......@@ -86,8 +86,6 @@ ssize_t __mei_cl_send(struct mei_cl *cl, u8 *buf, size_t length,
out:
mutex_unlock(&bus->device_lock);
if (rets < 0)
mei_io_cb_free(cb);
return rets;
}
......
......@@ -1645,7 +1645,7 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
if (rets < 0 && rets != -EINPROGRESS) {
pm_runtime_put_noidle(dev->dev);
cl_err(dev, cl, "rpm: get failed %d\n", rets);
return rets;
goto free;
}
cb->buf_idx = 0;
......@@ -1724,6 +1724,8 @@ int mei_cl_write(struct mei_cl *cl, struct mei_cl_cb *cb, bool blocking)
cl_dbg(dev, cl, "rpm: autosuspend\n");
pm_runtime_mark_last_busy(dev->dev);
pm_runtime_put_autosuspend(dev->dev);
free:
mei_io_cb_free(cb);
return rets;
}
......
......@@ -267,7 +267,7 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
size_t length, loff_t *offset)
{
struct mei_cl *cl = file->private_data;
struct mei_cl_cb *write_cb = NULL;
struct mei_cl_cb *cb;
struct mei_device *dev;
int rets;
......@@ -305,36 +305,30 @@ static ssize_t mei_write(struct file *file, const char __user *ubuf,
}
*offset = 0;
write_cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, file);
if (!write_cb) {
cb = mei_cl_alloc_cb(cl, length, MEI_FOP_WRITE, file);
if (!cb) {
rets = -ENOMEM;
goto out;
}
rets = copy_from_user(write_cb->buf.data, ubuf, length);
rets = copy_from_user(cb->buf.data, ubuf, length);
if (rets) {
dev_dbg(dev->dev, "failed to copy data from userland\n");
rets = -EFAULT;
mei_io_cb_free(cb);
goto out;
}
if (cl == &dev->iamthif_cl) {
rets = mei_amthif_write(cl, write_cb);
if (rets) {
dev_err(dev->dev,
"amthif write failed with status = %d\n", rets);
goto out;
}
mutex_unlock(&dev->device_lock);
return length;
rets = mei_amthif_write(cl, cb);
if (!rets)
rets = length;
goto out;
}
rets = mei_cl_write(cl, write_cb, false);
rets = mei_cl_write(cl, cb, false);
out:
mutex_unlock(&dev->device_lock);
if (rets < 0)
mei_io_cb_free(write_cb);
return rets;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册