io_uring: fix dead-hung for non-iter fixed rw
A message that is not in the archive (sent off-list or not yet received): [email protected]
PATCH v2 1/1 io_uring: fix dead-hung for non-iter fixed rw
Read/write requests to devices without implemented read/write_iter using fixed buffers causes general protection fault, which totally hangs a machine.
io_import_fixed() initialises iov_iter with bvec, but loop_rw_iter() accesses it as iovec, so dereferencing random address.
kmap() page by page in this case
---
v2: use kmap
P.S. this one passes all tests well
fs/io_uring.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-)
fs/io_uring.c +14 -1
@@ -1613,9 +1613,19 @@ static ssize_t loop_rw_iter(int rw, struct file *file, struct kiocb *kiocb,return -EAGAIN ;while (iov_iter_count (iter)) { -struct iovec iovec =iov_iter_iovec (iter); +struct iovec iovec;ssize_t nr; +if (!iov_iter_is_bvec (iter)) { + iovec =iov_iter_iovec (iter); + }else { +/* fixed buffers import bvec */ + iovec.iov_base =kmap (iter->bvec->bv_page) + + iter->iov_offset; + iovec.iov_len =min (iter->count, + iter->bvec->bv_len - iter->iov_offset); + } +if (rw ==READ ) { nr = file->f_op->read (file, iovec.iov_base, iovec.iov_len, &kiocb->ki_pos);
@@ -1624,6 +1634,9 @@ static ssize_t loop_rw_iter(int rw, struct file *file, struct kiocb *kiocb, iovec.iov_len, &kiocb->ki_pos); } +if (iov_iter_is_bvec (iter)) +kunmap (iter->bvec->bv_page); +if (nr <0 ) {if (!ret) ret = nr;
Signature · 1 line
2.24.0
Jens Axboe
maintainerQuoted 8 lines · Pavel Begunkov
Read/write requests to devices without implemented read/write_iter using fixed buffers causes general protection fault, which totally hangs a machine.
io_import_fixed()initialisesiov_iterwith bvec, butloop_rw_iter()accesses it as iovec, so dereferencing random address.
kmap()page by page in this case
This looks good to me, much cleaner/simpler. I've added a few pipe fixed buffer tests to liburing as well. Didn't crash for me, but obvious garbage coming out. I've flagged this for stable as well.
Signature · 1 line
Jens Axboe
Quoted 5 lines · Jens Axboe
Quoted 4 lines · Pavel Begunkov
Read/write requests to devices without implemented read/write_iter using fixed buffers causes general protection fault, which totally hangs a machine.
Quoted 9 lines
Quoted 4 lines
io_import_fixed()initialisesiov_iterwith bvec, butloop_rw_iter()accesses it as iovec, so dereferencing random address.
kmap()page by page in this caseThis looks good to me, much cleaner/simpler. I've added a few pipe fixed buffer tests to liburing as well. Didn't crash for me, but obvious garbage coming out. I've flagged this for stable as well.
The problem I have is that __user pointer is meant to be checked for not being a kernel address. I suspect, it could fail in some device, which double checks the pointer after vfs (e.g. using access_ok()). Am I wrong? Not a fault at least...
#define access_ok(...) __range_not_ok(addr, user_addr_max());
BTW, is there anybody testing it for non x86-64 arch?
Signature · 1 line
Pavel Begunkov
Quoted 19 lines
2019年11月25日 01:52,Pavel Begunkov <[email protected]> 写道:
Quoted 5 lines · Jens Axboe
Quoted 4 lines · Pavel Begunkov
Read/write requests to devices without implemented read/write_iter using fixed buffers causes general protection fault, which totally hangs a machine.
Quoted 9 lines
Quoted 4 lines
io_import_fixed()initialisesiov_iterwith bvec, butloop_rw_iter()accesses it as iovec, so dereferencing random address.
kmap()page by page in this caseThis looks good to me, much cleaner/simpler. I've added a few pipe fixed buffer tests to liburing as well. Didn't crash for me, but obvious garbage coming out. I've flagged this for stable as well.
Quoted 9 lines
The problem I have is that
__userpointer is meant to be checked for not being a kernel address. I suspect, it could fail in some device, which double checks the pointer after vfs (e.g. usingaccess_ok()). Am I wrong? Not a fault at least...#define
access_ok(...)__range_not_ok(addr, user_addr_max());BTW, is there anybody testing it for non x86-64 arch?
I have some aarch64 platform, What test do you want me to do?
--
Jackie Liu
Jens Axboe
maintainerQuoted 24 lines · Jackie Liu
Quoted 24 lines
2019年11月25日 01:52,Pavel Begunkov <[email protected]> 写道:
Quoted 5 lines · Jens Axboe
Quoted 4 lines · Pavel Begunkov
Read/write requests to devices without implemented read/write_iter using fixed buffers causes general protection fault, which totally hangs a machine.
Quoted 9 lines
Quoted 4 lines
io_import_fixed()initialisesiov_iterwith bvec, butloop_rw_iter()accesses it as iovec, so dereferencing random address.
kmap()page by page in this caseThis looks good to me, much cleaner/simpler. I've added a few pipe fixed buffer tests to liburing as well. Didn't crash for me, but obvious garbage coming out. I've flagged this for stable as well.
The problem I have is that
__userpointer is meant to be checked for not being a kernel address. I suspect, it could fail in some device, which double checks the pointer after vfs (e.g. usingaccess_ok()). Am I wrong? Not a fault at least...
Quoted 6 lines
Quoted 4 lines
#define
access_ok(...)__range_not_ok(addr, user_addr_max());BTW, is there anybody testing it for non x86-64 arch?
I have some aarch64 platform, What test do you want me to do?
A basic one to try would be:
axboe@x1:/home/axboe/git/liburing $ test/stdout
This is a pipe test
This is a fixed pipe test
But in general I'd just run make runtests in the liburing directory and go through all of them.
Signature · 1 line
Jens Axboe
Quoted 36 lines
2019年11月25日 10:38,Jens Axboe <[email protected]> 写道:
Quoted 24 lines · Jackie Liu
Quoted 24 lines
2019年11月25日 01:52,Pavel Begunkov <[email protected]> 写道:
Quoted 5 lines · Jens Axboe
Quoted 4 lines · Pavel Begunkov
Read/write requests to devices without implemented read/write_iter using fixed buffers causes general protection fault, which totally hangs a machine.
Quoted 9 lines
Quoted 4 lines
io_import_fixed()initialisesiov_iterwith bvec, butloop_rw_iter()accesses it as iovec, so dereferencing random address.
kmap()page by page in this caseThis looks good to me, much cleaner/simpler. I've added a few pipe fixed buffer tests to liburing as well. Didn't crash for me, but obvious garbage coming out. I've flagged this for stable as well.
The problem I have is that
__userpointer is meant to be checked for not being a kernel address. I suspect, it could fail in some device, which double checks the pointer after vfs (e.g. usingaccess_ok()). Am I wrong? Not a fault at least...Quoted 6 lines
Quoted 4 lines
#define
access_ok(...)__range_not_ok(addr, user_addr_max());BTW, is there anybody testing it for non x86-64 arch?
I have some aarch64 platform, What test do you want me to do?
Quoted 9 lines
A basic one to try would be:
axboe@x1:/home/axboe/git/liburing $ test/stdout
This is a pipe test
This is a fixed pipe testBut in general I'd just run make runtests in the liburing directory and go through all of them.
For test/stdout is PASS. Tested-by: Jackie Liu <[email protected]>
But test/accept-link and test/fixed-link failed in for-5.5/io_uring-post branch. that is expect?
--
Jackie Liu
Jens Axboe
maintainerQuoted 45 lines · Jackie Liu
Quoted 40 lines
Quoted 25 lines · 2019年11月25日 10:38,Jens Axboe <[email protected]> 写道:
Quoted 22 lines · Jackie Liu
2019年11月25日 01:52,Pavel Begunkov <[email protected]> 写道:
Quoted 5 lines · Jens Axboe
Quoted 4 lines · Pavel Begunkov
Read/write requests to devices without implemented read/write_iter using fixed buffers causes general protection fault, which totally hangs a machine.
Quoted 9 lines
Quoted 4 lines
io_import_fixed()initialisesiov_iterwith bvec, butloop_rw_iter()accesses it as iovec, so dereferencing random address.
kmap()page by page in this caseThis looks good to me, much cleaner/simpler. I've added a few pipe fixed buffer tests to liburing as well. Didn't crash for me, but obvious garbage coming out. I've flagged this for stable as well.
The problem I have is that
__userpointer is meant to be checked for not being a kernel address. I suspect, it could fail in some device, which double checks the pointer after vfs (e.g. usingaccess_ok()). Am I wrong? Not a fault at least...Quoted 6 lines
Quoted 4 lines
#define
access_ok(...)__range_not_ok(addr, user_addr_max());BTW, is there anybody testing it for non x86-64 arch?
I have some aarch64 platform, What test do you want me to do?
A basic one to try would be:
axboe@x1:/home/axboe/git/liburing $ test/stdout
This is a pipe test
This is a fixed pipe test
Quoted 5 lines
Quoted 3 lines
But in general I'd just run make runtests in the liburing directory and go through all of them.
For test/stdout is PASS. Tested-by: Jackie Liu <[email protected]>
Thanks!
Quoted 2 lines
But test/accept-link and test/fixed-link failed in for-5.5/io_uring-post branch. that is expect?
Yes, the fix for that is in 5.4, didn’t merge it into the 5.5 branch. It’ll pass once Linus pulls the 5.5 bits and the branches merge.
—
Jens Axboe
Quoted 8 lines
Quoted 8 lines
Quoted 1 line
I have some aarch64 platform, What test do you want me to do?
A basic one to try would be:
axboe@x1:/home/axboe/git/liburing $ test/stdout
This is a pipe test
This is a fixed pipe test
Quoted 6 lines
Quoted 3 lines
But in general I'd just run make runtests in the liburing directory and go through all of them.
For test/stdout is PASS. Tested-by: Jackie Liu <[email protected]>
Great, thanks!
Signature · 1 line
Pavel Begunkov
Jens Axboe
maintainerQuoted 15 lines · Pavel Begunkov
Quoted 5 lines · Jens Axboe
Quoted 4 lines · Pavel Begunkov
Read/write requests to devices without implemented read/write_iter using fixed buffers causes general protection fault, which totally hangs a machine.
Quoted 9 lines
Quoted 4 lines
io_import_fixed()initialisesiov_iterwith bvec, butloop_rw_iter()accesses it as iovec, so dereferencing random address.
kmap()page by page in this caseThis looks good to me, much cleaner/simpler. I've added a few pipe fixed buffer tests to liburing as well. Didn't crash for me, but obvious garbage coming out. I've flagged this for stable as well.
Quoted 6 lines
The problem I have is that
__userpointer is meant to be checked for not being a kernel address. I suspect, it could fail in some device, which double checks the pointer after vfs (e.g. usingaccess_ok()). Am I wrong? Not a fault at least...#define
access_ok(...)__range_not_ok(addr, user_addr_max());
They are user pages! So this should be totally fine. The only difference is that we have them pre-mapped. But it's not like we're pretending these kernel pages are user pages, and hence access_ok() should be totally happy with them.
Quoted 1 line
BTW, is there anybody testing it for non x86-64 arch?
Would be nice, I've mostly failed at getting other archs interested enough to actually make hardware available. Which seems pretty lame, but only so much I can do there. There _shouldn't_ be anything arch specific, but it would be great to have archs with eg weaker ordering as part of the regular test arsenal.
Signature · 1 line
Jens Axboe
Quoted 21 lines · Jens Axboe
Quoted 20 lines · Pavel Begunkov
Quoted 5 lines · Jens Axboe
Quoted 4 lines · Pavel Begunkov
Read/write requests to devices without implemented read/write_iter using fixed buffers causes general protection fault, which totally hangs a machine.
Quoted 9 lines
Quoted 4 lines
io_import_fixed()initialisesiov_iterwith bvec, butloop_rw_iter()accesses it as iovec, so dereferencing random address.
kmap()page by page in this caseThis looks good to me, much cleaner/simpler. I've added a few pipe fixed buffer tests to liburing as well. Didn't crash for me, but obvious garbage coming out. I've flagged this for stable as well.
The problem I have is that
__userpointer is meant to be checked for not being a kernel address. I suspect, it could fail in some device, which double checks the pointer after vfs (e.g. usingaccess_ok()). Am I wrong? Not a fault at least...
Quoted 7 lines
Quoted 1 line
#define
access_ok(...)__range_not_ok(addr, user_addr_max());They are user pages! So this should be totally fine. The only difference is that we have them pre-mapped. But it's not like we're pretending these kernel pages are user pages, and hence
access_ok()should be totally happy with them.
Good, if you say so, but I'll take the liberty of asking a little bit more :)
Yes, they are user pages, but that's rather about used virtual addresses. Having virtual address space separation (e.g. [0-n): user's virtual address space part, [n-m): kernel's one), I'd expect __user ptr to be checked to be bounded by [0-n). E.g. copy_to_user() obviously shouldn't write into kernel's addresses. And I also assume that kmap() maps into [n-m), at least because the kernel may want to allocate and kmap() pages, and use them internally.
And that's why I thought it may fail.
E.g. vfs_read_sys((__user void*)kmap()) _should_ fail. Where is my mistake?
Quoted 8 lines
Quoted 1 line
BTW, is there anybody testing it for non x86-64 arch?
Would be nice, I've mostly failed at getting other archs interested enough to actually make hardware available. Which seems pretty lame, but only so much I can do there. There _shouldn't_ be anything arch specific, but it would be great to have archs with eg weaker ordering as part of the regular test arsenal.
Yeah, that's the point. It probably needs some use in Android to turn the things over.
Signature · 1 line
Pavel Begunkov