Unverified Commit 8a472d7b authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!10040 lib/generic-radix-tree.c: Don't overflow in peek()

parents 99075488 a31d890e
Loading
Loading
Loading
Loading
+7 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@
#include <asm/page.h>
#include <linux/bug.h>
#include <linux/kernel.h>
#include <linux/limits.h>
#include <linux/log2.h>

struct genradix_root;
@@ -183,6 +184,12 @@ 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)
{
	if (iter->offset + obj_size < iter->offset) {
		iter->offset	= SIZE_MAX;
		iter->pos	= SIZE_MAX;
		return;
	}

	iter->offset += obj_size;

	if (!is_power_of_2(obj_size) &&
+14 −3
Original line number Diff line number Diff line
@@ -166,6 +166,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)
@@ -184,10 +188,17 @@ void *__genradix_iter_peek(struct genradix_iter *iter,
			(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)