Skip to content

Commit eb2667b

Browse files
josephhzaxboe
authored andcommitted
io_uring: fix shift-out-of-bounds when round up cq size
Abaci Fuzz reported a shift-out-of-bounds BUG in io_uring_create(): [ 59.598207] UBSAN: shift-out-of-bounds in ./include/linux/log2.h:57:13 [ 59.599665] shift exponent 64 is too large for 64-bit type 'long unsigned int' [ 59.601230] CPU: 0 PID: 963 Comm: a.out Not tainted 5.10.0-rc4+ #3 [ 59.602502] Hardware name: Red Hat KVM, BIOS 0.5.1 01/01/2011 [ 59.603673] Call Trace: [ 59.604286] dump_stack+0x107/0x163 [ 59.605237] ubsan_epilogue+0xb/0x5a [ 59.606094] __ubsan_handle_shift_out_of_bounds.cold+0xb2/0x20e [ 59.607335] ? lock_downgrade+0x6c0/0x6c0 [ 59.608182] ? rcu_read_lock_sched_held+0xaf/0xe0 [ 59.609166] io_uring_create.cold+0x99/0x149 [ 59.610114] io_uring_setup+0xd6/0x140 [ 59.610975] ? io_uring_create+0x2510/0x2510 [ 59.611945] ? lockdep_hardirqs_on_prepare+0x286/0x400 [ 59.613007] ? syscall_enter_from_user_mode+0x27/0x80 [ 59.614038] ? trace_hardirqs_on+0x5b/0x180 [ 59.615056] do_syscall_64+0x2d/0x40 [ 59.615940] entry_SYSCALL_64_after_hwframe+0x44/0xa9 [ 59.617007] RIP: 0033:0x7f2bb8a0b239 This is caused by roundup_pow_of_two() if the input entries larger enough, e.g. 2^32-1. For sq_entries, it will check first and we allow at most IORING_MAX_ENTRIES, so it is okay. But for cq_entries, we do round up first, that may overflow and truncate it to 0, which is not the expected behavior. So check the cq size first and then do round up. Fixes: 88ec321 ("io_uring: round-up cq size before comparing with rounded sq size") Reported-by: Abaci Fuzz <[email protected]> Signed-off-by: Joseph Qi <[email protected]> Reviewed-by: Stefano Garzarella <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 418baf2 commit eb2667b

File tree

1 file changed

+4
-2
lines changed

1 file changed

+4
-2
lines changed

fs/io_uring.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -9252,14 +9252,16 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p,
92529252
* to a power-of-two, if it isn't already. We do NOT impose
92539253
* any cq vs sq ring sizing.
92549254
*/
9255-
p->cq_entries = roundup_pow_of_two(p->cq_entries);
9256-
if (p->cq_entries < p->sq_entries)
9255+
if (!p->cq_entries)
92579256
return -EINVAL;
92589257
if (p->cq_entries > IORING_MAX_CQ_ENTRIES) {
92599258
if (!(p->flags & IORING_SETUP_CLAMP))
92609259
return -EINVAL;
92619260
p->cq_entries = IORING_MAX_CQ_ENTRIES;
92629261
}
9262+
p->cq_entries = roundup_pow_of_two(p->cq_entries);
9263+
if (p->cq_entries < p->sq_entries)
9264+
return -EINVAL;
92639265
} else {
92649266
p->cq_entries = 2 * p->sq_entries;
92659267
}

0 commit comments

Comments
 (0)