Skip to content

Commit 3e659d9

Browse files
Hyesoo Yuopsiff
authored andcommitted
mm: slub: call WARN() when detecting a slab corruption
[ Upstream commit 3f6f32b ] If a slab object is corrupted or an error occurs in its internal validation, continuing after restoration may cause other side effects. At this point, it is difficult to debug because the problem occurred in the past. It is useful to use WARN() to catch errors at the point of issue because WARN() could trigger panic for system debugging when panic_on_warn is enabled. WARN() is added where to detect the error on slab_err and object_err. It makes sense to only do the WARN() after printing the logs. slab_err is splited to __slab_err that calls the WARN() and it is called after printing logs. Signed-off-by: Hyesoo Yu <[email protected]> Reviewed-by: Harry Yoo <[email protected]> Signed-off-by: Vlastimil Babka <[email protected]> Stable-dep-of: b4efccec8d06 ("mm/slub: avoid accessing metadata when pointer is invalid in object_err()") Signed-off-by: Sasha Levin <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> (cherry picked from commit d06b739f41dccb45c06972b4de46fc856d7411a9)
1 parent ab28e72 commit 3e659d9

File tree

1 file changed

+29
-18
lines changed

1 file changed

+29
-18
lines changed

mm/slub.c

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,7 +1036,7 @@ static void slab_bug(struct kmem_cache *s, char *fmt, ...)
10361036
vaf.fmt = fmt;
10371037
vaf.va = &args;
10381038
pr_err("=============================================================================\n");
1039-
pr_err("BUG %s (%s): %pV\n", s->name, print_tainted(), &vaf);
1039+
pr_err("BUG %s (%s): %pV\n", s ? s->name : "<unknown>", print_tainted(), &vaf);
10401040
pr_err("-----------------------------------------------------------------------------\n\n");
10411041
va_end(args);
10421042
}
@@ -1095,8 +1095,6 @@ static void print_trailer(struct kmem_cache *s, struct slab *slab, u8 *p)
10951095
/* Beginning of the filler is the free pointer */
10961096
print_section(KERN_ERR, "Padding ", p + off,
10971097
size_from_object(s) - off);
1098-
1099-
dump_stack();
11001098
}
11011099

11021100
static void object_err(struct kmem_cache *s, struct slab *slab,
@@ -1108,6 +1106,8 @@ static void object_err(struct kmem_cache *s, struct slab *slab,
11081106
slab_bug(s, "%s", reason);
11091107
print_trailer(s, slab, object);
11101108
add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE);
1109+
1110+
WARN_ON(1);
11111111
}
11121112

11131113
static bool freelist_corrupted(struct kmem_cache *s, struct slab *slab,
@@ -1124,6 +1124,17 @@ static bool freelist_corrupted(struct kmem_cache *s, struct slab *slab,
11241124
return false;
11251125
}
11261126

1127+
static void __slab_err(struct slab *slab)
1128+
{
1129+
if (slab_in_kunit_test())
1130+
return;
1131+
1132+
print_slab_info(slab);
1133+
add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE);
1134+
1135+
WARN_ON(1);
1136+
}
1137+
11271138
static __printf(3, 4) void slab_err(struct kmem_cache *s, struct slab *slab,
11281139
const char *fmt, ...)
11291140
{
@@ -1137,9 +1148,7 @@ static __printf(3, 4) void slab_err(struct kmem_cache *s, struct slab *slab,
11371148
vsnprintf(buf, sizeof(buf), fmt, args);
11381149
va_end(args);
11391150
slab_bug(s, "%s", buf);
1140-
print_slab_info(slab);
1141-
dump_stack();
1142-
add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE);
1151+
__slab_err(slab);
11431152
}
11441153

11451154
static void init_object(struct kmem_cache *s, void *object, u8 val)
@@ -1312,9 +1321,10 @@ slab_pad_check(struct kmem_cache *s, struct slab *slab)
13121321
while (end > fault && end[-1] == POISON_INUSE)
13131322
end--;
13141323

1315-
slab_err(s, slab, "Padding overwritten. 0x%p-0x%p @offset=%tu",
1316-
fault, end - 1, fault - start);
1324+
slab_bug(s, "Padding overwritten. 0x%p-0x%p @offset=%tu",
1325+
fault, end - 1, fault - start);
13171326
print_section(KERN_ERR, "Padding ", pad, remainder);
1327+
__slab_err(slab);
13181328

13191329
restore_bytes(s, "slab padding", POISON_INUSE, fault, end);
13201330
}
@@ -1630,12 +1640,12 @@ static inline int free_consistency_checks(struct kmem_cache *s,
16301640
slab_err(s, slab, "Attempt to free object(0x%p) outside of slab",
16311641
object);
16321642
} else if (!slab->slab_cache) {
1633-
pr_err("SLUB <none>: no slab for object 0x%p.\n",
1634-
object);
1635-
dump_stack();
1636-
} else
1643+
slab_err(NULL, slab, "No slab cache for object 0x%p",
1644+
object);
1645+
} else {
16371646
object_err(s, slab, object,
1638-
"page slab pointer corrupt.");
1647+
"page slab pointer corrupt.");
1648+
}
16391649
return 0;
16401650
}
16411651
return 1;
@@ -5450,14 +5460,14 @@ static int calculate_sizes(struct kmem_cache_args *args, struct kmem_cache *s)
54505460
return !!oo_objects(s->oo);
54515461
}
54525462

5453-
static void list_slab_objects(struct kmem_cache *s, struct slab *slab,
5454-
const char *text)
5463+
static void list_slab_objects(struct kmem_cache *s, struct slab *slab)
54555464
{
54565465
#ifdef CONFIG_SLUB_DEBUG
54575466
void *addr = slab_address(slab);
54585467
void *p;
54595468

5460-
slab_err(s, slab, text, s->name);
5469+
if (!slab_add_kunit_errors())
5470+
slab_bug(s, "Objects remaining on __kmem_cache_shutdown()");
54615471

54625472
spin_lock(&object_map_lock);
54635473
__fill_map(object_map, s, slab);
@@ -5472,6 +5482,8 @@ static void list_slab_objects(struct kmem_cache *s, struct slab *slab,
54725482
}
54735483
}
54745484
spin_unlock(&object_map_lock);
5485+
5486+
__slab_err(slab);
54755487
#endif
54765488
}
54775489

@@ -5492,8 +5504,7 @@ static void free_partial(struct kmem_cache *s, struct kmem_cache_node *n)
54925504
remove_partial(n, slab);
54935505
list_add(&slab->slab_list, &discard);
54945506
} else {
5495-
list_slab_objects(s, slab,
5496-
"Objects remaining in %s on __kmem_cache_shutdown()");
5507+
list_slab_objects(s, slab);
54975508
}
54985509
}
54995510
spin_unlock_irq(&n->list_lock);

0 commit comments

Comments
 (0)