Blob Blame History Raw
From e4dbe0ced7c80f96df7c04a73ffaa7b8a44d9518 Mon Sep 17 00:00:00 2001
From: Oscar Salvador <osalvador@suse.de>
Date: Wed, 14 Feb 2024 09:48:28 +0100
Subject: [PATCH v10 1/7] lib/stackdepot: Fix first entry having a 0-handle
References: jsc-PED#7423
Patch-mainline: v6.8-rc5
Git-commit: 3ee34eabac2abb6b1b6fcdebffe18870719ad000

The very first entry of stack_record gets a handle of 0, but this is wrong
because stackdepot treats a 0-handle as a non-valid one.
E.g: See the check in stack_depot_fetch()

Fix this by adding and offset of 1.

This bug has been lurking since the very beginning of stackdepot,
but no one really cared as it seems.
Because of that I am not adding a Fixes tag.

Co-developed-by: Marco Elver <elver@google.com>
Signed-off-by: Marco Elver <elver@google.com>
Signed-off-by: Oscar Salvador <osalvador@suse.de>
Acked-by: Vlastimil Babka <vbabka@suse.cz>
---
 lib/stackdepot.c |   15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

--- a/lib/stackdepot.c
+++ b/lib/stackdepot.c
@@ -47,14 +47,14 @@
 		STACK_ALLOC_NULL_PROTECTION_BITS - STACK_ALLOC_OFFSET_BITS)
 #define STACK_ALLOC_SLABS_CAP 8192
 #define STACK_ALLOC_MAX_SLABS \
-	(((1LL << (STACK_ALLOC_INDEX_BITS)) < STACK_ALLOC_SLABS_CAP) ? \
-	 (1LL << (STACK_ALLOC_INDEX_BITS)) : STACK_ALLOC_SLABS_CAP)
+	(((1LL << (STACK_ALLOC_INDEX_BITS)) - 1 < STACK_ALLOC_SLABS_CAP) ? \
+	 (1LL << (STACK_ALLOC_INDEX_BITS)) - 1 : STACK_ALLOC_SLABS_CAP)
 
 /* The compact structure to store the reference to stacks. */
 union handle_parts {
 	depot_stack_handle_t handle;
 	struct {
-		u32 slabindex : STACK_ALLOC_INDEX_BITS;
+		u32 slabindex : STACK_ALLOC_INDEX_BITS; /* slabindex is offset by 1 */
 		u32 offset : STACK_ALLOC_OFFSET_BITS;
 		u32 valid : STACK_ALLOC_NULL_PROTECTION_BITS;
 	};
@@ -136,7 +136,7 @@ static struct stack_record *depot_alloc_
 
 	stack->hash = hash;
 	stack->size = size;
-	stack->handle.slabindex = depot_index;
+	stack->handle.slabindex = depot_index + 1;
 	stack->handle.offset = depot_offset >> STACK_ALLOC_ALIGN;
 	stack->handle.valid = 1;
 	refcount_set(&stack->count, REFCOUNT_SATURATED);
@@ -287,15 +287,16 @@ static struct stack_record *depot_fetch_
 {
 	union handle_parts parts = { .handle = handle };
 	void *slab;
+	u32 slab_index_real = parts.slabindex - 1;
 	size_t offset = parts.offset << STACK_ALLOC_ALIGN;
 	struct stack_record *stack;
 
-	if (parts.slabindex > depot_index) {
+	if (slab_index_real > depot_index) {
 		WARN(1, "slab index %d out of bounds (%d) for stack id %08x\n",
-			parts.slabindex, depot_index, handle);
+			slab_index_real, depot_index, handle);
 		return NULL;
 	}
-	slab = stack_slabs[parts.slabindex];
+	slab = stack_slabs[slab_index_real];
 	if (!slab)
 		return NULL;