badblocks: fix infinite loop due to incorrect rounding and overflow#1032
Open
blktests-ci[bot] wants to merge 1 commit into
Open
badblocks: fix infinite loop due to incorrect rounding and overflow#1032blktests-ci[bot] wants to merge 1 commit into
blktests-ci[bot] wants to merge 1 commit into
Conversation
The roundup() and rounddown() macros return the rounded value but do not modify their input in place. In _badblocks_set(), _badblocks_clear(), and badblocks_check(), the return values were being discarded, so s and target/next remained unrounded. Sectors were then calculated from these unrounded values, which could make sectors way too large (or zero), causing infinite loops in the re_insert/re_clear/re_check loops. This was confirmed with local syzkaller fuzzing against the nvdimm ioctl path (ND_IOCTL_CLEAR_ERROR -> nvdimm_clear_badblocks_region() -> badblocks_clear()), which reliably produces RCU stalls with the looping task caught mid-loop: rcu: INFO: rcu_preempt detected stalls on CPUs/tasks: rcu: rcu_preempt kthread starved for 21001 jiffies! g40229 f0x0 RCU_GP_WAIT_FQS(5) ... Call Trace: badblocks_clear+0x259/0xb10 nvdimm_clear_badblocks_region+0x165/0x1e0 [libnvdimm] device_for_each_child+0x11e/0x1a0 nd_ioctl+0x1413/0x1750 [libnvdimm] __x64_sys_ioctl+0x18e/0x210 do_syscall_64+0x102/0x5a0 Fix this by properly capturing the return values of round_up()/ round_down() (the power-of-two variants, since 1 << bb->shift is always a power of two -- roundup()/rounddown() use a division/ modulo internally, which is undesirable here). Also add overflow checks (s > ULLONG_MAX - sectors) before the s + sectors addition in all three functions, and handle the case where sectors becomes zero after rounding. The overflow check is done unconditionally, before the bb->shift rounding block, rather than inside it. bb->shift == 0 is not just an initial state -- __badblocks_init() sets it to 0 by default, and drivers/md/md.c explicitly sets rdev->badblocks.shift back to 0 in several paths -- so s + sectors needs the same overflow guard whether or not rounding happens. Signed-off-by: Ramesh Adhikari <adhikari.resume@gmail.com>
Author
|
Upstream branch: 87320be |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Pull request for series with
subject: badblocks: fix infinite loop due to incorrect rounding and overflow
version: 5
url: https://patchwork.kernel.org/project/linux-block/list/?series=1121577