* [PATCH] io_uring: Fix leaking double_put()
@ 2019-11-12 8:17 Pavel Begunkov
2019-11-12 15:02 ` Jens Axboe
0 siblings, 1 reply; 3+ messages in thread
From: Pavel Begunkov @ 2019-11-12 8:17 UTC (permalink / raw)
To: Jens Axboe, io-uring
io_double_put_req() may be called for a request with a link (see
io_req_defer(req)), and so can leak it in case of an error, as
__io_free_req() doesn't handle links.
Fixes: 78e19bbef38362ceb ("io_uring: pass in io_kiocb to fill/add CQ
handlers")
Signed-off-by: Pavel Begunkov <[email protected]>
---
fs/io_uring.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/fs/io_uring.c b/fs/io_uring.c
index 18711d45b994..82f139ebdbbc 100644
--- a/fs/io_uring.c
+++ b/fs/io_uring.c
@@ -376,7 +376,6 @@ static void io_wq_submit_work(struct io_wq_work **workptr);
static void io_cqring_fill_event(struct io_kiocb *req, long res);
static void __io_free_req(struct io_kiocb *req);
static void io_put_req(struct io_kiocb *req);
-static void io_double_put_req(struct io_kiocb *req);
static struct kmem_cache *req_cachep;
@@ -930,7 +929,8 @@ static void io_fail_links(struct io_kiocb *req)
io_link_cancel_timeout(link);
} else {
io_cqring_fill_event(link, -ECANCELED);
- io_double_put_req(link);
+ if (refcount_sub_and_test(2, &req->refs))
+ __io_free_req(req);
}
}
@@ -1007,7 +1007,7 @@ static void io_double_put_req(struct io_kiocb *req)
{
/* drop both submit and complete references */
if (refcount_sub_and_test(2, &req->refs))
- __io_free_req(req);
+ io_free_req(req);
}
static unsigned io_cqring_events(struct io_ring_ctx *ctx, bool noflush)
@@ -2830,6 +2830,8 @@ static int io_queue_sqe(struct io_kiocb *req)
if (ret) {
if (ret != -EIOCBQUEUED) {
io_cqring_add_event(req, ret);
+ if (req->flags & REQ_F_LINK)
+ req->flags |= REQ_F_FAIL_LINK;
io_double_put_req(req);
}
return 0;
@@ -2857,6 +2859,8 @@ static int io_queue_link_head(struct io_kiocb *req, struct io_kiocb *shadow)
if (ret) {
if (ret != -EIOCBQUEUED) {
io_cqring_add_event(req, ret);
+ if (req->flags & REQ_F_LINK)
+ req->flags |= REQ_F_FAIL_LINK;
io_double_put_req(req);
__io_free_req(shadow);
return 0;
@@ -2903,6 +2907,8 @@ static void io_submit_sqe(struct io_kiocb *req, struct io_submit_state *state,
if (unlikely(ret)) {
err_req:
io_cqring_add_event(req, ret);
+ if (req->flags & REQ_F_LINK)
+ req->flags |= REQ_F_FAIL_LINK;
io_double_put_req(req);
return;
}
--
2.24.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] io_uring: Fix leaking double_put()
2019-11-12 8:17 [PATCH] io_uring: Fix leaking double_put() Pavel Begunkov
@ 2019-11-12 15:02 ` Jens Axboe
2019-11-12 20:11 ` Pavel Begunkov
0 siblings, 1 reply; 3+ messages in thread
From: Jens Axboe @ 2019-11-12 15:02 UTC (permalink / raw)
To: Pavel Begunkov, io-uring
On 11/12/19 12:17 AM, Pavel Begunkov wrote:
> io_double_put_req() may be called for a request with a link (see
> io_req_defer(req)), and so can leak it in case of an error, as
> __io_free_req() doesn't handle links.
>
> Fixes: 78e19bbef38362ceb ("io_uring: pass in io_kiocb to fill/add CQ
> handlers")
This blows up the 'link' test from the liburing regression suite:
[ 20.007180] refcount_t: underflow; use-after-free.
[ 20.008562] WARNING: CPU: 0 PID: 278 at lib/refcount.c:190 refcount_sub_and_test_checked+0xf3/0x100
[ 20.010784] Modules linked in:
[ 20.011565] CPU: 0 PID: 278 Comm: link Not tainted 5.4.0-rc5+ #3490
[ 20.013112] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.10.2-1ubuntu1 04/01/2014
[ 20.015540] RIP: 0010:refcount_sub_and_test_checked+0xf3/0x100
[ 20.017312] Code: 5d 41 5c 41 5d 41 5e c3 eb db 44 0f b6 35 cb a3 3a 01 45 84 f6 75 cb 48 c7 c7 e0 55 1a 82 c6 05 b8 a3 3a 01 01 e8 30 92 99 ff <0f> 0b eb b7 66 0f 1f 84 00 00 00 00 00 48 89 fe bf 01 00 00 00 e9
[ 20.021244] RSP: 0018:ffff8881005f7af8 EFLAGS: 00010086
[ 20.022159] RAX: 0000000000000000 RBX: 00000000fffffffe RCX: 0000000000000000
[ 20.023419] RDX: 0000000000000001 RSI: 0000000000000008 RDI: ffffed10200bef55
[ 20.024775] RBP: ffff8881003f2e54 R08: 0000000000000001 R09: ffffed10218c3ee1
[ 20.025743] R10: ffffed10218c3ee0 R11: ffff88810c61f707 R12: 0000000000000002
[ 20.026645] R13: 1ffff110200bef60 R14: 0000000000000000 R15: ffff8881003f2e40
[ 20.027546] FS: 00007f5f0be74540(0000) GS:ffff88810c600000(0000) knlGS:0000000000000000
[ 20.028700] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 20.029726] CR2: 00007f5f0bceabd0 CR3: 00000001072ab001 CR4: 00000000001606f0
[ 20.030880] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 20.032127] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[ 20.033457] Call Trace:
[ 20.033999] ? refcount_dec_if_one+0x90/0x90
[ 20.034861] ? debug_lockdep_rcu_enabled.part.0+0x16/0x30
[ 20.035583] ? io_cqring_fill_event+0x11d/0x330
[ 20.036035] io_free_req_find_next+0x20c/0x350
[ 20.036631] __io_queue_sqe+0x2db/0x9c0
[ 20.037219] ? io_wq_submit_work+0x220/0x220
[ 20.037795] ? io_req_defer+0x6c/0x3d0
[ 20.038404] ? rcu_read_lock_sched_held+0x81/0xb0
[ 20.039045] io_submit_sqes+0x69e/0xee0
[ 20.039521] ? io_queue_link_head+0x2c0/0x2c0
[ 20.040109] ? mutex_lock_io_nested+0xbd0/0xbd0
[ 20.040730] ? find_held_lock+0x85/0xa0
[ 20.041238] ? __x64_sys_io_uring_enter+0x1be/0x660
[ 20.041611] ? lock_downgrade+0x310/0x310
[ 20.041911] ? lock_acquire+0xc9/0x200
[ 20.042194] ? __x64_sys_io_uring_enter+0x140/0x660
[ 20.042583] __x64_sys_io_uring_enter+0x47f/0x660
[ 20.042949] ? io_sq_thread+0x4f0/0x4f0
[ 20.043250] ? trace_hardirqs_on_thunk+0x1a/0x20
[ 20.043605] ? mark_held_locks+0x24/0x90
[ 20.043927] ? do_syscall_64+0x14/0x260
[ 20.044231] do_syscall_64+0x62/0x260
[ 20.044638] entry_SYSCALL_64_after_hwframe+0x49/0xbe
[ 20.045182] RIP: 0033:0x7f5f0bda5e9d
[ 20.045425] Code: 00 c3 66 2e 0f 1f 84 00 00 00 00 00 90 f3 0f 1e fa 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d b3 5f 0c 00 f7 d8 64 89 01 48
--
Jens Axboe
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] io_uring: Fix leaking double_put()
2019-11-12 15:02 ` Jens Axboe
@ 2019-11-12 20:11 ` Pavel Begunkov
0 siblings, 0 replies; 3+ messages in thread
From: Pavel Begunkov @ 2019-11-12 20:11 UTC (permalink / raw)
To: Jens Axboe, io-uring
[-- Attachment #1.1: Type: text/plain, Size: 745 bytes --]
On 12/11/2019 18:02, Jens Axboe wrote:
> On 11/12/19 12:17 AM, Pavel Begunkov wrote:
>> io_double_put_req() may be called for a request with a link (see
>> io_req_defer(req)), and so can leak it in case of an error, as
>> __io_free_req() doesn't handle links.
>>
>> Fixes: 78e19bbef38362ceb ("io_uring: pass in io_kiocb to fill/add CQ
>> handlers")
>
> This blows up the 'link' test from the liburing regression suite:
> - io_double_put_req(link);
> + if (refcount_sub_and_test(2, &req->refs))
> + __io_free_req(req);
My bad, it frees @req instead of @link. Sorry for the trouble.
It wouldn't apply properly anyway, as there is new commit using
io_double_put_req(). I'll resend it later.
--
Pavel Begunkov
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2019-11-12 20:12 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2019-11-12 8:17 [PATCH] io_uring: Fix leaking double_put() Pavel Begunkov
2019-11-12 15:02 ` Jens Axboe
2019-11-12 20:11 ` Pavel Begunkov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox