diff options
author | Gvozden Neskovic <[email protected]> | 2016-09-02 15:10:34 +0200 |
---|---|---|
committer | Brian Behlendorf <[email protected]> | 2016-09-29 15:55:41 -0700 |
commit | 6ca636a1526ea08a7e0a972fa164b22815529d4b (patch) | |
tree | 59ffe0bd8cf66168cb941ff26ac92886e203e69d | |
parent | 4ca9c1de129f8250c446c2355349e6b300d84586 (diff) |
Avoid undefined shift overflow in fzap_cursor_retrieve()
Avoid calculating (1<<64) if lh_prefix_len == 0. Semantics of the method remain
the same.
Assert (lh_prefix_len > 0) in zap_expand_leaf() to detect possibly the same
problem.
Issue #4883
Signed-off-by: Gvozden Neskovic <[email protected]>
-rw-r--r-- | module/zfs/zap.c | 26 |
1 files changed, 17 insertions, 9 deletions
diff --git a/module/zfs/zap.c b/module/zfs/zap.c index 0ed6d7f49..a8ccd2895 100644 --- a/module/zfs/zap.c +++ b/module/zfs/zap.c @@ -693,6 +693,8 @@ zap_expand_leaf(zap_name_t *zn, zap_leaf_t *l, ASSERT0(err); /* we checked for i/o errors above */ } + ASSERT3U(zap_leaf_phys(l)->l_hdr.lh_prefix_len, >, 0); + if (hash & (1ULL << (64 - zap_leaf_phys(l)->l_hdr.lh_prefix_len))) { /* we want the sibling */ zap_put_leaf(l); @@ -1230,17 +1232,23 @@ again: err = zap_leaf_lookup_closest(l, zc->zc_hash, zc->zc_cd, &zeh); if (err == ENOENT) { - uint64_t nocare = - (1ULL << (64 - zap_leaf_phys(l)->l_hdr.lh_prefix_len)) - 1; - zc->zc_hash = (zc->zc_hash & ~nocare) + nocare + 1; - zc->zc_cd = 0; - if (zap_leaf_phys(l)->l_hdr.lh_prefix_len == 0 || - zc->zc_hash == 0) { + if (zap_leaf_phys(l)->l_hdr.lh_prefix_len == 0) { zc->zc_hash = -1ULL; + zc->zc_cd = 0; } else { - zap_put_leaf(zc->zc_leaf); - zc->zc_leaf = NULL; - goto again; + uint64_t nocare = (1ULL << + (64 - zap_leaf_phys(l)->l_hdr.lh_prefix_len)) - 1; + + zc->zc_hash = (zc->zc_hash & ~nocare) + nocare + 1; + zc->zc_cd = 0; + + if (zc->zc_hash == 0) { + zc->zc_hash = -1ULL; + } else { + zap_put_leaf(zc->zc_leaf); + zc->zc_leaf = NULL; + goto again; + } } } |