From patchwork Thu Mar 7 00:03:09 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Viro X-Patchwork-Id: 1052593 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ZenIV.linux.org.uk Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44F9q46zNhz9s4V for ; Thu, 7 Mar 2019 11:04:32 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726435AbfCGAD3 (ORCPT ); Wed, 6 Mar 2019 19:03:29 -0500 Received: from zeniv.linux.org.uk ([195.92.253.2]:39960 "EHLO ZenIV.linux.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725747AbfCGAD3 (ORCPT ); Wed, 6 Mar 2019 19:03:29 -0500 Received: from viro by ZenIV.linux.org.uk with local (Exim 4.92 #3 (Red Hat Linux)) id 1h1gVI-00086l-VW; Thu, 07 Mar 2019 00:03:17 +0000 From: Al Viro To: Linus Torvalds Cc: Eric Dumazet , David Miller , Jason Baron , kgraul@linux.ibm.com, ktkhai@virtuozzo.com, kyeongdon.kim@lge.com, Linux List Kernel Mailing , Netdev , pabeni@redhat.com, syzkaller-bugs@googlegroups.com, xiyou.wangcong@gmail.com, Christoph Hellwig , zhengbin , bcrl@kvack.org, linux-fsdevel@vger.kernel.org, linux-aio@kvack.org, houtao1@huawei.com, yi.zhang@huawei.com Subject: [PATCH 1/8] aio: make sure file is pinned Date: Thu, 7 Mar 2019 00:03:09 +0000 Message-Id: <20190307000316.31133-1-viro@ZenIV.linux.org.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: References: MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Al Viro "aio: remove the extra get_file/fput pair in io_submit_one" was too optimistic - not dereferencing file pointer after e.g. ->write_iter() returns is not enough; that reference might've been the only thing that kept alive objects that are referenced *before* the method returns. Such as inode, for example... Signed-off-by: Al Viro --- fs/aio.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/aio.c b/fs/aio.c index 3d9669d011b9..ea30b78187ed 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1790,6 +1790,7 @@ static int __io_submit_one(struct kioctx *ctx, const struct iocb *iocb, struct iocb __user *user_iocb, bool compat) { struct aio_kiocb *req; + struct file *file; ssize_t ret; /* enforce forwards compatibility on users */ @@ -1844,6 +1845,7 @@ static int __io_submit_one(struct kioctx *ctx, const struct iocb *iocb, req->ki_user_iocb = user_iocb; req->ki_user_data = iocb->aio_data; + file = get_file(req->ki_filp); /* req can die too early */ switch (iocb->aio_lio_opcode) { case IOCB_CMD_PREAD: @@ -1872,6 +1874,7 @@ static int __io_submit_one(struct kioctx *ctx, const struct iocb *iocb, ret = -EINVAL; break; } + fput(file); /* * If ret is 0, we'd either done aio_complete() ourselves or have From patchwork Thu Mar 7 00:03:10 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Viro X-Patchwork-Id: 1052592 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ZenIV.linux.org.uk Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44F9pw1gHsz9s4Y for ; Thu, 7 Mar 2019 11:04:24 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726414AbfCGAEX (ORCPT ); Wed, 6 Mar 2019 19:04:23 -0500 Received: from zeniv.linux.org.uk ([195.92.253.2]:39966 "EHLO ZenIV.linux.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726101AbfCGAD3 (ORCPT ); Wed, 6 Mar 2019 19:03:29 -0500 Received: from viro by ZenIV.linux.org.uk with local (Exim 4.92 #3 (Red Hat Linux)) id 1h1gVJ-00086o-4P; Thu, 07 Mar 2019 00:03:17 +0000 From: Al Viro To: Linus Torvalds Cc: Eric Dumazet , David Miller , Jason Baron , kgraul@linux.ibm.com, ktkhai@virtuozzo.com, kyeongdon.kim@lge.com, Linux List Kernel Mailing , Netdev , pabeni@redhat.com, syzkaller-bugs@googlegroups.com, xiyou.wangcong@gmail.com, Christoph Hellwig , zhengbin , bcrl@kvack.org, linux-fsdevel@vger.kernel.org, linux-aio@kvack.org, houtao1@huawei.com, yi.zhang@huawei.com Subject: [PATCH 2/8] aio_poll_wake(): don't set ->woken if we ignore the wakeup Date: Thu, 7 Mar 2019 00:03:10 +0000 Message-Id: <20190307000316.31133-2-viro@ZenIV.linux.org.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190307000316.31133-1-viro@ZenIV.linux.org.uk> References: <20190307000316.31133-1-viro@ZenIV.linux.org.uk> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Al Viro In case of early wakeups, aio_poll() assumes that aio_poll_complete() has either already happened or is imminent. In that case we do not want to put iocb on the list of cancellables. However, ignored wakeups need to be treated as if wakeup has not happened at all. Trivially fixed by having aio_poll_wake() set ->woken only after it's committed to taking iocb out of the waitqueue. Spotted-by: zhengbin Signed-off-by: Al Viro --- fs/aio.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/aio.c b/fs/aio.c index ea30b78187ed..3a8b894378e0 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1668,13 +1668,13 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync, __poll_t mask = key_to_poll(key); unsigned long flags; + /* for instances that support it check for an event match first: */ + if (mask && !(mask & req->events)) + return 0; + req->woken = true; - /* for instances that support it check for an event match first: */ if (mask) { - if (!(mask & req->events)) - return 0; - /* * Try to complete the iocb inline if we can. Use * irqsave/irqrestore because not all filesystems (e.g. fuse) From patchwork Thu Mar 7 00:03:11 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Viro X-Patchwork-Id: 1052591 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ZenIV.linux.org.uk Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44F9pq2W3Jz9s4Y for ; Thu, 7 Mar 2019 11:04:19 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726567AbfCGAD3 (ORCPT ); Wed, 6 Mar 2019 19:03:29 -0500 Received: from zeniv.linux.org.uk ([195.92.253.2]:39962 "EHLO ZenIV.linux.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1725793AbfCGAD3 (ORCPT ); Wed, 6 Mar 2019 19:03:29 -0500 Received: from viro by ZenIV.linux.org.uk with local (Exim 4.92 #3 (Red Hat Linux)) id 1h1gVJ-00086s-8T; Thu, 07 Mar 2019 00:03:17 +0000 From: Al Viro To: Linus Torvalds Cc: Eric Dumazet , David Miller , Jason Baron , kgraul@linux.ibm.com, ktkhai@virtuozzo.com, kyeongdon.kim@lge.com, Linux List Kernel Mailing , Netdev , pabeni@redhat.com, syzkaller-bugs@googlegroups.com, xiyou.wangcong@gmail.com, Christoph Hellwig , zhengbin , bcrl@kvack.org, linux-fsdevel@vger.kernel.org, linux-aio@kvack.org, houtao1@huawei.com, yi.zhang@huawei.com Subject: [PATCH 3/8] aio_poll(): sanitize the logics after vfs_poll(), get rid of leak on error Date: Thu, 7 Mar 2019 00:03:11 +0000 Message-Id: <20190307000316.31133-3-viro@ZenIV.linux.org.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190307000316.31133-1-viro@ZenIV.linux.org.uk> References: <20190307000316.31133-1-viro@ZenIV.linux.org.uk> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Al Viro 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. Signed-off-by: Al Viro --- fs/aio.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/fs/aio.c b/fs/aio.c index 3a8b894378e0..22b288997441 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1724,6 +1724,7 @@ static ssize_t aio_poll(struct aio_kiocb *aiocb, const 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. */ @@ -1760,30 +1761,26 @@ static ssize_t aio_poll(struct aio_kiocb *aiocb, const 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); out: - if (unlikely(apt.error)) - 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, const struct iocb *iocb, From patchwork Thu Mar 7 00:03:12 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Viro X-Patchwork-Id: 1052589 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ZenIV.linux.org.uk Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44F9pS6Kc2z9sB3 for ; Thu, 7 Mar 2019 11:04:00 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726586AbfCGADz (ORCPT ); Wed, 6 Mar 2019 19:03:55 -0500 Received: from zeniv.linux.org.uk ([195.92.253.2]:39968 "EHLO ZenIV.linux.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726226AbfCGADa (ORCPT ); Wed, 6 Mar 2019 19:03:30 -0500 Received: from viro by ZenIV.linux.org.uk with local (Exim 4.92 #3 (Red Hat Linux)) id 1h1gVJ-00086w-Bj; Thu, 07 Mar 2019 00:03:17 +0000 From: Al Viro To: Linus Torvalds Cc: Eric Dumazet , David Miller , Jason Baron , kgraul@linux.ibm.com, ktkhai@virtuozzo.com, kyeongdon.kim@lge.com, Linux List Kernel Mailing , Netdev , pabeni@redhat.com, syzkaller-bugs@googlegroups.com, xiyou.wangcong@gmail.com, Christoph Hellwig , zhengbin , bcrl@kvack.org, linux-fsdevel@vger.kernel.org, linux-aio@kvack.org, houtao1@huawei.com, yi.zhang@huawei.com Subject: [PATCH 4/8] aio_poll(): get rid of weird refcounting Date: Thu, 7 Mar 2019 00:03:12 +0000 Message-Id: <20190307000316.31133-4-viro@ZenIV.linux.org.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190307000316.31133-1-viro@ZenIV.linux.org.uk> References: <20190307000316.31133-1-viro@ZenIV.linux.org.uk> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Al Viro The only reason for taking the extra ref to iocb is that we want to access it after vfs_poll() and an early wakeup could have it already completed by the time vfs_poll() returns. That's very easy to avoid, though - we need to know which lock to grab and, having grabbed it, we need to check if an early wakeup has already happened. So let's just copy the reference to waitqueue into aio_poll_table and instead of having the "woken" flag in iocb, move it to aio_poll() stack frame and put its address into iocb (and make sure it's cleared, so aio_poll_wake() won't step onto it after aio_poll() exits). That's enough to get rid of the refcount. In async case freeing is done by aio_poll_complete() (and aio_poll() will only touch the iocb past the vfs_poll() if it's guaranteed that aio_poll_complete() has not happened yet), in all other cases we make sure that wakeups hadn't and won't happen and deal with disposal of iocb ourselves. Signed-off-by: Al Viro --- fs/aio.c | 55 +++++++++++++++++++++++++++---------------------------- 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/fs/aio.c b/fs/aio.c index 22b288997441..ee062253e303 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -180,8 +180,8 @@ struct fsync_iocb { struct poll_iocb { struct file *file; struct wait_queue_head *head; + bool *taken; __poll_t events; - bool woken; bool cancelled; struct wait_queue_entry wait; struct work_struct work; @@ -209,8 +209,6 @@ struct aio_kiocb { struct list_head ki_list; /* the aio core uses this * for cancellation */ - refcount_t ki_refcnt; - /* * If the aio_resfd field of the userspace iocb is not zero, * this is the underlying eventfd context to deliver events to. @@ -1034,7 +1032,6 @@ static inline struct aio_kiocb *aio_get_req(struct kioctx *ctx) percpu_ref_get(&ctx->reqs); req->ki_ctx = ctx; INIT_LIST_HEAD(&req->ki_list); - refcount_set(&req->ki_refcnt, 0); req->ki_eventfd = NULL; return req; } @@ -1069,13 +1066,10 @@ static struct kioctx *lookup_ioctx(unsigned long ctx_id) static inline void iocb_put(struct aio_kiocb *iocb) { - if (refcount_read(&iocb->ki_refcnt) == 0 || - refcount_dec_and_test(&iocb->ki_refcnt)) { - if (iocb->ki_filp) - fput(iocb->ki_filp); - percpu_ref_put(&iocb->ki_ctx->reqs); - kmem_cache_free(kiocb_cachep, iocb); - } + if (iocb->ki_filp) + fput(iocb->ki_filp); + percpu_ref_put(&iocb->ki_ctx->reqs); + kmem_cache_free(kiocb_cachep, iocb); } static void aio_fill_event(struct io_event *ev, struct aio_kiocb *iocb, @@ -1672,8 +1666,10 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync, if (mask && !(mask & req->events)) return 0; - req->woken = true; - + if (unlikely(req->taken)) { + *req->taken = true; + req->taken = NULL; + } if (mask) { /* * Try to complete the iocb inline if we can. Use @@ -1698,6 +1694,7 @@ static int aio_poll_wake(struct wait_queue_entry *wait, unsigned mode, int sync, struct aio_poll_table { struct poll_table_struct pt; + struct wait_queue_head *head; struct aio_kiocb *iocb; int error; }; @@ -1715,7 +1712,7 @@ aio_poll_queue_proc(struct file *file, struct wait_queue_head *head, } pt->error = 0; - pt->iocb->poll.head = head; + pt->head = pt->iocb->poll.head = head; add_wait_queue(head, &pt->iocb->poll.wait); } @@ -1738,7 +1735,7 @@ static ssize_t aio_poll(struct aio_kiocb *aiocb, const struct iocb *iocb) req->events = demangle_poll(iocb->aio_buf) | EPOLLERR | EPOLLHUP; req->head = NULL; - req->woken = false; + req->taken = &async; req->cancelled = false; apt.pt._qproc = aio_poll_queue_proc; @@ -1750,36 +1747,38 @@ static ssize_t aio_poll(struct aio_kiocb *aiocb, const struct iocb *iocb) INIT_LIST_HEAD(&req->wait.entry); init_waitqueue_func_entry(&req->wait, aio_poll_wake); - /* one for removal from waitqueue, one for this function */ - refcount_set(&aiocb->ki_refcnt, 2); - - mask = vfs_poll(req->file, &apt.pt) & req->events; - if (unlikely(!req->head)) { + mask = req->events; + mask &= vfs_poll(req->file, &apt.pt); + /* + * Careful: we might've been put into waitqueue *and* already + * woken up before vfs_poll() returns. The caller is holding + * a reference to file, so it couldn't have been killed under + * us, no matter what. However, in case of early wakeup, @req + * might be already gone by now. + */ + if (unlikely(!apt.head)) { /* we did not manage to set up a waitqueue, done */ goto out; } - spin_lock_irq(&ctx->ctx_lock); - spin_lock(&req->head->lock); - if (req->woken) { /* already taken up by aio_poll_wake() */ - async = true; + spin_lock(&apt.head->lock); + if (async) { /* already taken up by aio_poll_wake() */ apt.error = 0; } 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; + req->taken = NULL; 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(&apt.head->lock); spin_unlock_irq(&ctx->ctx_lock); - out: - if (async && !apt.error) + if (!async && !apt.error) aio_poll_complete(aiocb, mask); - iocb_put(aiocb); return apt.error; } From patchwork Thu Mar 7 00:03:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Viro X-Patchwork-Id: 1052590 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ZenIV.linux.org.uk Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44F9pf5dJVz9sB3 for ; Thu, 7 Mar 2019 11:04:10 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726649AbfCGAEF (ORCPT ); Wed, 6 Mar 2019 19:04:05 -0500 Received: from zeniv.linux.org.uk ([195.92.253.2]:39976 "EHLO ZenIV.linux.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726307AbfCGADa (ORCPT ); Wed, 6 Mar 2019 19:03:30 -0500 Received: from viro by ZenIV.linux.org.uk with local (Exim 4.92 #3 (Red Hat Linux)) id 1h1gVJ-000870-Ey; Thu, 07 Mar 2019 00:03:17 +0000 From: Al Viro To: Linus Torvalds Cc: Eric Dumazet , David Miller , Jason Baron , kgraul@linux.ibm.com, ktkhai@virtuozzo.com, kyeongdon.kim@lge.com, Linux List Kernel Mailing , Netdev , pabeni@redhat.com, syzkaller-bugs@googlegroups.com, xiyou.wangcong@gmail.com, Christoph Hellwig , zhengbin , bcrl@kvack.org, linux-fsdevel@vger.kernel.org, linux-aio@kvack.org, houtao1@huawei.com, yi.zhang@huawei.com Subject: [PATCH 5/8] make aio_read()/aio_write() return int Date: Thu, 7 Mar 2019 00:03:13 +0000 Message-Id: <20190307000316.31133-5-viro@ZenIV.linux.org.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190307000316.31133-1-viro@ZenIV.linux.org.uk> References: <20190307000316.31133-1-viro@ZenIV.linux.org.uk> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Al Viro that ssize_t is a rudiment of earlier calling conventions; it's been used only to pass 0 and -E... since last autumn. Signed-off-by: Al Viro --- fs/aio.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/aio.c b/fs/aio.c index ee062253e303..5dd5f35d054c 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1508,13 +1508,13 @@ static inline void aio_rw_done(struct kiocb *req, ssize_t ret) } } -static ssize_t aio_read(struct kiocb *req, const struct iocb *iocb, +static int aio_read(struct kiocb *req, const struct iocb *iocb, bool vectored, bool compat) { struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs; struct iov_iter iter; struct file *file; - ssize_t ret; + int ret; ret = aio_prep_rw(req, iocb); if (ret) @@ -1536,13 +1536,13 @@ static ssize_t aio_read(struct kiocb *req, const struct iocb *iocb, return ret; } -static ssize_t aio_write(struct kiocb *req, const struct iocb *iocb, +static int aio_write(struct kiocb *req, const struct iocb *iocb, bool vectored, bool compat) { struct iovec inline_vecs[UIO_FASTIOV], *iovec = inline_vecs; struct iov_iter iter; struct file *file; - ssize_t ret; + int ret; ret = aio_prep_rw(req, iocb); if (ret) @@ -1716,7 +1716,7 @@ aio_poll_queue_proc(struct file *file, struct wait_queue_head *head, add_wait_queue(head, &pt->iocb->poll.wait); } -static ssize_t aio_poll(struct aio_kiocb *aiocb, const struct iocb *iocb) +static int aio_poll(struct aio_kiocb *aiocb, const struct iocb *iocb) { struct kioctx *ctx = aiocb->ki_ctx; struct poll_iocb *req = &aiocb->poll; @@ -1787,7 +1787,7 @@ static int __io_submit_one(struct kioctx *ctx, const struct iocb *iocb, { struct aio_kiocb *req; struct file *file; - ssize_t ret; + int ret; /* enforce forwards compatibility on users */ if (unlikely(iocb->aio_reserved2)) { From patchwork Thu Mar 7 00:03:14 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Viro X-Patchwork-Id: 1052588 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ZenIV.linux.org.uk Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44F9pF0SqZz9sD4 for ; Thu, 7 Mar 2019 11:03:49 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726760AbfCGADg (ORCPT ); Wed, 6 Mar 2019 19:03:36 -0500 Received: from zeniv.linux.org.uk ([195.92.253.2]:40004 "EHLO ZenIV.linux.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726422AbfCGADf (ORCPT ); Wed, 6 Mar 2019 19:03:35 -0500 Received: from viro by ZenIV.linux.org.uk with local (Exim 4.92 #3 (Red Hat Linux)) id 1h1gVJ-000874-He; Thu, 07 Mar 2019 00:03:17 +0000 From: Al Viro To: Linus Torvalds Cc: Eric Dumazet , David Miller , Jason Baron , kgraul@linux.ibm.com, ktkhai@virtuozzo.com, kyeongdon.kim@lge.com, Linux List Kernel Mailing , Netdev , pabeni@redhat.com, syzkaller-bugs@googlegroups.com, xiyou.wangcong@gmail.com, Christoph Hellwig , zhengbin , bcrl@kvack.org, linux-fsdevel@vger.kernel.org, linux-aio@kvack.org, houtao1@huawei.com, yi.zhang@huawei.com Subject: [PATCH 6/8] move dropping ->ki_eventfd into iocb_put() Date: Thu, 7 Mar 2019 00:03:14 +0000 Message-Id: <20190307000316.31133-6-viro@ZenIV.linux.org.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190307000316.31133-1-viro@ZenIV.linux.org.uk> References: <20190307000316.31133-1-viro@ZenIV.linux.org.uk> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Al Viro Signed-off-by: Al Viro --- fs/aio.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/fs/aio.c b/fs/aio.c index 5dd5f35d054c..5837a29e63fe 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1066,6 +1066,8 @@ static struct kioctx *lookup_ioctx(unsigned long ctx_id) static inline void iocb_put(struct aio_kiocb *iocb) { + if (iocb->ki_eventfd) + eventfd_ctx_put(iocb->ki_eventfd); if (iocb->ki_filp) fput(iocb->ki_filp); percpu_ref_put(&iocb->ki_ctx->reqs); @@ -1142,10 +1144,8 @@ static void aio_complete(struct aio_kiocb *iocb, long res, long res2) * eventfd. The eventfd_signal() function is safe to be called * from IRQ context. */ - if (iocb->ki_eventfd) { + if (iocb->ki_eventfd) eventfd_signal(iocb->ki_eventfd, 1); - eventfd_ctx_put(iocb->ki_eventfd); - } /* * We have to order our ring_info tail store above and test @@ -1819,18 +1819,19 @@ static int __io_submit_one(struct kioctx *ctx, const struct iocb *iocb, goto out_put_req; if (iocb->aio_flags & IOCB_FLAG_RESFD) { + struct eventfd_ctx *eventfd; /* * If the IOCB_FLAG_RESFD flag of aio_flags is set, get an * instance of the file* now. The file descriptor must be * an eventfd() fd, and will be signaled for each completed * event using the eventfd_signal() function. */ - req->ki_eventfd = eventfd_ctx_fdget((int) iocb->aio_resfd); - if (IS_ERR(req->ki_eventfd)) { - ret = PTR_ERR(req->ki_eventfd); - req->ki_eventfd = NULL; + eventfd = eventfd_ctx_fdget((int) iocb->aio_resfd); + if (IS_ERR(eventfd)) { + ret = PTR_ERR(eventfd); goto out_put_req; } + req->ki_eventfd = eventfd; } ret = put_user(KIOCB_KEY, &user_iocb->aio_key); @@ -1881,8 +1882,6 @@ static int __io_submit_one(struct kioctx *ctx, const struct iocb *iocb, goto out_put_req; return 0; out_put_req: - if (req->ki_eventfd) - eventfd_ctx_put(req->ki_eventfd); iocb_put(req); out_put_reqs_available: put_reqs_available(ctx, 1); From patchwork Thu Mar 7 00:03:15 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Viro X-Patchwork-Id: 1052587 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ZenIV.linux.org.uk Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44F9p76S0Hz9s4V for ; Thu, 7 Mar 2019 11:03:43 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726791AbfCGADg (ORCPT ); Wed, 6 Mar 2019 19:03:36 -0500 Received: from zeniv.linux.org.uk ([195.92.253.2]:39996 "EHLO ZenIV.linux.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726299AbfCGADf (ORCPT ); Wed, 6 Mar 2019 19:03:35 -0500 Received: from viro by ZenIV.linux.org.uk with local (Exim 4.92 #3 (Red Hat Linux)) id 1h1gVJ-000878-K6; Thu, 07 Mar 2019 00:03:17 +0000 From: Al Viro To: Linus Torvalds Cc: Eric Dumazet , David Miller , Jason Baron , kgraul@linux.ibm.com, ktkhai@virtuozzo.com, kyeongdon.kim@lge.com, Linux List Kernel Mailing , Netdev , pabeni@redhat.com, syzkaller-bugs@googlegroups.com, xiyou.wangcong@gmail.com, Christoph Hellwig , zhengbin , bcrl@kvack.org, linux-fsdevel@vger.kernel.org, linux-aio@kvack.org, houtao1@huawei.com, yi.zhang@huawei.com Subject: [PATCH 7/8] deal with get_reqs_available() in aio_get_req() itself Date: Thu, 7 Mar 2019 00:03:15 +0000 Message-Id: <20190307000316.31133-7-viro@ZenIV.linux.org.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190307000316.31133-1-viro@ZenIV.linux.org.uk> References: <20190307000316.31133-1-viro@ZenIV.linux.org.uk> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Al Viro simplifies the caller Signed-off-by: Al Viro --- fs/aio.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/fs/aio.c b/fs/aio.c index 5837a29e63fe..af51b1360305 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1029,6 +1029,11 @@ static inline struct aio_kiocb *aio_get_req(struct kioctx *ctx) if (unlikely(!req)) return NULL; + if (unlikely(!get_reqs_available(ctx))) { + kfree(req); + return NULL; + } + percpu_ref_get(&ctx->reqs); req->ki_ctx = ctx; INIT_LIST_HEAD(&req->ki_list); @@ -1805,13 +1810,9 @@ static int __io_submit_one(struct kioctx *ctx, const struct iocb *iocb, return -EINVAL; } - if (!get_reqs_available(ctx)) - return -EAGAIN; - - ret = -EAGAIN; req = aio_get_req(ctx); if (unlikely(!req)) - goto out_put_reqs_available; + return -EAGAIN; req->ki_filp = fget(iocb->aio_fildes); ret = -EBADF; @@ -1883,7 +1884,6 @@ static int __io_submit_one(struct kioctx *ctx, const struct iocb *iocb, return 0; out_put_req: iocb_put(req); -out_put_reqs_available: put_reqs_available(ctx, 1); return ret; } From patchwork Thu Mar 7 00:03:16 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Al Viro X-Patchwork-Id: 1052586 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming-netdev@ozlabs.org Delivered-To: patchwork-incoming-netdev@ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=vger.kernel.org (client-ip=209.132.180.67; helo=vger.kernel.org; envelope-from=netdev-owner@vger.kernel.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ZenIV.linux.org.uk Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 44F9nv2dNbz9s4V for ; Thu, 7 Mar 2019 11:03:31 +1100 (AEDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1725747AbfCGAD3 (ORCPT ); Wed, 6 Mar 2019 19:03:29 -0500 Received: from zeniv.linux.org.uk ([195.92.253.2]:39972 "EHLO ZenIV.linux.org.uk" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726299AbfCGAD3 (ORCPT ); Wed, 6 Mar 2019 19:03:29 -0500 Received: from viro by ZenIV.linux.org.uk with local (Exim 4.92 #3 (Red Hat Linux)) id 1h1gVJ-00087C-N4; Thu, 07 Mar 2019 00:03:17 +0000 From: Al Viro To: Linus Torvalds Cc: Eric Dumazet , David Miller , Jason Baron , kgraul@linux.ibm.com, ktkhai@virtuozzo.com, kyeongdon.kim@lge.com, Linux List Kernel Mailing , Netdev , pabeni@redhat.com, syzkaller-bugs@googlegroups.com, xiyou.wangcong@gmail.com, Christoph Hellwig , zhengbin , bcrl@kvack.org, linux-fsdevel@vger.kernel.org, linux-aio@kvack.org, houtao1@huawei.com, yi.zhang@huawei.com Subject: [PATCH 8/8] aio: move sanity checks and request allocation to io_submit_one() Date: Thu, 7 Mar 2019 00:03:16 +0000 Message-Id: <20190307000316.31133-8-viro@ZenIV.linux.org.uk> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190307000316.31133-1-viro@ZenIV.linux.org.uk> References: <20190307000316.31133-1-viro@ZenIV.linux.org.uk> MIME-Version: 1.0 Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Al Viro makes for somewhat cleaner control flow in __io_submit_one() Signed-off-by: Al Viro --- fs/aio.c | 86 +++++++++++++++++++++++++++++++--------------------------------- 1 file changed, 42 insertions(+), 44 deletions(-) diff --git a/fs/aio.c b/fs/aio.c index af51b1360305..6993581b77b2 100644 --- a/fs/aio.c +++ b/fs/aio.c @@ -1788,36 +1788,15 @@ static int aio_poll(struct aio_kiocb *aiocb, const struct iocb *iocb) } static int __io_submit_one(struct kioctx *ctx, const struct iocb *iocb, - struct iocb __user *user_iocb, bool compat) + struct iocb __user *user_iocb, struct aio_kiocb *req, + bool compat) { - struct aio_kiocb *req; struct file *file; int ret; - /* enforce forwards compatibility on users */ - if (unlikely(iocb->aio_reserved2)) { - pr_debug("EINVAL: reserve field set\n"); - return -EINVAL; - } - - /* prevent overflows */ - if (unlikely( - (iocb->aio_buf != (unsigned long)iocb->aio_buf) || - (iocb->aio_nbytes != (size_t)iocb->aio_nbytes) || - ((ssize_t)iocb->aio_nbytes < 0) - )) { - pr_debug("EINVAL: overflow check\n"); - return -EINVAL; - } - - req = aio_get_req(ctx); - if (unlikely(!req)) - return -EAGAIN; - req->ki_filp = fget(iocb->aio_fildes); - ret = -EBADF; if (unlikely(!req->ki_filp)) - goto out_put_req; + return -EBADF; if (iocb->aio_flags & IOCB_FLAG_RESFD) { struct eventfd_ctx *eventfd; @@ -1828,17 +1807,15 @@ static int __io_submit_one(struct kioctx *ctx, const struct iocb *iocb, * event using the eventfd_signal() function. */ eventfd = eventfd_ctx_fdget((int) iocb->aio_resfd); - if (IS_ERR(eventfd)) { - ret = PTR_ERR(eventfd); - goto out_put_req; - } + if (IS_ERR(eventfd)) + return PTR_ERR(req->ki_eventfd); + req->ki_eventfd = eventfd; } - ret = put_user(KIOCB_KEY, &user_iocb->aio_key); - if (unlikely(ret)) { + if (unlikely(put_user(KIOCB_KEY, &user_iocb->aio_key))) { pr_debug("EFAULT: aio_key\n"); - goto out_put_req; + return -EFAULT; } req->ki_user_iocb = user_iocb; @@ -1873,30 +1850,51 @@ static int __io_submit_one(struct kioctx *ctx, const struct iocb *iocb, break; } fput(file); - - /* - * If ret is 0, we'd either done aio_complete() ourselves or have - * arranged for that to be done asynchronously. Anything non-zero - * means that we need to destroy req ourselves. - */ - if (ret) - goto out_put_req; - return 0; -out_put_req: - iocb_put(req); - put_reqs_available(ctx, 1); return ret; } static int io_submit_one(struct kioctx *ctx, struct iocb __user *user_iocb, bool compat) { + struct aio_kiocb *req; struct iocb iocb; + int err; if (unlikely(copy_from_user(&iocb, user_iocb, sizeof(iocb)))) return -EFAULT; - return __io_submit_one(ctx, &iocb, user_iocb, compat); + /* enforce forwards compatibility on users */ + if (unlikely(iocb.aio_reserved2)) { + pr_debug("EINVAL: reserve field set\n"); + return -EINVAL; + } + + /* prevent overflows */ + if (unlikely( + (iocb.aio_buf != (unsigned long)iocb.aio_buf) || + (iocb.aio_nbytes != (size_t)iocb.aio_nbytes) || + ((ssize_t)iocb.aio_nbytes < 0) + )) { + pr_debug("EINVAL: overflow check\n"); + return -EINVAL; + } + + req = aio_get_req(ctx); + if (unlikely(!req)) + return -EAGAIN; + + err = __io_submit_one(ctx, &iocb, user_iocb, req, compat); + + /* + * If err is 0, we'd either done aio_complete() ourselves or have + * arranged for that to be done asynchronously. Anything non-zero + * means that we need to destroy req ourselves. + */ + if (unlikely(err)) { + iocb_put(req); + put_reqs_available(ctx, 1); + } + return err; } /* sys_io_submit: