提交 40bdfdc7 编写于 作者: A Al Viro 提交者: Xie XiuQi

aio_poll(): sanitize the logics after vfs_poll(), get rid of leak on error

euler inclusion
category: bugfix
bugzilla: 10679
CVE: NA

---------------------------

We want iocb_put() happening on errors, to balance the extra reference
we'd taken.  As it is, we end up with a leak.  The rules should be
	* error: iocb_put() to deal with the extra ref, return error,
let the caller do another iocb_put().
	* async: iocb_put() to deal with the extra ref, return 0.
	* no error, event present immediately: aio_poll_complete() to
report it, iocb_put() to deal with the extra ref, return 0.

Link: https://patchwork.kernel.org/patch/10842103/Signed-off-by: NAl Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Nzhengbin <zhengbin13@huawei.com>
Reviewed-by: Nzhangyi (F) <yi.zhang@huawei.com>
Signed-off-by: NYang Yingliang <yangyingliang@huawei.com>
上级 2d9e350d
......@@ -1713,6 +1713,7 @@ static ssize_t aio_poll(struct aio_kiocb *aiocb, struct iocb *iocb)
struct kioctx *ctx = aiocb->ki_ctx;
struct poll_iocb *req = &aiocb->poll;
struct aio_poll_table apt;
bool async = false;
__poll_t mask;
/* reject any unknown events outside the normal event mask. */
......@@ -1754,18 +1755,19 @@ static ssize_t aio_poll(struct aio_kiocb *aiocb, struct iocb *iocb)
spin_lock_irq(&ctx->ctx_lock);
spin_lock(&req->head->lock);
if (req->woken) {
/* wake_up context handles the rest */
mask = 0;
if (req->woken) { /* already taken up by aio_poll_wake() */
async = true;
apt.error = 0;
} else if (mask || apt.error) {
/* if we get an error or a mask we are done */
WARN_ON_ONCE(list_empty(&req->wait.entry));
list_del_init(&req->wait.entry);
} else {
/* actually waiting for an event */
} else if (!mask && !apt.error) { /* actually waiting for an event */
list_add_tail(&aiocb->ki_list, &ctx->active_reqs);
aiocb->ki_cancel = aio_poll_cancel;
async = true;
} else { /* if we get an error or a mask we are done */
WARN_ON_ONCE(list_empty(&req->wait.entry));
list_del_init(&req->wait.entry);
/* no wakeup in the future either;
* aiocb is ours to dispose of
*/
}
spin_unlock(&req->head->lock);
spin_unlock_irq(&ctx->ctx_lock);
......@@ -1775,13 +1777,12 @@ static ssize_t aio_poll(struct aio_kiocb *aiocb, struct iocb *iocb)
fput(req->file);
if (unlikely(apt.error)) {
fput(req->file);
return apt.error;
}
if (mask)
if (!async && !apt.error)
aio_poll_complete(aiocb, mask);
iocb_put(aiocb);
return 0;
return apt.error;
}
static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册