generix radix trees: Don't overflow in peek()

This commit is contained in:
Kent Overstreet 2021-02-12 20:12:43 -05:00
parent 868abec1ab
commit c28f93bc52
2 changed files with 22 additions and 3 deletions

View File

@ -183,6 +183,14 @@ void *__genradix_iter_peek(struct genradix_iter *, struct __genradix *, size_t);
static inline void __genradix_iter_advance(struct genradix_iter *iter,
size_t obj_size)
{
size_t new_offset = iter->offset + obj_size;
if (new_offset < iter->offset) {
iter->offset = SIZE_MAX;
iter->pos = SIZE_MAX;
return;
}
iter->offset += obj_size;
if (!is_power_of_2(obj_size) &&

View File

@ -147,6 +147,10 @@ void *__genradix_iter_peek(struct genradix_iter *iter,
struct genradix_root *r;
struct genradix_node *n;
unsigned level, i;
if (iter->offset == SIZE_MAX)
return NULL;
restart:
r = READ_ONCE(radix->root);
if (!r)
@ -165,10 +169,17 @@ restart:
(GENRADIX_ARY - 1);
while (!n->children[i]) {
size_t objs_per_ptr = genradix_depth_size(level);
if (iter->offset + objs_per_ptr < iter->offset) {
iter->offset = SIZE_MAX;
iter->pos = SIZE_MAX;
return NULL;
}
i++;
iter->offset = round_down(iter->offset +
genradix_depth_size(level),
genradix_depth_size(level));
iter->offset = round_down(iter->offset + objs_per_ptr,
objs_per_ptr);
iter->pos = (iter->offset >> PAGE_SHIFT) *
objs_per_page;
if (i == GENRADIX_ARY)