When running iocg_kick_delay(), iocg->delay_at could be way behind "now", which causes a huge tdelta difference. The tdelta value is used to shift some bits around, raising the following UBSAN splat: UBSAN: shift-out-of-bounds in block/blk-iocost.c:1366:23 Debugging this, these are some values I got in my machine with 6.9-rc3. now = 3626064295 iocg->delay_at = 3275794093 Fix this by validating that the shift if valid, otherwise bail out, similarly to commit 2a427b49d029 ("blk-iocost: Fix an UBSAN shift-out-of-bounds warning") Signed-off-by: Breno Leitao <leitao@xxxxxxxxxx> --- block/blk-iocost.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/block/blk-iocost.c b/block/blk-iocost.c index 9a85bfbbc45a..398fe19db4ca 100644 --- a/block/blk-iocost.c +++ b/block/blk-iocost.c @@ -1347,7 +1347,7 @@ static bool iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now) { struct ioc *ioc = iocg->ioc; struct blkcg_gq *blkg = iocg_to_blkg(iocg); - u64 tdelta, delay, new_delay; + u64 tdelta, delay, new_delay, shift; s64 vover, vover_pct; u32 hwa; @@ -1362,8 +1362,13 @@ static bool iocg_kick_delay(struct ioc_gq *iocg, struct ioc_now *now) /* calculate the current delay in effect - 1/2 every second */ tdelta = now->now - iocg->delay_at; + + shift = div64_u64(tdelta, USEC_PER_SEC); + if (shift >= BITS_PER_LONG) + return false; + if (iocg->delay) - delay = iocg->delay >> div64_u64(tdelta, USEC_PER_SEC); + delay = iocg->delay >> shift; else delay = 0; -- 2.43.0