Skip to content

Commit

Permalink
Fix possible bad bit shift in dnode_next_offset_level()
Browse files Browse the repository at this point in the history
031d7c2 did not handle reverse
iteration, such that the original issue theoretically could still occur.

Note that contrary to the claim in the ZFS disk format specification
that a maximum of 6 levels are possible, 9 levels are possible with
recordsize=512 and and indirect block size of 16KB. In this unusual
configuration, span will be 65. The maximum size of span at 70 can be
reached at recordsize=16K and an indirect blocksize of 16KB.

When we are at this indirection level and are traversing backward, the
minimum value is start, but we cannot calculate that with 64-bit
arithmetic, so we avoid the calculation and instead rely on the earlier
statement that did `*offset = start;`.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Richard Yao <richard.yao@alumni.stonybrook.edu>
Reported-by: Coverity (CID-1466214)
Closes openzfs#14618
  • Loading branch information
ryao authored Mar 16, 2023
1 parent 60cfd3b commit fa46802
Showing 1 changed file with 3 additions and 2 deletions.
5 changes: 3 additions & 2 deletions module/zfs/dnode.c
Original file line number Diff line number Diff line change
Expand Up @@ -2597,8 +2597,9 @@ dnode_next_offset_level(dnode_t *dn, int flags, uint64_t *offset,

if (inc < 0) {
/* traversing backwards; position offset at the end */
ASSERT3U(*offset, <=, start);
*offset = MIN(*offset + (1ULL << span) - 1, start);
if (span < 8 * sizeof (*offset))
*offset = MIN(*offset + (1ULL << span) - 1,
start);
} else if (*offset < start) {
*offset = start;
}
Expand Down

0 comments on commit fa46802

Please sign in to comment.