Skip to content

Commit 9bce800

Browse files
Konstantin Ovsepianaxboe
authored andcommitted
blk_iocost: fix more out of bound shifts
Recently running UBSAN caught few out of bound shifts in the ioc_forgive_debts() function: UBSAN: shift-out-of-bounds in block/blk-iocost.c:2142:38 shift exponent 80 is too large for 64-bit type 'u64' (aka 'unsigned long long') ... UBSAN: shift-out-of-bounds in block/blk-iocost.c:2144:30 shift exponent 80 is too large for 64-bit type 'u64' (aka 'unsigned long long') ... Call Trace: <IRQ> dump_stack_lvl+0xca/0x130 __ubsan_handle_shift_out_of_bounds+0x22c/0x280 ? __lock_acquire+0x6441/0x7c10 ioc_timer_fn+0x6cec/0x7750 ? blk_iocost_init+0x720/0x720 ? call_timer_fn+0x5d/0x470 call_timer_fn+0xfa/0x470 ? blk_iocost_init+0x720/0x720 __run_timer_base+0x519/0x700 ... Actual impact of this issue was not identified but I propose to fix the undefined behaviour. The proposed fix to prevent those out of bound shifts consist of precalculating exponent before using it the shift operations by taking min value from the actual exponent and maximum possible number of bits. Reported-by: Breno Leitao <[email protected]> Signed-off-by: Konstantin Ovsepian <[email protected]> Acked-by: Tejun Heo <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Jens Axboe <[email protected]>
1 parent 87599ed commit 9bce800

File tree

1 file changed

+5
-3
lines changed

1 file changed

+5
-3
lines changed

block/blk-iocost.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2076,7 +2076,7 @@ static void ioc_forgive_debts(struct ioc *ioc, u64 usage_us_sum, int nr_debtors,
20762076
struct ioc_now *now)
20772077
{
20782078
struct ioc_gq *iocg;
2079-
u64 dur, usage_pct, nr_cycles;
2079+
u64 dur, usage_pct, nr_cycles, nr_cycles_shift;
20802080

20812081
/* if no debtor, reset the cycle */
20822082
if (!nr_debtors) {
@@ -2138,10 +2138,12 @@ static void ioc_forgive_debts(struct ioc *ioc, u64 usage_us_sum, int nr_debtors,
21382138
old_debt = iocg->abs_vdebt;
21392139
old_delay = iocg->delay;
21402140

2141+
nr_cycles_shift = min_t(u64, nr_cycles, BITS_PER_LONG - 1);
21412142
if (iocg->abs_vdebt)
2142-
iocg->abs_vdebt = iocg->abs_vdebt >> nr_cycles ?: 1;
2143+
iocg->abs_vdebt = iocg->abs_vdebt >> nr_cycles_shift ?: 1;
2144+
21432145
if (iocg->delay)
2144-
iocg->delay = iocg->delay >> nr_cycles ?: 1;
2146+
iocg->delay = iocg->delay >> nr_cycles_shift ?: 1;
21452147

21462148
iocg_kick_waitq(iocg, true, now);
21472149

0 commit comments

Comments
 (0)