2022-07-27 07:11:57

by Feng Tang

[permalink] [raw]
Subject: [PATCH v3 0/3] mm/slub: some debug enhancements

kmalloc's API family is critical for mm, and one of its nature is that
it will round up the request size to a fixed one (mostly power of 2).
When user requests memory for '2^n + 1' bytes, actually 2^(n+1) bytes
could be allocated, so in worst case, there is around 50% memory space
waste.

The wastage is not a big issue for requests that get allocated/freed
quickly, but may cause problems with objects that have longer life time,
and there were some OOM cases in some extrem cases.

This patchset tries to :
* Add a debug method to track each kmalloced object's wastage info,
and show the call stack of original allocation
* Extend the redzone sanity check to the extra kmalloced buffer than
requested, to better detect un-legitimate access to it.

Please help to review, thanks!

- Feng

---
Changelogs:

since v2:
* rebased against slab tree's 'for-next' branch
* fix pointer handling (Kefeng Wang)
* move kzalloc zeroing handling change to a separate patch (Vlastimil Babka)
* make 'orig_size' only depend on KMALLOC & STORE_USER flag
bits (Vlastimil Babka)

since v1:
* limit the 'orig_size' to kmalloc objects only, and save
it after track in metadata (Vlastimil Babka)
* fix a offset calculation problem in print_trailer

since RFC:
* fix problems in kmem_cache_alloc_bulk() and records sorting,
improve the print format (Hyeonggon Yoo)
* fix a compiling issue found by 0Day bot
* update the commit log based info from iova developers


Feng Tang (3):
mm/slub: enable debugging memory wasting of kmalloc
mm/slub: only zero the requested size of buffer for kzalloc
mm/slub: extend redzone check to cover extra allocated kmalloc space
than requested

include/linux/slab.h | 2 +
mm/slab.c | 8 +--
mm/slab.h | 9 ++-
mm/slub.c | 157 ++++++++++++++++++++++++++++++++++++-------
4 files changed, 146 insertions(+), 30 deletions(-)

--
2.27.0


2022-07-27 07:13:01

by Feng Tang

[permalink] [raw]
Subject: [PATCH v3 1/3] mm/slub: enable debugging memory wasting of kmalloc

kmalloc's API family is critical for mm, with one nature that it will
round up the request size to a fixed one (mostly power of 2). Say
when user requests memory for '2^n + 1' bytes, actually 2^(n+1) bytes
could be allocated, so in worst case, there is around 50% memory
space waste.

The wastage is not a big issue for requests that get allocated/freed
quickly, but may cause problems with objects that have longer life
time.

We've met a kernel boot OOM panic (v5.10), and from the dumped slab
info:

[ 26.062145] kmalloc-2k 814056KB 814056KB

From debug we found there are huge number of 'struct iova_magazine',
whose size is 1032 bytes (1024 + 8), so each allocation will waste
1016 bytes. Though the issue was solved by giving the right (bigger)
size of RAM, it is still nice to optimize the size (either use a
kmalloc friendly size or create a dedicated slab for it).

And from lkml archive, there was another crash kernel OOM case [1]
back in 2019, which seems to be related with the similar slab waste
situation, as the log is similar:

[ 4.332648] iommu: Adding device 0000:20:02.0 to group 16
[ 4.338946] swapper/0 invoked oom-killer: gfp_mask=0x6040c0(GFP_KERNEL|__GFP_COMP), nodemask=(null), order=0, oom_score_adj=0
...
[ 4.857565] kmalloc-2048 59164KB 59164KB

The crash kernel only has 256M memory, and 59M is pretty big here.
(Note: the related code has been changed and optimised in recent
kernel [2], these logs are picked just to demo the problem)

So add an way to track each kmalloc's memory waste info, and
leverage the existing SLUB debug framework to show its call stack
of original allocation, so that user can evaluate the waste
situation, identify some hot spots and optimize accordingly, for
a better utilization of memory.

The waste info is integrated into existing interface:
/sys/kernel/debug/slab/kmalloc-xx/alloc_traces, one example of
'kmalloc-4k' after boot is:

126 ixgbe_alloc_q_vector+0xa5/0x4a0 [ixgbe] waste=233856/1856 age=1493302/1493830/1494358 pid=1284 cpus=32 nodes=1
__slab_alloc.isra.86+0x52/0x80
__kmalloc_node+0x143/0x350
ixgbe_alloc_q_vector+0xa5/0x4a0 [ixgbe]
ixgbe_init_interrupt_scheme+0x1a6/0x730 [ixgbe]
ixgbe_probe+0xc8e/0x10d0 [ixgbe]
local_pci_probe+0x42/0x80
work_for_cpu_fn+0x13/0x20
process_one_work+0x1c5/0x390

which means in 'kmalloc-4k' slab, there are 126 requests of
2240 bytes which got a 4KB space (wasting 1856 bytes each
and 233856 bytes in total). And when system starts some real
workload like multiple docker instances, there are more
severe waste.

[1]. https://lkml.org/lkml/2019/8/12/266
[2]. https://lore.kernel.org/lkml/[email protected]/

[Thanks Hyeonggon for pointing out several bugs about sorting/format]
[Thanks Vlastimil for suggesting way to reduce memory usage of
orig_size and keep it only for kmalloc objects]

Signed-off-by: Feng Tang <[email protected]>
---
include/linux/slab.h | 2 +
mm/slub.c | 99 ++++++++++++++++++++++++++++++++++++--------
2 files changed, 83 insertions(+), 18 deletions(-)

diff --git a/include/linux/slab.h b/include/linux/slab.h
index 0fefdf528e0d..a713b0e5bbcd 100644
--- a/include/linux/slab.h
+++ b/include/linux/slab.h
@@ -29,6 +29,8 @@
#define SLAB_RED_ZONE ((slab_flags_t __force)0x00000400U)
/* DEBUG: Poison objects */
#define SLAB_POISON ((slab_flags_t __force)0x00000800U)
+/* Indicate a kmalloc slab */
+#define SLAB_KMALLOC ((slab_flags_t __force)0x00001000U)
/* Align objs on cache lines */
#define SLAB_HWCACHE_ALIGN ((slab_flags_t __force)0x00002000U)
/* Use GFP_DMA memory */
diff --git a/mm/slub.c b/mm/slub.c
index 862dbd9af4f5..2e046cc10b84 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -191,6 +191,12 @@ static inline bool kmem_cache_debug(struct kmem_cache *s)
return kmem_cache_debug_flags(s, SLAB_DEBUG_FLAGS);
}

+static inline bool slub_debug_orig_size(struct kmem_cache *s)
+{
+ return (kmem_cache_debug_flags(s, SLAB_STORE_USER) &&
+ (s->flags & SLAB_KMALLOC));
+}
+
void *fixup_red_left(struct kmem_cache *s, void *p)
{
if (kmem_cache_debug_flags(s, SLAB_RED_ZONE))
@@ -816,6 +822,33 @@ static void print_slab_info(const struct slab *slab)
folio_flags(folio, 0));
}

+static inline void set_orig_size(struct kmem_cache *s,
+ void *object, unsigned int orig_size)
+{
+ void *p = kasan_reset_tag(object);
+
+ if (!slub_debug_orig_size(s))
+ return;
+
+ p += get_info_end(s);
+ p += sizeof(struct track) * 2;
+
+ *(unsigned int *)p = orig_size;
+}
+
+static unsigned int get_orig_size(struct kmem_cache *s, void *object)
+{
+ void *p = kasan_reset_tag(object);
+
+ if (!slub_debug_orig_size(s))
+ return s->object_size;
+
+ p += get_info_end(s);
+ p += sizeof(struct track) * 2;
+
+ return *(unsigned int *)p;
+}
+
static void slab_bug(struct kmem_cache *s, char *fmt, ...)
{
struct va_format vaf;
@@ -875,6 +908,9 @@ static void print_trailer(struct kmem_cache *s, struct slab *slab, u8 *p)
if (s->flags & SLAB_STORE_USER)
off += 2 * sizeof(struct track);

+ if (slub_debug_orig_size(s))
+ off += sizeof(unsigned int);
+
off += kasan_metadata_size(s);

if (off != size_from_object(s))
@@ -1026,10 +1062,14 @@ static int check_pad_bytes(struct kmem_cache *s, struct slab *slab, u8 *p)
{
unsigned long off = get_info_end(s); /* The end of info */

- if (s->flags & SLAB_STORE_USER)
+ if (s->flags & SLAB_STORE_USER) {
/* We also have user information there */
off += 2 * sizeof(struct track);

+ if (s->flags & SLAB_KMALLOC)
+ off += sizeof(unsigned int);
+ }
+
off += kasan_metadata_size(s);

if (size_from_object(s) == off)
@@ -1325,7 +1365,8 @@ static inline int alloc_consistency_checks(struct kmem_cache *s,

static noinline int alloc_debug_processing(struct kmem_cache *s,
struct slab *slab,
- void *object, unsigned long addr)
+ void *object, unsigned long addr,
+ unsigned int orig_size)
{
if (s->flags & SLAB_CONSISTENCY_CHECKS) {
if (!alloc_consistency_checks(s, slab, object))
@@ -1335,6 +1376,9 @@ static noinline int alloc_debug_processing(struct kmem_cache *s,
/* Success perform special debug activities for allocs */
if (s->flags & SLAB_STORE_USER)
set_track(s, object, TRACK_ALLOC, addr);
+
+ set_orig_size(s, object, orig_size);
+
trace(s, slab, object, 1);
init_object(s, object, SLUB_RED_ACTIVE);
return 1;
@@ -1661,7 +1705,8 @@ static inline
void setup_slab_debug(struct kmem_cache *s, struct slab *slab, void *addr) {}

static inline int alloc_debug_processing(struct kmem_cache *s,
- struct slab *slab, void *object, unsigned long addr) { return 0; }
+ struct slab *slab, void *object, unsigned long addr,
+ unsigned int orig_size) { return 0; }

static inline int free_debug_processing(
struct kmem_cache *s, struct slab *slab,
@@ -2905,7 +2950,7 @@ static inline void *get_freelist(struct kmem_cache *s, struct slab *slab)
* already disabled (which is the case for bulk allocation).
*/
static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
- unsigned long addr, struct kmem_cache_cpu *c)
+ unsigned long addr, struct kmem_cache_cpu *c, unsigned int orig_size)
{
void *freelist;
struct slab *slab;
@@ -3048,7 +3093,7 @@ static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
check_new_slab:

if (kmem_cache_debug(s)) {
- if (!alloc_debug_processing(s, slab, freelist, addr)) {
+ if (!alloc_debug_processing(s, slab, freelist, addr, orig_size)) {
/* Slab failed checks. Next slab needed */
goto new_slab;
} else {
@@ -3102,7 +3147,7 @@ static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
* pointer.
*/
static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
- unsigned long addr, struct kmem_cache_cpu *c)
+ unsigned long addr, struct kmem_cache_cpu *c, unsigned int orig_size)
{
void *p;

@@ -3115,7 +3160,7 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
c = slub_get_cpu_ptr(s->cpu_slab);
#endif

- p = ___slab_alloc(s, gfpflags, node, addr, c);
+ p = ___slab_alloc(s, gfpflags, node, addr, c, orig_size);
#ifdef CONFIG_PREEMPT_COUNT
slub_put_cpu_ptr(s->cpu_slab);
#endif
@@ -3206,7 +3251,7 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s, struct list_l
*/
if (IS_ENABLED(CONFIG_PREEMPT_RT) ||
unlikely(!object || !slab || !node_match(slab, node))) {
- object = __slab_alloc(s, gfpflags, node, addr, c);
+ object = __slab_alloc(s, gfpflags, node, addr, c, orig_size);
} else {
void *next_object = get_freepointer_safe(s, object);

@@ -3709,7 +3754,7 @@ int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
* of re-populating per CPU c->freelist
*/
p[i] = ___slab_alloc(s, flags, NUMA_NO_NODE,
- _RET_IP_, c);
+ _RET_IP_, c, s->object_size);
if (unlikely(!p[i]))
goto error;

@@ -4112,12 +4157,17 @@ static int calculate_sizes(struct kmem_cache *s)
}

#ifdef CONFIG_SLUB_DEBUG
- if (flags & SLAB_STORE_USER)
+ if (flags & SLAB_STORE_USER) {
/*
* Need to store information about allocs and frees after
* the object.
*/
size += 2 * sizeof(struct track);
+
+ /* Save the original kmalloc request size */
+ if (flags & SLAB_KMALLOC)
+ size += sizeof(unsigned int);
+ }
#endif

kasan_cache_create(s, &size, &s->flags);
@@ -4842,7 +4892,7 @@ void __init kmem_cache_init(void)

/* Now we can use the kmem_cache to allocate kmalloc slabs */
setup_kmalloc_cache_index_table();
- create_kmalloc_caches(0);
+ create_kmalloc_caches(SLAB_KMALLOC);

/* Setup random freelists for each cache */
init_freelist_randomization();
@@ -5068,6 +5118,7 @@ struct location {
depot_stack_handle_t handle;
unsigned long count;
unsigned long addr;
+ unsigned long waste;
long long sum_time;
long min_time;
long max_time;
@@ -5114,13 +5165,15 @@ static int alloc_loc_track(struct loc_track *t, unsigned long max, gfp_t flags)
}

static int add_location(struct loc_track *t, struct kmem_cache *s,
- const struct track *track)
+ const struct track *track,
+ unsigned int orig_size)
{
long start, end, pos;
struct location *l;
- unsigned long caddr, chandle;
+ unsigned long caddr, chandle, cwaste;
unsigned long age = jiffies - track->when;
depot_stack_handle_t handle = 0;
+ unsigned int waste = s->object_size - orig_size;

#ifdef CONFIG_STACKDEPOT
handle = READ_ONCE(track->handle);
@@ -5138,11 +5191,13 @@ static int add_location(struct loc_track *t, struct kmem_cache *s,
if (pos == end)
break;

- caddr = t->loc[pos].addr;
- chandle = t->loc[pos].handle;
- if ((track->addr == caddr) && (handle == chandle)) {
+ l = &t->loc[pos];
+ caddr = l->addr;
+ chandle = l->handle;
+ cwaste = l->waste;
+ if ((track->addr == caddr) && (handle == chandle) &&
+ (waste == cwaste)) {

- l = &t->loc[pos];
l->count++;
if (track->when) {
l->sum_time += age;
@@ -5167,6 +5222,9 @@ static int add_location(struct loc_track *t, struct kmem_cache *s,
end = pos;
else if (track->addr == caddr && handle < chandle)
end = pos;
+ else if (track->addr == caddr && handle == chandle &&
+ waste < cwaste)
+ end = pos;
else
start = pos;
}
@@ -5190,6 +5248,7 @@ static int add_location(struct loc_track *t, struct kmem_cache *s,
l->min_pid = track->pid;
l->max_pid = track->pid;
l->handle = handle;
+ l->waste = waste;
cpumask_clear(to_cpumask(l->cpus));
cpumask_set_cpu(track->cpu, to_cpumask(l->cpus));
nodes_clear(l->nodes);
@@ -5208,7 +5267,7 @@ static void process_slab(struct loc_track *t, struct kmem_cache *s,

for_each_object(p, s, addr, slab->objects)
if (!test_bit(__obj_to_index(s, addr, p), obj_map))
- add_location(t, s, get_track(s, p, alloc));
+ add_location(t, s, get_track(s, p, alloc), get_orig_size(s, p));
}
#endif /* CONFIG_DEBUG_FS */
#endif /* CONFIG_SLUB_DEBUG */
@@ -6078,6 +6137,10 @@ static int slab_debugfs_show(struct seq_file *seq, void *v)
else
seq_puts(seq, "<not-available>");

+ if (l->waste)
+ seq_printf(seq, " waste=%lu/%lu",
+ l->count * l->waste, l->waste);
+
if (l->sum_time != l->min_time) {
seq_printf(seq, " age=%ld/%llu/%ld",
l->min_time, div_u64(l->sum_time, l->count),
--
2.27.0

2022-07-27 07:23:43

by Feng Tang

[permalink] [raw]
Subject: [PATCH v3 3/3] mm/slub: extend redzone check to cover extra allocated kmalloc space than requested

kmalloc will round up the request size to a fixed size (mostly power
of 2), so there could be a extra space than what is requested, whose
size is the actual buffer size minus original request size.

To better detect out of bound access or abuse of this space, add
redzone sanity check for it.

And in current kernel, some kmalloc user already knows the existence
of the space and utilizes it after calling 'ksize()' to know the real
size of the allocated buffer. So we skip the sanity check for objects
which have been called with ksize(), as treating them as legitimate
users.

Suggested-by: Vlastimil Babka <[email protected]>
Signed-off-by: Feng Tang <[email protected]>
---
mm/slub.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 49 insertions(+), 3 deletions(-)

diff --git a/mm/slub.c b/mm/slub.c
index 946919066a4b..added2653bb0 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -836,6 +836,11 @@ static inline void set_orig_size(struct kmem_cache *s,
*(unsigned int *)p = orig_size;
}

+static inline void skip_orig_size_check(struct kmem_cache *s, const void *object)
+{
+ set_orig_size(s, (void *)object, s->object_size);
+}
+
static unsigned int get_orig_size(struct kmem_cache *s, void *object)
{
void *p = kasan_reset_tag(object);
@@ -967,13 +972,35 @@ static __printf(3, 4) void slab_err(struct kmem_cache *s, struct slab *slab,
static void init_object(struct kmem_cache *s, void *object, u8 val)
{
u8 *p = kasan_reset_tag(object);
+ unsigned int orig_size = s->object_size;

- if (s->flags & SLAB_RED_ZONE)
+ if (s->flags & SLAB_RED_ZONE) {
memset(p - s->red_left_pad, val, s->red_left_pad);

+ if (slub_debug_orig_size(s) && val == SLUB_RED_ACTIVE) {
+ unsigned int zone_start;
+
+ orig_size = get_orig_size(s, object);
+ zone_start = orig_size;
+
+ if (!freeptr_outside_object(s))
+ zone_start = max_t(unsigned int, orig_size,
+ s->offset + sizeof(void *));
+
+ /*
+ * Redzone the extra allocated space by kmalloc
+ * than requested.
+ */
+ if (zone_start < s->object_size)
+ memset(p + zone_start, val,
+ s->object_size - zone_start);
+ }
+
+ }
+
if (s->flags & __OBJECT_POISON) {
- memset(p, POISON_FREE, s->object_size - 1);
- p[s->object_size - 1] = POISON_END;
+ memset(p, POISON_FREE, orig_size - 1);
+ p[orig_size - 1] = POISON_END;
}

if (s->flags & SLAB_RED_ZONE)
@@ -1120,6 +1147,7 @@ static int check_object(struct kmem_cache *s, struct slab *slab,
{
u8 *p = object;
u8 *endobject = object + s->object_size;
+ unsigned int orig_size;

if (s->flags & SLAB_RED_ZONE) {
if (!check_bytes_and_report(s, slab, object, "Left Redzone",
@@ -1129,6 +1157,20 @@ static int check_object(struct kmem_cache *s, struct slab *slab,
if (!check_bytes_and_report(s, slab, object, "Right Redzone",
endobject, val, s->inuse - s->object_size))
return 0;
+
+ if (slub_debug_orig_size(s) && val == SLUB_RED_ACTIVE) {
+ orig_size = get_orig_size(s, object);
+
+ if (!freeptr_outside_object(s))
+ orig_size = max_t(unsigned int, orig_size,
+ s->offset + sizeof(void *));
+ if (s->object_size > orig_size &&
+ !check_bytes_and_report(s, slab, object,
+ "kmalloc Redzone", p + orig_size,
+ val, s->object_size - orig_size)) {
+ return 0;
+ }
+ }
} else {
if ((s->flags & SLAB_POISON) && s->object_size < s->inuse) {
check_bytes_and_report(s, slab, p, "Alignment padding",
@@ -4588,6 +4630,10 @@ size_t __ksize(const void *object)
if (unlikely(!folio_test_slab(folio)))
return folio_size(folio);

+#ifdef CONFIG_SLUB_DEBUG
+ skip_orig_size_check(folio_slab(folio)->slab_cache, object);
+#endif
+
return slab_ksize(folio_slab(folio)->slab_cache);
}
EXPORT_SYMBOL(__ksize);
--
2.27.0

2022-07-27 07:25:37

by Feng Tang

[permalink] [raw]
Subject: [PATCH v3 2/3] mm/slub: only zero the requested size of buffer for kzalloc

kzalloc/kmalloc will round up the request size to a fixed size
(mostly power of 2), so the allocated memory could be more than
requested. Currently kzalloc family APIs will zero all the
allocated memory.

To detect out-of-bound usage of the extra allocated memory, only
zero the requested part, so that sanity check could be added to
the extra space later.

For kzalloc users who will call ksize() later and utilize this
extra space, please be aware that the space is not zeroed any
more.

Signed-off-by: Feng Tang <[email protected]>
---
mm/slab.c | 8 ++++----
mm/slab.h | 9 +++++++--
mm/slub.c | 6 +++---
3 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/mm/slab.c b/mm/slab.c
index 5e73e2d80222..771f7c57d3ef 100644
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -3236,7 +3236,7 @@ slab_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid, size_t orig_
init = slab_want_init_on_alloc(flags, cachep);

out_hooks:
- slab_post_alloc_hook(cachep, objcg, flags, 1, &ptr, init);
+ slab_post_alloc_hook(cachep, objcg, flags, 1, &ptr, init, 0);
return ptr;
}

@@ -3299,7 +3299,7 @@ slab_alloc(struct kmem_cache *cachep, struct list_lru *lru, gfp_t flags,
init = slab_want_init_on_alloc(flags, cachep);

out:
- slab_post_alloc_hook(cachep, objcg, flags, 1, &objp, init);
+ slab_post_alloc_hook(cachep, objcg, flags, 1, &objp, init, 0);
return objp;
}

@@ -3546,13 +3546,13 @@ int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
* Done outside of the IRQ disabled section.
*/
slab_post_alloc_hook(s, objcg, flags, size, p,
- slab_want_init_on_alloc(flags, s));
+ slab_want_init_on_alloc(flags, s), 0);
/* FIXME: Trace call missing. Christoph would like a bulk variant */
return size;
error:
local_irq_enable();
cache_alloc_debugcheck_after_bulk(s, flags, i, p, _RET_IP_);
- slab_post_alloc_hook(s, objcg, flags, i, p, false);
+ slab_post_alloc_hook(s, objcg, flags, i, p, false, 0);
kmem_cache_free_bulk(s, i, p);
return 0;
}
diff --git a/mm/slab.h b/mm/slab.h
index 4ec82bec15ec..7b53868efe6d 100644
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -710,12 +710,17 @@ static inline struct kmem_cache *slab_pre_alloc_hook(struct kmem_cache *s,

static inline void slab_post_alloc_hook(struct kmem_cache *s,
struct obj_cgroup *objcg, gfp_t flags,
- size_t size, void **p, bool init)
+ size_t size, void **p, bool init,
+ unsigned int orig_size)
{
size_t i;

flags &= gfp_allowed_mask;

+ /* If original request size(kmalloc) is not set, use object_size */
+ if (!orig_size)
+ orig_size = s->object_size;
+
/*
* As memory initialization might be integrated into KASAN,
* kasan_slab_alloc and initialization memset must be
@@ -726,7 +731,7 @@ static inline void slab_post_alloc_hook(struct kmem_cache *s,
for (i = 0; i < size; i++) {
p[i] = kasan_slab_alloc(s, p[i], flags, init);
if (p[i] && init && !kasan_has_integrated_init())
- memset(p[i], 0, s->object_size);
+ memset(p[i], 0, orig_size);
kmemleak_alloc_recursive(p[i], s->object_size, 1,
s->flags, flags);
}
diff --git a/mm/slub.c b/mm/slub.c
index 2e046cc10b84..946919066a4b 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -3285,7 +3285,7 @@ static __always_inline void *slab_alloc_node(struct kmem_cache *s, struct list_l
init = slab_want_init_on_alloc(gfpflags, s);

out:
- slab_post_alloc_hook(s, objcg, gfpflags, 1, &object, init);
+ slab_post_alloc_hook(s, objcg, gfpflags, 1, &object, init, orig_size);

return object;
}
@@ -3778,11 +3778,11 @@ int kmem_cache_alloc_bulk(struct kmem_cache *s, gfp_t flags, size_t size,
* Done outside of the IRQ disabled fastpath loop.
*/
slab_post_alloc_hook(s, objcg, flags, size, p,
- slab_want_init_on_alloc(flags, s));
+ slab_want_init_on_alloc(flags, s), 0);
return i;
error:
slub_put_cpu_ptr(s->cpu_slab);
- slab_post_alloc_hook(s, objcg, flags, i, p, false);
+ slab_post_alloc_hook(s, objcg, flags, i, p, false, 0);
kmem_cache_free_bulk(s, i, p);
return 0;
}
--
2.27.0

2022-07-27 10:41:02

by Christoph Lameter

[permalink] [raw]
Subject: Re: [PATCH v3 1/3] mm/slub: enable debugging memory wasting of kmalloc

On Wed, 27 Jul 2022, Feng Tang wrote:

> @@ -2905,7 +2950,7 @@ static inline void *get_freelist(struct kmem_cache *s, struct slab *slab)
> * already disabled (which is the case for bulk allocation).
> */
> static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
> - unsigned long addr, struct kmem_cache_cpu *c)
> + unsigned long addr, struct kmem_cache_cpu *c, unsigned int orig_size)
> {
> void *freelist;
> struct slab *slab;
> @@ -3102,7 +3147,7 @@ static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
> * pointer.
> */
> static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
> - unsigned long addr, struct kmem_cache_cpu *c)
> + unsigned long addr, struct kmem_cache_cpu *c, unsigned int orig_size)
> {
> void *p;
>
> @@ -3115,7 +3160,7 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
> c = slub_get_cpu_ptr(s->cpu_slab);
> #endif
>
> - p = ___slab_alloc(s, gfpflags, node, addr, c);
> + p = ___slab_alloc(s, gfpflags, node, addr, c, orig_size);
> #ifdef CONFIG_PREEMPT_COUNT
> slub_put_cpu_ptr(s->cpu_slab);

This is modifying and making execution of standard slab functions more
expensive. Could you restrict modifications to the kmalloc subsystem?

kmem_cache_alloc() and friends are not doing any rounding up to power of
two sizes.

What is happening here is that you pass kmalloc object size info through
the kmem_cache_alloc functions so that the regular allocation functions
debug functionality can then save the kmalloc specific object request
size. This is active even when no debugging options are enabled.

Can you avoid that? Have kmalloc do the object allocation without passing
through the kmalloc request size and then add the original size info
to the debug field later after execution continues in the kmalloc functions?


2022-07-27 13:37:48

by Feng Tang

[permalink] [raw]
Subject: Re: [PATCH v3 1/3] mm/slub: enable debugging memory wasting of kmalloc



On 2022/7/27 18:20, Christoph Lameter wrote:
> On Wed, 27 Jul 2022, Feng Tang wrote:
>
>> @@ -2905,7 +2950,7 @@ static inline void *get_freelist(struct kmem_cache *s, struct slab *slab)
>> * already disabled (which is the case for bulk allocation).
>> */
>> static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
>> - unsigned long addr, struct kmem_cache_cpu *c)
>> + unsigned long addr, struct kmem_cache_cpu *c, unsigned int orig_size)
>> {
>> void *freelist;
>> struct slab *slab;
>> @@ -3102,7 +3147,7 @@ static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
>> * pointer.
>> */
>> static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
>> - unsigned long addr, struct kmem_cache_cpu *c)
>> + unsigned long addr, struct kmem_cache_cpu *c, unsigned int orig_size)
>> {
>> void *p;
>>
>> @@ -3115,7 +3160,7 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
>> c = slub_get_cpu_ptr(s->cpu_slab);
>> #endif
>>
>> - p = ___slab_alloc(s, gfpflags, node, addr, c);
>> + p = ___slab_alloc(s, gfpflags, node, addr, c, orig_size);
>> #ifdef CONFIG_PREEMPT_COUNT
>> slub_put_cpu_ptr(s->cpu_slab);
>
> This is modifying and making execution of standard slab functions more
> expensive. Could you restrict modifications to the kmalloc subsystem?
>
> kmem_cache_alloc() and friends are not doing any rounding up to power of
> two sizes.
>
> What is happening here is that you pass kmalloc object size info through
> the kmem_cache_alloc functions so that the regular allocation functions
> debug functionality can then save the kmalloc specific object request
> size. This is active even when no debugging options are enabled.

Yes, it indeed is some extra cost which I don't like either.

>
> Can you avoid that? Have kmalloc do the object allocation without passing
> through the kmalloc request size and then add the original size info
> to the debug field later after execution continues in the kmalloc functions?


How about the following patch which adds no new 'orig_size' to core
functions (the following 2nd, 3rd redzone debug patch may also need
some changes).

(Our email server has just been changed, and my mutt can't
work correctly, so the format could be broken, and I attached the
new patch as well. Sorry for the inconvenience!)

Thanks,
Feng

---
diff --git a/include/linux/slab.h b/include/linux/slab.h

index 0fefdf528e0d..a713b0e5bbcd 100644

--- a/include/linux/slab.h

+++ b/include/linux/slab.h

@@ -29,6 +29,8 @@

#define SLAB_RED_ZONE ((slab_flags_t __force)0x00000400U)

/* DEBUG: Poison objects */

#define SLAB_POISON ((slab_flags_t __force)0x00000800U)

+/* Indicate a kmalloc slab */

+#define SLAB_KMALLOC ((slab_flags_t __force)0x00001000U)

/* Align objs on cache lines */

#define SLAB_HWCACHE_ALIGN ((slab_flags_t __force)0x00002000U)

/* Use GFP_DMA memory */

diff --git a/mm/slub.c b/mm/slub.c

index 862dbd9af4f5..97c21a37a6a1 100644

--- a/mm/slub.c

+++ b/mm/slub.c

@@ -191,6 +191,12 @@ static inline bool kmem_cache_debug(struct
kmem_cache *s)

return kmem_cache_debug_flags(s, SLAB_DEBUG_FLAGS);

}



+static inline bool slub_debug_orig_size(struct kmem_cache *s)

+{

+ return (kmem_cache_debug_flags(s, SLAB_STORE_USER) &&

+ (s->flags & SLAB_KMALLOC));

+}

+

void *fixup_red_left(struct kmem_cache *s, void *p)

{

if (kmem_cache_debug_flags(s, SLAB_RED_ZONE))

@@ -816,6 +822,39 @@ static void print_slab_info(const struct slab *slab)

folio_flags(folio, 0));

}



+static inline unsigned int *get_orig_size_pointer(struct kmem_cache *s,

+ void *object)

+{

+ void *p = kasan_reset_tag(object);

+

+ p += get_info_end(s);

+ p += sizeof(struct track) * 2;

+ return (unsigned int *)p;

+}

+

+static void set_orig_size(struct kmem_cache *s,

+ void *object, unsigned int orig_size)

+{

+ unsigned int *p;

+

+ if (!slub_debug_orig_size(s))

+ return;

+

+ p = get_orig_size_pointer(s, object);

+ *p = orig_size;

+}

+

+static unsigned int get_orig_size(struct kmem_cache *s, void *object)

+{

+ unsigned int *p;

+

+ if (!slub_debug_orig_size(s))

+ return s->object_size;

+

+ p = get_orig_size_pointer(s, object);

+ return *p;

+}

+

static void slab_bug(struct kmem_cache *s, char *fmt, ...)

{

struct va_format vaf;

@@ -875,6 +914,9 @@ static void print_trailer(struct kmem_cache *s,
struct slab *slab, u8 *p)

if (s->flags & SLAB_STORE_USER)

off += 2 * sizeof(struct track);



+ if (slub_debug_orig_size(s))

+ off += sizeof(unsigned int);

+

off += kasan_metadata_size(s);



if (off != size_from_object(s))

@@ -1026,10 +1068,14 @@ static int check_pad_bytes(struct kmem_cache *s,
struct slab *slab, u8 *p)

{

unsigned long off = get_info_end(s); /* The end of info */



- if (s->flags & SLAB_STORE_USER)

+ if (s->flags & SLAB_STORE_USER) {

/* We also have user information there */

off += 2 * sizeof(struct track);



+ if (s->flags & SLAB_KMALLOC)

+ off += sizeof(unsigned int);

+ }

+

off += kasan_metadata_size(s);



if (size_from_object(s) == off)

@@ -1335,6 +1381,7 @@ static noinline int alloc_debug_processing(struct
kmem_cache *s,

/* Success perform special debug activities for allocs */

if (s->flags & SLAB_STORE_USER)

set_track(s, object, TRACK_ALLOC, addr);

+

trace(s, slab, object, 1);

init_object(s, object, SLUB_RED_ACTIVE);

return 1;

@@ -3240,6 +3287,9 @@ static __always_inline void
*slab_alloc_node(struct kmem_cache *s, struct list_l

init = slab_want_init_on_alloc(gfpflags, s);



out:

+#ifdef CONFIG_SLUB_DEBUG

+ set_orig_size(s, object, orig_size);

+#endif

slab_post_alloc_hook(s, objcg, gfpflags, 1, &object, init);



return object;

@@ -4112,12 +4162,17 @@ static int calculate_sizes(struct kmem_cache *s)

}



#ifdef CONFIG_SLUB_DEBUG

- if (flags & SLAB_STORE_USER)

+ if (flags & SLAB_STORE_USER) {

/*

* Need to store information about allocs and frees after

* the object.

*/

size += 2 * sizeof(struct track);

+

+ /* Save the original kmalloc request size */

+ if (flags & SLAB_KMALLOC)

+ size += sizeof(unsigned int);

+ }

#endif



kasan_cache_create(s, &size, &s->flags);

@@ -4842,7 +4897,7 @@ void __init kmem_cache_init(void)



/* Now we can use the kmem_cache to allocate kmalloc slabs */

setup_kmalloc_cache_index_table();

- create_kmalloc_caches(0);

+ create_kmalloc_caches(SLAB_KMALLOC);



/* Setup random freelists for each cache */

init_freelist_randomization();

@@ -5068,6 +5123,7 @@ struct location {

depot_stack_handle_t handle;

unsigned long count;

unsigned long addr;

+ unsigned long waste;

long long sum_time;

long min_time;

long max_time;

@@ -5114,13 +5170,15 @@ static int alloc_loc_track(struct loc_track *t,
unsigned long max, gfp_t flags)

}



static int add_location(struct loc_track *t, struct kmem_cache *s,

- const struct track *track)

+ const struct track *track,

+ unsigned int orig_size)

{

long start, end, pos;

struct location *l;

- unsigned long caddr, chandle;

+ unsigned long caddr, chandle, cwaste;

unsigned long age = jiffies - track->when;

depot_stack_handle_t handle = 0;

+ unsigned int waste = s->object_size - orig_size;



#ifdef CONFIG_STACKDEPOT

handle = READ_ONCE(track->handle);

@@ -5138,11 +5196,13 @@ static int add_location(struct loc_track *t,
struct kmem_cache *s,

if (pos == end)

break;



- caddr = t->loc[pos].addr;

- chandle = t->loc[pos].handle;

- if ((track->addr == caddr) && (handle == chandle)) {

+ l = &t->loc[pos];

+ caddr = l->addr;

+ chandle = l->handle;

+ cwaste = l->waste;

+ if ((track->addr == caddr) && (handle == chandle) &&

+ (waste == cwaste)) {



- l = &t->loc[pos];

l->count++;

if (track->when) {

l->sum_time += age;

@@ -5167,6 +5227,9 @@ static int add_location(struct loc_track *t,
struct kmem_cache *s,

end = pos;

else if (track->addr == caddr && handle < chandle)

end = pos;

+ else if (track->addr == caddr && handle == chandle &&

+ waste < cwaste)

+ end = pos;

else

start = pos;

}

@@ -5190,6 +5253,7 @@ static int add_location(struct loc_track *t,
struct kmem_cache *s,

l->min_pid = track->pid;

l->max_pid = track->pid;

l->handle = handle;

+ l->waste = waste;

cpumask_clear(to_cpumask(l->cpus));

cpumask_set_cpu(track->cpu, to_cpumask(l->cpus));

nodes_clear(l->nodes);

@@ -5208,7 +5272,7 @@ static void process_slab(struct loc_track *t,
struct kmem_cache *s,



for_each_object(p, s, addr, slab->objects)

if (!test_bit(__obj_to_index(s, addr, p), obj_map))

- add_location(t, s, get_track(s, p, alloc));

+ add_location(t, s, get_track(s, p, alloc), get_orig_size(s, p));

}

#endif /* CONFIG_DEBUG_FS */

#endif /* CONFIG_SLUB_DEBUG */

@@ -6078,6 +6142,10 @@ static int slab_debugfs_show(struct seq_file
*seq, void *v)

else

seq_puts(seq, "<not-available>");



+ if (l->waste)

+ seq_printf(seq, " waste=%lu/%lu",

+ l->count * l->waste, l->waste);

+

if (l->sum_time != l->min_time) {

seq_printf(seq, " age=%ld/%llu/%ld",

l->min_time, div_u64(l->sum_time, l->count),


Attachments:
kmalloc_debug.patch (6.50 kB)

2022-07-27 14:53:35

by Vlastimil Babka

[permalink] [raw]
Subject: Re: [PATCH v3 1/3] mm/slub: enable debugging memory wasting of kmalloc

On 7/27/22 12:20, Christoph Lameter wrote:
> On Wed, 27 Jul 2022, Feng Tang wrote:
>
>> @@ -2905,7 +2950,7 @@ static inline void *get_freelist(struct kmem_cache *s, struct slab *slab)
>> * already disabled (which is the case for bulk allocation).
>> */
>> static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
>> - unsigned long addr, struct kmem_cache_cpu *c)
>> + unsigned long addr, struct kmem_cache_cpu *c, unsigned int orig_size)
>> {
>> void *freelist;
>> struct slab *slab;
>> @@ -3102,7 +3147,7 @@ static void *___slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
>> * pointer.
>> */
>> static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
>> - unsigned long addr, struct kmem_cache_cpu *c)
>> + unsigned long addr, struct kmem_cache_cpu *c, unsigned int orig_size)
>> {
>> void *p;
>>
>> @@ -3115,7 +3160,7 @@ static void *__slab_alloc(struct kmem_cache *s, gfp_t gfpflags, int node,
>> c = slub_get_cpu_ptr(s->cpu_slab);
>> #endif
>>
>> - p = ___slab_alloc(s, gfpflags, node, addr, c);
>> + p = ___slab_alloc(s, gfpflags, node, addr, c, orig_size);
>> #ifdef CONFIG_PREEMPT_COUNT
>> slub_put_cpu_ptr(s->cpu_slab);
>
> This is modifying and making execution of standard slab functions more
> expensive. Could you restrict modifications to the kmalloc subsystem?
>
> kmem_cache_alloc() and friends are not doing any rounding up to power of
> two sizes.
>
> What is happening here is that you pass kmalloc object size info through
> the kmem_cache_alloc functions so that the regular allocation functions
> debug functionality can then save the kmalloc specific object request
> size. This is active even when no debugging options are enabled.

I don't think the extra orig_size parameter (unused for non-debug caches)
adds any noticeable overhead. In slab_alloc_node() we already have the
orig_size parameter (for both kmalloc and non-kmalloc caches) before this
patch, and it remains unused in the cmpxchg based fast path. The patch adds
it to __slab_alloc() which is not the fast path, and it's still unused for
non-debug caches there. So the overhead is basically one less register
available (because of the extra param) in a slow path and that should be
immeasurable.

> Can you avoid that? Have kmalloc do the object allocation without passing
> through the kmalloc request size and then add the original size info
> to the debug field later after execution continues in the kmalloc functions?

That approach is problematic wrt patches 2+3 if we want to use orig_size to
affect the boundaries of zero-init and redzoning.
Also it goes against the attempt to fix races wrt validation, see [1] where
the idea is to have alloc_debug_processing() including redzoning done under
n->list_lock and for that should have orig_size passed there as well.

[1] https://lore.kernel.org/all/[email protected]/

2022-07-31 07:04:52

by Oliver Sang

[permalink] [raw]
Subject: [mm/slub] 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten



Greeting,

FYI, we noticed the following commit (built with gcc-11):

commit: 3616799128612e04ed919579e2c7b0dccf6bcb00 ("[PATCH v3 3/3] mm/slub: extend redzone check to cover extra allocated kmalloc space than requested")
url: https://github.com/intel-lab-lkp/linux/commits/Feng-Tang/mm-slub-some-debug-enhancements/20220727-151318
base: git://git.kernel.org/cgit/linux/kernel/git/vbabka/slab.git for-next
patch link: https://lore.kernel.org/linux-mm/[email protected]

in testcase: boot

on test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 16G

caused below changes (please refer to attached dmesg/kmsg for entire log/backtrace):


If you fix the issue, kindly add following tag
Reported-by: kernel test robot <[email protected]>


[ 50.637839][ T154] =============================================================================
[ 50.639937][ T154] BUG kmalloc-16 (Not tainted): kmalloc Redzone overwritten
[ 50.641291][ T154] -----------------------------------------------------------------------------
[ 50.641291][ T154]
[ 50.643617][ T154] 0xffff88810018464c-0xffff88810018464f @offset=1612. First byte 0x7 instead of 0xcc
[ 50.645311][ T154] Allocated in __sdt_alloc+0x258/0x457 age=14287 cpu=0 pid=1
[ 50.646584][ T154] ___slab_alloc+0x52b/0x5b6
[ 50.647411][ T154] __slab_alloc+0x1a/0x22
[ 50.648374][ T154] __kmalloc_node+0x10c/0x1e1
[ 50.649237][ T154] __sdt_alloc+0x258/0x457
[ 50.650060][ T154] build_sched_domains+0xae/0x10e8
[ 50.650981][ T154] sched_init_smp+0x30/0xa5
[ 50.651805][ T154] kernel_init_freeable+0x1c6/0x23b
[ 50.652767][ T154] kernel_init+0x14/0x127
[ 50.653594][ T154] ret_from_fork+0x1f/0x30
[ 50.654414][ T154] Slab 0xffffea0004006100 objects=28 used=28 fp=0x0000000000000000 flags=0x1fffc0000000201(locked|slab|node=0|zone=1|lastcpupid=0x3fff)
[ 50.656866][ T154] Object 0xffff888100184640 @offset=1600 fp=0xffff888100184520
[ 50.656866][ T154]
[ 50.658410][ T154] Redzone ffff888100184630: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ................
[ 50.660047][ T154] Object ffff888100184640: 00 32 80 00 81 88 ff ff 01 00 00 00 07 00 80 8a .2..............
[ 50.661837][ T154] Redzone ffff888100184650: cc cc cc cc cc cc cc cc ........
[ 50.663454][ T154] Padding ffff8881001846b4: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZZZZZ
[ 50.665225][ T154] CPU: 0 PID: 154 Comm: systemd-udevd Not tainted 5.19.0-rc5-00010-g361679912861 #1
[ 50.666861][ T154] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.0-debian-1.16.0-4 04/01/2014
[ 50.668694][ T154] Call Trace:
[ 50.669331][ T154] <TASK>
[ 50.669832][ T154] dump_stack_lvl+0x57/0x7d
[ 50.670601][ T154] check_bytes_and_report+0xca/0xfe
[ 50.671436][ T154] check_object+0xdc/0x24d
[ 50.672163][ T154] free_debug_processing+0x98/0x210
[ 50.673036][ T154] ? qlist_free_all+0x90/0xde
[ 50.673904][ T154] __slab_free+0x46/0x198
[ 50.674660][ T154] ? lockdep_hardirqs_on_prepare+0x32d/0x34e
[ 50.675746][ T154] qlist_free_all+0xae/0xde
[ 50.676552][ T154] kasan_quarantine_reduce+0x10d/0x145
[ 50.677507][ T154] __kasan_slab_alloc+0x1c/0x5a
[ 50.678327][ T154] slab_post_alloc_hook+0x5a/0xa2
[ 50.679249][ T154] ? getname_flags+0x4b/0x314
[ 50.680069][ T154] kmem_cache_alloc+0x102/0x135
[ 50.680938][ T154] getname_flags+0x4b/0x314
[ 50.681781][ T154] do_sys_openat2+0x7a/0x15c
[ 50.682624][ T154] ? build_open_flags+0x324/0x324
[ 50.683522][ T154] ? __lock_release+0xe8/0x367
[ 50.684407][ T154] do_sys_open+0x6b/0x83
[ 50.685225][ T154] ? file_open_root+0xbf/0xbf
[ 50.686093][ T154] do_syscall_64+0x6e/0x82
[ 50.686895][ T154] ? lockdep_hardirqs_on_prepare+0x32d/0x34e
[ 50.688007][ T154] ? do_syscall_64+0x7c/0x82
[ 50.688859][ T154] ? rcu_read_lock_sched_held+0x60/0x98
[ 50.689780][ T154] ? lockdep_hardirqs_on_prepare+0x32d/0x34e
[ 50.690766][ T154] ? do_syscall_64+0x7c/0x82
[ 50.691591][ T154] ? lockdep_hardirqs_on_prepare+0x32d/0x34e
[ 50.692521][ T154] entry_SYSCALL_64_after_hwframe+0x46/0xb0
[ 50.693535][ T154] RIP: 0033:0x7f60f7d2a767
[ 50.694372][ T154] Code: 25 00 00 41 00 3d 00 00 41 00 74 47 64 8b 04 25 18 00 00 00 85 c0 75 6b 44 89 e2 48 89 ee bf 9c ff ff ff b8 01 01 00 00 0f 05 <48> 3d 00 f0 ff ff 0f 87 95 00 00 00 48 8b 4c 24 28 64 48 2b 0c 25
[ 50.697786][ T154] RSP: 002b:00007ffe8d6644b0 EFLAGS: 00000246 ORIG_RAX: 0000000000000101
[ 50.699213][ T154] RAX: ffffffffffffffda RBX: 00007f60f77916c0 RCX: 00007f60f7d2a767
[ 50.700601][ T154] RDX: 00000000000800c1 RSI: 000056320c6d0431 RDI: 00000000ffffff9c
[ 50.702019][ T154] RBP: 000056320c6d0431 R08: 000056320cec9d30 R09: 00007f60f7c90e20
[ 50.703408][ T154] R10: 00000000000001a4 R11: 0000000000000246 R12: 00000000000800c1
[ 50.704860][ T154] R13: 000056320c6d0431 R14: 00000000ffffffff R15: 00007ffe8d6645b8
[ 50.706282][ T154] </TASK>
[ 50.706848][ T154] Disabling lock debugging due to kernel taint
[ 50.707913][ T154] FIX kmalloc-16: Restoring kmalloc Redzone 0xffff88810018464c-0xffff88810018464f=0xcc



To reproduce:

# build kernel
cd linux
cp config-5.19.0-rc5-00010-g361679912861 .config
make HOSTCC=gcc-11 CC=gcc-11 ARCH=x86_64 olddefconfig prepare modules_prepare bzImage modules
make HOSTCC=gcc-11 CC=gcc-11 ARCH=x86_64 INSTALL_MOD_PATH=<mod-install-dir> modules_install
cd <mod-install-dir>
find lib/ | cpio -o -H newc --quiet | gzip > modules.cgz


git clone https://github.com/intel/lkp-tests.git
cd lkp-tests
bin/lkp qemu -k <bzImage> -m modules.cgz job-script # job-script is attached in this email

# if come across any failure that blocks the test,
# please remove ~/.lkp and /lkp dir to run from a clean state.



--
0-DAY CI Kernel Test Service
https://01.org/lkp



Attachments:
(No filename) (5.93 kB)
config-5.19.0-rc5-00010-g361679912861 (135.49 kB)
job-script (4.96 kB)
dmesg.xz (69.11 kB)
Download all attachments

2022-07-31 08:42:01

by Feng Tang

[permalink] [raw]
Subject: Re: [mm/slub] 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten

Hi Oliver,

On Sun, Jul 31, 2022 at 02:53:17PM +0800, Sang, Oliver wrote:
>
>
> Greeting,
>
> FYI, we noticed the following commit (built with gcc-11):
>
> commit: 3616799128612e04ed919579e2c7b0dccf6bcb00 ("[PATCH v3 3/3] mm/slub: extend redzone check to cover extra allocated kmalloc space than requested")
> url: https://github.com/intel-lab-lkp/linux/commits/Feng-Tang/mm-slub-some-debug-enhancements/20220727-151318
> base: git://git.kernel.org/cgit/linux/kernel/git/vbabka/slab.git for-next
> patch link: https://lore.kernel.org/linux-mm/[email protected]
>
> in testcase: boot
>
> on test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 16G
>
> caused below changes (please refer to attached dmesg/kmsg for entire log/backtrace):
>
>
> If you fix the issue, kindly add following tag
> Reported-by: kernel test robot <[email protected]>
>
>
> [ 50.637839][ T154] =============================================================================
> [ 50.639937][ T154] BUG kmalloc-16 (Not tainted): kmalloc Redzone overwritten
> [ 50.641291][ T154] -----------------------------------------------------------------------------
> [ 50.641291][ T154]
> [ 50.643617][ T154] 0xffff88810018464c-0xffff88810018464f @offset=1612. First byte 0x7 instead of 0xcc
> [ 50.645311][ T154] Allocated in __sdt_alloc+0x258/0x457 age=14287 cpu=0 pid=1
> [ 50.646584][ T154] ___slab_alloc+0x52b/0x5b6
> [ 50.647411][ T154] __slab_alloc+0x1a/0x22
> [ 50.648374][ T154] __kmalloc_node+0x10c/0x1e1
> [ 50.649237][ T154] __sdt_alloc+0x258/0x457
> [ 50.650060][ T154] build_sched_domains+0xae/0x10e8
> [ 50.650981][ T154] sched_init_smp+0x30/0xa5
> [ 50.651805][ T154] kernel_init_freeable+0x1c6/0x23b
> [ 50.652767][ T154] kernel_init+0x14/0x127
> [ 50.653594][ T154] ret_from_fork+0x1f/0x30
> [ 50.654414][ T154] Slab 0xffffea0004006100 objects=28 used=28 fp=0x0000000000000000 flags=0x1fffc0000000201(locked|slab|node=0|zone=1|lastcpupid=0x3fff)
> [ 50.656866][ T154] Object 0xffff888100184640 @offset=1600 fp=0xffff888100184520
> [ 50.656866][ T154]
> [ 50.658410][ T154] Redzone ffff888100184630: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ................
> [ 50.660047][ T154] Object ffff888100184640: 00 32 80 00 81 88 ff ff 01 00 00 00 07 00 80 8a .2..............
> [ 50.661837][ T154] Redzone ffff888100184650: cc cc cc cc cc cc cc cc ........
> [ 50.663454][ T154] Padding ffff8881001846b4: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZZZZZ
> [ 50.665225][ T154] CPU: 0 PID: 154 Comm: systemd-udevd Not tainted 5.19.0-rc5-00010-g361679912861 #1
> [ 50.666861][ T154] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.0-debian-1.16.0-4 04/01/2014
> [ 50.668694][ T154] Call Trace:
> [ 50.669331][ T154] <TASK>
> [ 50.669832][ T154] dump_stack_lvl+0x57/0x7d
> [ 50.670601][ T154] check_bytes_and_report+0xca/0xfe
> [ 50.671436][ T154] check_object+0xdc/0x24d
> [ 50.672163][ T154] free_debug_processing+0x98/0x210
> [ 50.673904][ T154] __slab_free+0x46/0x198
> [ 50.675746][ T154] qlist_free_all+0xae/0xde
> [ 50.676552][ T154] kasan_quarantine_reduce+0x10d/0x145
> [ 50.677507][ T154] __kasan_slab_alloc+0x1c/0x5a
> [ 50.678327][ T154] slab_post_alloc_hook+0x5a/0xa2
> [ 50.680069][ T154] kmem_cache_alloc+0x102/0x135
> [ 50.680938][ T154] getname_flags+0x4b/0x314
> [ 50.681781][ T154] do_sys_openat2+0x7a/0x15c
> [ 50.706848][ T154] Disabling lock debugging due to kernel taint
> [ 50.707913][ T154] FIX kmalloc-16: Restoring kmalloc Redzone 0xffff88810018464c-0xffff88810018464f=0xcc

Thanks for the report!

From the log it happened when kasan is enabled, and my first guess is
the data processing from kmalloc redzone handling had some conflict
with kasan's in allocation path (though I tested some kernel config
with KASAN enabled)

Will study more about kasan and reproduce/debug this. thanks

- Feng

>
> To reproduce:
>
> # build kernel
> cd linux
> cp config-5.19.0-rc5-00010-g361679912861 .config
> make HOSTCC=gcc-11 CC=gcc-11 ARCH=x86_64 olddefconfig prepare modules_prepare bzImage modules
> make HOSTCC=gcc-11 CC=gcc-11 ARCH=x86_64 INSTALL_MOD_PATH=<mod-install-dir> modules_install
> cd <mod-install-dir>
> find lib/ | cpio -o -H newc --quiet | gzip > modules.cgz
>
>
> git clone https://github.com/intel/lkp-tests.git
> cd lkp-tests
> bin/lkp qemu -k <bzImage> -m modules.cgz job-script # job-script is attached in this email
>
> # if come across any failure that blocks the test,
> # please remove ~/.lkp and /lkp dir to run from a clean state.
>
>
>
> --
> 0-DAY CI Kernel Test Service
> https://01.org/lkp

2022-08-01 06:27:35

by Feng Tang

[permalink] [raw]
Subject: Re: [mm/slub] 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten

On Sun, Jul 31, 2022 at 04:16:53PM +0800, Tang, Feng wrote:
> Hi Oliver,
>
> On Sun, Jul 31, 2022 at 02:53:17PM +0800, Sang, Oliver wrote:
> >
> >
> > Greeting,
> >
> > FYI, we noticed the following commit (built with gcc-11):
> >
> > commit: 3616799128612e04ed919579e2c7b0dccf6bcb00 ("[PATCH v3 3/3] mm/slub: extend redzone check to cover extra allocated kmalloc space than requested")
> > url: https://github.com/intel-lab-lkp/linux/commits/Feng-Tang/mm-slub-some-debug-enhancements/20220727-151318
> > base: git://git.kernel.org/cgit/linux/kernel/git/vbabka/slab.git for-next
> > patch link: https://lore.kernel.org/linux-mm/[email protected]
> >
> > in testcase: boot
> >
> > on test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 16G
> >
> > caused below changes (please refer to attached dmesg/kmsg for entire log/backtrace):
> >
> >
> > If you fix the issue, kindly add following tag
> > Reported-by: kernel test robot <[email protected]>
> >
> >
> > [ 50.637839][ T154] =============================================================================
> > [ 50.639937][ T154] BUG kmalloc-16 (Not tainted): kmalloc Redzone overwritten
> > [ 50.641291][ T154] -----------------------------------------------------------------------------
> > [ 50.641291][ T154]
> > [ 50.643617][ T154] 0xffff88810018464c-0xffff88810018464f @offset=1612. First byte 0x7 instead of 0xcc
> > [ 50.645311][ T154] Allocated in __sdt_alloc+0x258/0x457 age=14287 cpu=0 pid=1
> > [ 50.646584][ T154] ___slab_alloc+0x52b/0x5b6
> > [ 50.647411][ T154] __slab_alloc+0x1a/0x22
> > [ 50.648374][ T154] __kmalloc_node+0x10c/0x1e1
> > [ 50.649237][ T154] __sdt_alloc+0x258/0x457
> > [ 50.650060][ T154] build_sched_domains+0xae/0x10e8
> > [ 50.650981][ T154] sched_init_smp+0x30/0xa5
> > [ 50.651805][ T154] kernel_init_freeable+0x1c6/0x23b
> > [ 50.652767][ T154] kernel_init+0x14/0x127
> > [ 50.653594][ T154] ret_from_fork+0x1f/0x30
> > [ 50.654414][ T154] Slab 0xffffea0004006100 objects=28 used=28 fp=0x0000000000000000 flags=0x1fffc0000000201(locked|slab|node=0|zone=1|lastcpupid=0x3fff)
> > [ 50.656866][ T154] Object 0xffff888100184640 @offset=1600 fp=0xffff888100184520
> > [ 50.656866][ T154]
> > [ 50.658410][ T154] Redzone ffff888100184630: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ................
> > [ 50.660047][ T154] Object ffff888100184640: 00 32 80 00 81 88 ff ff 01 00 00 00 07 00 80 8a .2..............
> > [ 50.661837][ T154] Redzone ffff888100184650: cc cc cc cc cc cc cc cc ........
> > [ 50.663454][ T154] Padding ffff8881001846b4: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZZZZZ
> > [ 50.665225][ T154] CPU: 0 PID: 154 Comm: systemd-udevd Not tainted 5.19.0-rc5-00010-g361679912861 #1
> > [ 50.666861][ T154] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.0-debian-1.16.0-4 04/01/2014
> > [ 50.668694][ T154] Call Trace:
> > [ 50.669331][ T154] <TASK>
> > [ 50.669832][ T154] dump_stack_lvl+0x57/0x7d
> > [ 50.670601][ T154] check_bytes_and_report+0xca/0xfe
> > [ 50.671436][ T154] check_object+0xdc/0x24d
> > [ 50.672163][ T154] free_debug_processing+0x98/0x210
> > [ 50.673904][ T154] __slab_free+0x46/0x198
> > [ 50.675746][ T154] qlist_free_all+0xae/0xde
> > [ 50.676552][ T154] kasan_quarantine_reduce+0x10d/0x145
> > [ 50.677507][ T154] __kasan_slab_alloc+0x1c/0x5a
> > [ 50.678327][ T154] slab_post_alloc_hook+0x5a/0xa2
> > [ 50.680069][ T154] kmem_cache_alloc+0x102/0x135
> > [ 50.680938][ T154] getname_flags+0x4b/0x314
> > [ 50.681781][ T154] do_sys_openat2+0x7a/0x15c
> > [ 50.706848][ T154] Disabling lock debugging due to kernel taint
> > [ 50.707913][ T154] FIX kmalloc-16: Restoring kmalloc Redzone 0xffff88810018464c-0xffff88810018464f=0xcc
>
> Thanks for the report!
>
> From the log it happened when kasan is enabled, and my first guess is
> the data processing from kmalloc redzone handling had some conflict
> with kasan's in allocation path (though I tested some kernel config
> with KASAN enabled)
>
> Will study more about kasan and reproduce/debug this. thanks

Cc kansan mail list.

This is really related with KASAN debug, that in free path, some
kmalloc redzone ([orig_size+1, object_size]) area is written by
kasan to save free meta info.

The callstack is:

kfree
slab_free
slab_free_freelist_hook
slab_free_hook
__kasan_slab_free
____kasan_slab_free
kasan_set_free_info
kasan_set_track

And this issue only happens with "kmalloc-16" slab. Kasan has 2
tracks: alloc_track and free_track, for x86_64 test platform, most
of the slabs will reserve space for alloc_track, and reuse the
'object' area for free_track. The kasan free_track is 16 bytes
large, that it will occupy the whole 'kmalloc-16's object area,
so when kmalloc-redzone is enabled by this patch, the 'overwritten'
error is triggered.

But it won't hurt other kmalloc slabs, as kasan's free meta won't
conflict with kmalloc-redzone which stay in the latter part of
kmalloc area.

So the solution I can think of is:
* skip the kmalloc-redzone for kmalloc-16 only, or
* skip kmalloc-redzone if kasan is enabled, or
* let kasan reserve the free meta (16 bytes) outside of object
just like for alloc meta

I don't have way to test kasan's SW/HW tag configuration, which
is only enabled on arm64 now. And I don't know if there will
also be some conflict.

Thanks,
Feng


2022-08-01 07:39:01

by Dmitry Vyukov

[permalink] [raw]
Subject: Re: [mm/slub] 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten

On Mon, 1 Aug 2022 at 08:22, Feng Tang <[email protected]> wrote:
>
> On Sun, Jul 31, 2022 at 04:16:53PM +0800, Tang, Feng wrote:
> > Hi Oliver,
> >
> > On Sun, Jul 31, 2022 at 02:53:17PM +0800, Sang, Oliver wrote:
> > >
> > >
> > > Greeting,
> > >
> > > FYI, we noticed the following commit (built with gcc-11):
> > >
> > > commit: 3616799128612e04ed919579e2c7b0dccf6bcb00 ("[PATCH v3 3/3] mm/slub: extend redzone check to cover extra allocated kmalloc space than requested")
> > > url: https://github.com/intel-lab-lkp/linux/commits/Feng-Tang/mm-slub-some-debug-enhancements/20220727-151318
> > > base: git://git.kernel.org/cgit/linux/kernel/git/vbabka/slab.git for-next
> > > patch link: https://lore.kernel.org/linux-mm/[email protected]
> > >
> > > in testcase: boot
> > >
> > > on test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 16G
> > >
> > > caused below changes (please refer to attached dmesg/kmsg for entire log/backtrace):
> > >
> > >
> > > If you fix the issue, kindly add following tag
> > > Reported-by: kernel test robot <[email protected]>
> > >
> > >
> > > [ 50.637839][ T154] =============================================================================
> > > [ 50.639937][ T154] BUG kmalloc-16 (Not tainted): kmalloc Redzone overwritten
> > > [ 50.641291][ T154] -----------------------------------------------------------------------------
> > > [ 50.641291][ T154]
> > > [ 50.643617][ T154] 0xffff88810018464c-0xffff88810018464f @offset=1612. First byte 0x7 instead of 0xcc
> > > [ 50.645311][ T154] Allocated in __sdt_alloc+0x258/0x457 age=14287 cpu=0 pid=1
> > > [ 50.646584][ T154] ___slab_alloc+0x52b/0x5b6
> > > [ 50.647411][ T154] __slab_alloc+0x1a/0x22
> > > [ 50.648374][ T154] __kmalloc_node+0x10c/0x1e1
> > > [ 50.649237][ T154] __sdt_alloc+0x258/0x457
> > > [ 50.650060][ T154] build_sched_domains+0xae/0x10e8
> > > [ 50.650981][ T154] sched_init_smp+0x30/0xa5
> > > [ 50.651805][ T154] kernel_init_freeable+0x1c6/0x23b
> > > [ 50.652767][ T154] kernel_init+0x14/0x127
> > > [ 50.653594][ T154] ret_from_fork+0x1f/0x30
> > > [ 50.654414][ T154] Slab 0xffffea0004006100 objects=28 used=28 fp=0x0000000000000000 flags=0x1fffc0000000201(locked|slab|node=0|zone=1|lastcpupid=0x3fff)
> > > [ 50.656866][ T154] Object 0xffff888100184640 @offset=1600 fp=0xffff888100184520
> > > [ 50.656866][ T154]
> > > [ 50.658410][ T154] Redzone ffff888100184630: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ................
> > > [ 50.660047][ T154] Object ffff888100184640: 00 32 80 00 81 88 ff ff 01 00 00 00 07 00 80 8a .2..............
> > > [ 50.661837][ T154] Redzone ffff888100184650: cc cc cc cc cc cc cc cc ........
> > > [ 50.663454][ T154] Padding ffff8881001846b4: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZZZZZ
> > > [ 50.665225][ T154] CPU: 0 PID: 154 Comm: systemd-udevd Not tainted 5.19.0-rc5-00010-g361679912861 #1
> > > [ 50.666861][ T154] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.0-debian-1.16.0-4 04/01/2014
> > > [ 50.668694][ T154] Call Trace:
> > > [ 50.669331][ T154] <TASK>
> > > [ 50.669832][ T154] dump_stack_lvl+0x57/0x7d
> > > [ 50.670601][ T154] check_bytes_and_report+0xca/0xfe
> > > [ 50.671436][ T154] check_object+0xdc/0x24d
> > > [ 50.672163][ T154] free_debug_processing+0x98/0x210
> > > [ 50.673904][ T154] __slab_free+0x46/0x198
> > > [ 50.675746][ T154] qlist_free_all+0xae/0xde
> > > [ 50.676552][ T154] kasan_quarantine_reduce+0x10d/0x145
> > > [ 50.677507][ T154] __kasan_slab_alloc+0x1c/0x5a
> > > [ 50.678327][ T154] slab_post_alloc_hook+0x5a/0xa2
> > > [ 50.680069][ T154] kmem_cache_alloc+0x102/0x135
> > > [ 50.680938][ T154] getname_flags+0x4b/0x314
> > > [ 50.681781][ T154] do_sys_openat2+0x7a/0x15c
> > > [ 50.706848][ T154] Disabling lock debugging due to kernel taint
> > > [ 50.707913][ T154] FIX kmalloc-16: Restoring kmalloc Redzone 0xffff88810018464c-0xffff88810018464f=0xcc
> >
> > Thanks for the report!
> >
> > From the log it happened when kasan is enabled, and my first guess is
> > the data processing from kmalloc redzone handling had some conflict
> > with kasan's in allocation path (though I tested some kernel config
> > with KASAN enabled)
> >
> > Will study more about kasan and reproduce/debug this. thanks
>
> Cc kansan mail list.
>
> This is really related with KASAN debug, that in free path, some
> kmalloc redzone ([orig_size+1, object_size]) area is written by
> kasan to save free meta info.
>
> The callstack is:
>
> kfree
> slab_free
> slab_free_freelist_hook
> slab_free_hook
> __kasan_slab_free
> ____kasan_slab_free
> kasan_set_free_info
> kasan_set_track
>
> And this issue only happens with "kmalloc-16" slab. Kasan has 2
> tracks: alloc_track and free_track, for x86_64 test platform, most
> of the slabs will reserve space for alloc_track, and reuse the
> 'object' area for free_track. The kasan free_track is 16 bytes
> large, that it will occupy the whole 'kmalloc-16's object area,
> so when kmalloc-redzone is enabled by this patch, the 'overwritten'
> error is triggered.
>
> But it won't hurt other kmalloc slabs, as kasan's free meta won't
> conflict with kmalloc-redzone which stay in the latter part of
> kmalloc area.
>
> So the solution I can think of is:
> * skip the kmalloc-redzone for kmalloc-16 only, or
> * skip kmalloc-redzone if kasan is enabled, or
> * let kasan reserve the free meta (16 bytes) outside of object
> just like for alloc meta

/\/\/\

Please just not the last option. Memory consumption matters.

I would do whatever is the simplest, e.g. skip the check for
kmalloc-16 when KASAN is enabled.
Or does it make sense to prohibit KASAN+SLUB_DEBUG combination? Does
SLUB_DEBUG add anything on top of KASAN?


> I don't have way to test kasan's SW/HW tag configuration, which
> is only enabled on arm64 now. And I don't know if there will
> also be some conflict.
>
> Thanks,
> Feng
>

2022-08-01 08:40:41

by Feng Tang

[permalink] [raw]
Subject: Re: [mm/slub] 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten

On Mon, Aug 01, 2022 at 03:26:43PM +0800, Dmitry Vyukov wrote:
> On Mon, 1 Aug 2022 at 08:22, Feng Tang <[email protected]> wrote:
> >
> > On Sun, Jul 31, 2022 at 04:16:53PM +0800, Tang, Feng wrote:
> > > Hi Oliver,
> > >
> > > On Sun, Jul 31, 2022 at 02:53:17PM +0800, Sang, Oliver wrote:
> > > >
> > > >
> > > > Greeting,
> > > >
> > > > FYI, we noticed the following commit (built with gcc-11):
> > > >
> > > > commit: 3616799128612e04ed919579e2c7b0dccf6bcb00 ("[PATCH v3 3/3] mm/slub: extend redzone check to cover extra allocated kmalloc space than requested")
> > > > url: https://github.com/intel-lab-lkp/linux/commits/Feng-Tang/mm-slub-some-debug-enhancements/20220727-151318
> > > > base: git://git.kernel.org/cgit/linux/kernel/git/vbabka/slab.git for-next
> > > > patch link: https://lore.kernel.org/linux-mm/[email protected]
> > > >
> > > > in testcase: boot
> > > >
> > > > on test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 16G
> > > >
> > > > caused below changes (please refer to attached dmesg/kmsg for entire log/backtrace):
> > > >
> > > >
> > > > If you fix the issue, kindly add following tag
> > > > Reported-by: kernel test robot <[email protected]>
> > > >
> > > >
> > > > [ 50.637839][ T154] =============================================================================
> > > > [ 50.639937][ T154] BUG kmalloc-16 (Not tainted): kmalloc Redzone overwritten
> > > > [ 50.641291][ T154] -----------------------------------------------------------------------------
> > > > [ 50.641291][ T154]
> > > > [ 50.643617][ T154] 0xffff88810018464c-0xffff88810018464f @offset=1612. First byte 0x7 instead of 0xcc
> > > > [ 50.645311][ T154] Allocated in __sdt_alloc+0x258/0x457 age=14287 cpu=0 pid=1
> > > > [ 50.646584][ T154] ___slab_alloc+0x52b/0x5b6
> > > > [ 50.647411][ T154] __slab_alloc+0x1a/0x22
> > > > [ 50.648374][ T154] __kmalloc_node+0x10c/0x1e1
> > > > [ 50.649237][ T154] __sdt_alloc+0x258/0x457
> > > > [ 50.650060][ T154] build_sched_domains+0xae/0x10e8
> > > > [ 50.650981][ T154] sched_init_smp+0x30/0xa5
> > > > [ 50.651805][ T154] kernel_init_freeable+0x1c6/0x23b
> > > > [ 50.652767][ T154] kernel_init+0x14/0x127
> > > > [ 50.653594][ T154] ret_from_fork+0x1f/0x30
> > > > [ 50.654414][ T154] Slab 0xffffea0004006100 objects=28 used=28 fp=0x0000000000000000 flags=0x1fffc0000000201(locked|slab|node=0|zone=1|lastcpupid=0x3fff)
> > > > [ 50.656866][ T154] Object 0xffff888100184640 @offset=1600 fp=0xffff888100184520
> > > > [ 50.656866][ T154]
> > > > [ 50.658410][ T154] Redzone ffff888100184630: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ................
> > > > [ 50.660047][ T154] Object ffff888100184640: 00 32 80 00 81 88 ff ff 01 00 00 00 07 00 80 8a .2..............
> > > > [ 50.661837][ T154] Redzone ffff888100184650: cc cc cc cc cc cc cc cc ........
> > > > [ 50.663454][ T154] Padding ffff8881001846b4: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZZZZZ
> > > > [ 50.665225][ T154] CPU: 0 PID: 154 Comm: systemd-udevd Not tainted 5.19.0-rc5-00010-g361679912861 #1
> > > > [ 50.666861][ T154] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.0-debian-1.16.0-4 04/01/2014
> > > > [ 50.668694][ T154] Call Trace:
> > > > [ 50.669331][ T154] <TASK>
> > > > [ 50.669832][ T154] dump_stack_lvl+0x57/0x7d
> > > > [ 50.670601][ T154] check_bytes_and_report+0xca/0xfe
> > > > [ 50.671436][ T154] check_object+0xdc/0x24d
> > > > [ 50.672163][ T154] free_debug_processing+0x98/0x210
> > > > [ 50.673904][ T154] __slab_free+0x46/0x198
> > > > [ 50.675746][ T154] qlist_free_all+0xae/0xde
> > > > [ 50.676552][ T154] kasan_quarantine_reduce+0x10d/0x145
> > > > [ 50.677507][ T154] __kasan_slab_alloc+0x1c/0x5a
> > > > [ 50.678327][ T154] slab_post_alloc_hook+0x5a/0xa2
> > > > [ 50.680069][ T154] kmem_cache_alloc+0x102/0x135
> > > > [ 50.680938][ T154] getname_flags+0x4b/0x314
> > > > [ 50.681781][ T154] do_sys_openat2+0x7a/0x15c
> > > > [ 50.706848][ T154] Disabling lock debugging due to kernel taint
> > > > [ 50.707913][ T154] FIX kmalloc-16: Restoring kmalloc Redzone 0xffff88810018464c-0xffff88810018464f=0xcc
> > >
> > > Thanks for the report!
> > >
> > > From the log it happened when kasan is enabled, and my first guess is
> > > the data processing from kmalloc redzone handling had some conflict
> > > with kasan's in allocation path (though I tested some kernel config
> > > with KASAN enabled)
> > >
> > > Will study more about kasan and reproduce/debug this. thanks
> >
> > Cc kansan mail list.
> >
> > This is really related with KASAN debug, that in free path, some
> > kmalloc redzone ([orig_size+1, object_size]) area is written by
> > kasan to save free meta info.
> >
> > The callstack is:
> >
> > kfree
> > slab_free
> > slab_free_freelist_hook
> > slab_free_hook
> > __kasan_slab_free
> > ____kasan_slab_free
> > kasan_set_free_info
> > kasan_set_track
> >
> > And this issue only happens with "kmalloc-16" slab. Kasan has 2
> > tracks: alloc_track and free_track, for x86_64 test platform, most
> > of the slabs will reserve space for alloc_track, and reuse the
> > 'object' area for free_track. The kasan free_track is 16 bytes
> > large, that it will occupy the whole 'kmalloc-16's object area,
> > so when kmalloc-redzone is enabled by this patch, the 'overwritten'
> > error is triggered.
> >
> > But it won't hurt other kmalloc slabs, as kasan's free meta won't
> > conflict with kmalloc-redzone which stay in the latter part of
> > kmalloc area.
> >
> > So the solution I can think of is:
> > * skip the kmalloc-redzone for kmalloc-16 only, or
> > * skip kmalloc-redzone if kasan is enabled, or
> > * let kasan reserve the free meta (16 bytes) outside of object
> > just like for alloc meta
>
> /\/\/\
>
> Please just not the last option. Memory consumption matters.
>
> I would do whatever is the simplest, e.g. skip the check for
> kmalloc-16 when KASAN is enabled.

Thanks for giving the suggestion. I'm fine with all these options,
and will also wait for Vlastimil and other developers opinion.

> Or does it make sense to prohibit KASAN+SLUB_DEBUG combination? Does
> SLUB_DEBUG add anything on top of KASAN?

I did a quick glance, seems the KASAN will select SLUB_DEBUG in
many cases, as shown in the lib/Kconfig.kasan:

config KASAN_GENERIC
...
select SLUB_DEBUG if SLUB

config KASAN_SW_TAGS
...
select SLUB_DEBUG if SLUB

Thanks,
Feng

>
> > I don't have way to test kasan's SW/HW tag configuration, which
> > is only enabled on arm64 now. And I don't know if there will
> > also be some conflict.
> >
> > Thanks,
> > Feng
> >
>

2022-08-01 14:30:57

by Vlastimil Babka

[permalink] [raw]
Subject: Re: [mm/slub] 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten

On 8/1/22 08:21, Feng Tang wrote:
> On Sun, Jul 31, 2022 at 04:16:53PM +0800, Tang, Feng wrote:
>> Hi Oliver,
>>
>> On Sun, Jul 31, 2022 at 02:53:17PM +0800, Sang, Oliver wrote:
>> >
>> >
>> > Greeting,
>> >
>> > FYI, we noticed the following commit (built with gcc-11):
>> >
>> > commit: 3616799128612e04ed919579e2c7b0dccf6bcb00 ("[PATCH v3 3/3] mm/slub: extend redzone check to cover extra allocated kmalloc space than requested")
>> > url: https://github.com/intel-lab-lkp/linux/commits/Feng-Tang/mm-slub-some-debug-enhancements/20220727-151318
>> > base: git://git.kernel.org/cgit/linux/kernel/git/vbabka/slab.git for-next
>> > patch link: https://lore.kernel.org/linux-mm/[email protected]
>> >
>> > in testcase: boot
>> >
>> > on test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 16G
>> >
>> > caused below changes (please refer to attached dmesg/kmsg for entire log/backtrace):
>> >
>> >
>> > If you fix the issue, kindly add following tag
>> > Reported-by: kernel test robot <[email protected]>
>> >
>> >
>> > [ 50.637839][ T154] =============================================================================
>> > [ 50.639937][ T154] BUG kmalloc-16 (Not tainted): kmalloc Redzone overwritten
>> > [ 50.641291][ T154] -----------------------------------------------------------------------------
>> > [ 50.641291][ T154]
>> > [ 50.643617][ T154] 0xffff88810018464c-0xffff88810018464f @offset=1612. First byte 0x7 instead of 0xcc
>> > [ 50.645311][ T154] Allocated in __sdt_alloc+0x258/0x457 age=14287 cpu=0 pid=1
>> > [ 50.646584][ T154] ___slab_alloc+0x52b/0x5b6
>> > [ 50.647411][ T154] __slab_alloc+0x1a/0x22
>> > [ 50.648374][ T154] __kmalloc_node+0x10c/0x1e1
>> > [ 50.649237][ T154] __sdt_alloc+0x258/0x457
>> > [ 50.650060][ T154] build_sched_domains+0xae/0x10e8
>> > [ 50.650981][ T154] sched_init_smp+0x30/0xa5
>> > [ 50.651805][ T154] kernel_init_freeable+0x1c6/0x23b
>> > [ 50.652767][ T154] kernel_init+0x14/0x127
>> > [ 50.653594][ T154] ret_from_fork+0x1f/0x30
>> > [ 50.654414][ T154] Slab 0xffffea0004006100 objects=28 used=28 fp=0x0000000000000000 flags=0x1fffc0000000201(locked|slab|node=0|zone=1|lastcpupid=0x3fff)
>> > [ 50.656866][ T154] Object 0xffff888100184640 @offset=1600 fp=0xffff888100184520
>> > [ 50.656866][ T154]
>> > [ 50.658410][ T154] Redzone ffff888100184630: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ................
>> > [ 50.660047][ T154] Object ffff888100184640: 00 32 80 00 81 88 ff ff 01 00 00 00 07 00 80 8a .2..............
>> > [ 50.661837][ T154] Redzone ffff888100184650: cc cc cc cc cc cc cc cc ........
>> > [ 50.663454][ T154] Padding ffff8881001846b4: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZZZZZ
>> > [ 50.665225][ T154] CPU: 0 PID: 154 Comm: systemd-udevd Not tainted 5.19.0-rc5-00010-g361679912861 #1
>> > [ 50.666861][ T154] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.0-debian-1.16.0-4 04/01/2014
>> > [ 50.668694][ T154] Call Trace:
>> > [ 50.669331][ T154] <TASK>
>> > [ 50.669832][ T154] dump_stack_lvl+0x57/0x7d
>> > [ 50.670601][ T154] check_bytes_and_report+0xca/0xfe
>> > [ 50.671436][ T154] check_object+0xdc/0x24d
>> > [ 50.672163][ T154] free_debug_processing+0x98/0x210
>> > [ 50.673904][ T154] __slab_free+0x46/0x198
>> > [ 50.675746][ T154] qlist_free_all+0xae/0xde
>> > [ 50.676552][ T154] kasan_quarantine_reduce+0x10d/0x145
>> > [ 50.677507][ T154] __kasan_slab_alloc+0x1c/0x5a
>> > [ 50.678327][ T154] slab_post_alloc_hook+0x5a/0xa2
>> > [ 50.680069][ T154] kmem_cache_alloc+0x102/0x135
>> > [ 50.680938][ T154] getname_flags+0x4b/0x314
>> > [ 50.681781][ T154] do_sys_openat2+0x7a/0x15c
>> > [ 50.706848][ T154] Disabling lock debugging due to kernel taint
>> > [ 50.707913][ T154] FIX kmalloc-16: Restoring kmalloc Redzone 0xffff88810018464c-0xffff88810018464f=0xcc
>>
>> Thanks for the report!
>>
>> From the log it happened when kasan is enabled, and my first guess is
>> the data processing from kmalloc redzone handling had some conflict
>> with kasan's in allocation path (though I tested some kernel config
>> with KASAN enabled)
>>
>> Will study more about kasan and reproduce/debug this. thanks
>
> Cc kansan mail list.
>
> This is really related with KASAN debug, that in free path, some
> kmalloc redzone ([orig_size+1, object_size]) area is written by
> kasan to save free meta info.
>
> The callstack is:
>
> kfree
> slab_free
> slab_free_freelist_hook
> slab_free_hook
> __kasan_slab_free
> ____kasan_slab_free
> kasan_set_free_info
> kasan_set_track
>
> And this issue only happens with "kmalloc-16" slab. Kasan has 2
> tracks: alloc_track and free_track, for x86_64 test platform, most
> of the slabs will reserve space for alloc_track, and reuse the
> 'object' area for free_track. The kasan free_track is 16 bytes
> large, that it will occupy the whole 'kmalloc-16's object area,
> so when kmalloc-redzone is enabled by this patch, the 'overwritten'
> error is triggered.
>
> But it won't hurt other kmalloc slabs, as kasan's free meta won't
> conflict with kmalloc-redzone which stay in the latter part of
> kmalloc area.
>
> So the solution I can think of is:
> * skip the kmalloc-redzone for kmalloc-16 only, or
> * skip kmalloc-redzone if kasan is enabled, or
> * let kasan reserve the free meta (16 bytes) outside of object
> just like for alloc meta

Maybe we could add some hack that if both kasan and SLAB_STORE_USER is
enabled, we bump the stored orig_size from <16 to 16? Similar to what
__ksize() does.

> I don't have way to test kasan's SW/HW tag configuration, which
> is only enabled on arm64 now. And I don't know if there will
> also be some conflict.
>
> Thanks,
> Feng
>


2022-08-02 06:57:39

by Feng Tang

[permalink] [raw]
Subject: Re: [mm/slub] 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten

On Mon, Aug 01, 2022 at 10:23:23PM +0800, Vlastimil Babka wrote:
> On 8/1/22 08:21, Feng Tang wrote:
[snip]
> > Cc kansan mail list.
> >
> > This is really related with KASAN debug, that in free path, some
> > kmalloc redzone ([orig_size+1, object_size]) area is written by
> > kasan to save free meta info.
> >
> > The callstack is:
> >
> > kfree
> > slab_free
> > slab_free_freelist_hook
> > slab_free_hook
> > __kasan_slab_free
> > ____kasan_slab_free
> > kasan_set_free_info
> > kasan_set_track
> >
> > And this issue only happens with "kmalloc-16" slab. Kasan has 2
> > tracks: alloc_track and free_track, for x86_64 test platform, most
> > of the slabs will reserve space for alloc_track, and reuse the
> > 'object' area for free_track. The kasan free_track is 16 bytes
> > large, that it will occupy the whole 'kmalloc-16's object area,
> > so when kmalloc-redzone is enabled by this patch, the 'overwritten'
> > error is triggered.
> >
> > But it won't hurt other kmalloc slabs, as kasan's free meta won't
> > conflict with kmalloc-redzone which stay in the latter part of
> > kmalloc area.
> >
> > So the solution I can think of is:
> > * skip the kmalloc-redzone for kmalloc-16 only, or
> > * skip kmalloc-redzone if kasan is enabled, or
> > * let kasan reserve the free meta (16 bytes) outside of object
> > just like for alloc meta
>
> Maybe we could add some hack that if both kasan and SLAB_STORE_USER is
> enabled, we bump the stored orig_size from <16 to 16? Similar to what
> __ksize() does.

How about the following patch:

---
diff --git a/mm/slub.c b/mm/slub.c
index added2653bb0..33bbac2afaef 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -830,6 +830,16 @@ static inline void set_orig_size(struct kmem_cache *s,
if (!slub_debug_orig_size(s))
return;

+#ifdef CONFIG_KASAN
+ /*
+ * When kasan is enabled, it could save its free meta data in the
+ * start part of object area, so skip the kmalloc redzone check
+ * for small kmalloc slabs to avoid the data conflict.
+ */
+ if (s->object_size <= 32)
+ orig_size = s->object_size;
+#endif
+
p += get_info_end(s);
p += sizeof(struct track) * 2;

I extend the size to 32 for potential's kasan meta data size increase.
This is tested locally, if people are OK with it, I can ask for 0Day's
help to verify this.

Thanks,
Feng

>
> > I don't have way to test kasan's SW/HW tag configuration, which
> > is only enabled on arm64 now. And I don't know if there will
> > also be some conflict.
> >
> > Thanks,
> > Feng
> >
>

2022-08-02 07:14:22

by Dmitry Vyukov

[permalink] [raw]
Subject: Re: [mm/slub] 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten

On Tue, 2 Aug 2022 at 08:55, Feng Tang <[email protected]> wrote:
>
> On Mon, Aug 01, 2022 at 10:23:23PM +0800, Vlastimil Babka wrote:
> > On 8/1/22 08:21, Feng Tang wrote:
> [snip]
> > > Cc kansan mail list.
> > >
> > > This is really related with KASAN debug, that in free path, some
> > > kmalloc redzone ([orig_size+1, object_size]) area is written by
> > > kasan to save free meta info.
> > >
> > > The callstack is:
> > >
> > > kfree
> > > slab_free
> > > slab_free_freelist_hook
> > > slab_free_hook
> > > __kasan_slab_free
> > > ____kasan_slab_free
> > > kasan_set_free_info
> > > kasan_set_track
> > >
> > > And this issue only happens with "kmalloc-16" slab. Kasan has 2
> > > tracks: alloc_track and free_track, for x86_64 test platform, most
> > > of the slabs will reserve space for alloc_track, and reuse the
> > > 'object' area for free_track. The kasan free_track is 16 bytes
> > > large, that it will occupy the whole 'kmalloc-16's object area,
> > > so when kmalloc-redzone is enabled by this patch, the 'overwritten'
> > > error is triggered.
> > >
> > > But it won't hurt other kmalloc slabs, as kasan's free meta won't
> > > conflict with kmalloc-redzone which stay in the latter part of
> > > kmalloc area.
> > >
> > > So the solution I can think of is:
> > > * skip the kmalloc-redzone for kmalloc-16 only, or
> > > * skip kmalloc-redzone if kasan is enabled, or
> > > * let kasan reserve the free meta (16 bytes) outside of object
> > > just like for alloc meta
> >
> > Maybe we could add some hack that if both kasan and SLAB_STORE_USER is
> > enabled, we bump the stored orig_size from <16 to 16? Similar to what
> > __ksize() does.
>
> How about the following patch:
>
> ---
> diff --git a/mm/slub.c b/mm/slub.c
> index added2653bb0..33bbac2afaef 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -830,6 +830,16 @@ static inline void set_orig_size(struct kmem_cache *s,
> if (!slub_debug_orig_size(s))
> return;
>
> +#ifdef CONFIG_KASAN
> + /*
> + * When kasan is enabled, it could save its free meta data in the
> + * start part of object area, so skip the kmalloc redzone check
> + * for small kmalloc slabs to avoid the data conflict.
> + */
> + if (s->object_size <= 32)
> + orig_size = s->object_size;
> +#endif
> +
> p += get_info_end(s);
> p += sizeof(struct track) * 2;
>
> I extend the size to 32 for potential's kasan meta data size increase.
> This is tested locally, if people are OK with it, I can ask for 0Day's
> help to verify this.

Where is set_orig_size() function defined? Don't see it upstream nor
in linux-next.
This looks fine but my only concern is that this should not increase
memory consumption when slub debug tracking is not enabled, which
should be the main operation mode when KASAN is enabled. But I can't
figure this out w/o context.


> Thanks,
> Feng
>
> >
> > > I don't have way to test kasan's SW/HW tag configuration, which
> > > is only enabled on arm64 now. And I don't know if there will
> > > also be some conflict.
> > >
> > > Thanks,
> > > Feng
> > >
> >
>
> --
> You received this message because you are subscribed to the Google Groups "kasan-dev" group.
> To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
> To view this discussion on the web visit https://groups.google.com/d/msgid/kasan-dev/YujKCxu2lJJFm73P%40feng-skl.

2022-08-02 07:32:45

by Dmitry Vyukov

[permalink] [raw]
Subject: Re: [mm/slub] 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten

On Mon, 1 Aug 2022 at 16:23, Vlastimil Babka <[email protected]> wrote:
>
> On 8/1/22 08:21, Feng Tang wrote:
> > On Sun, Jul 31, 2022 at 04:16:53PM +0800, Tang, Feng wrote:
> >> Hi Oliver,
> >>
> >> On Sun, Jul 31, 2022 at 02:53:17PM +0800, Sang, Oliver wrote:
> >> >
> >> >
> >> > Greeting,
> >> >
> >> > FYI, we noticed the following commit (built with gcc-11):
> >> >
> >> > commit: 3616799128612e04ed919579e2c7b0dccf6bcb00 ("[PATCH v3 3/3] mm/slub: extend redzone check to cover extra allocated kmalloc space than requested")
> >> > url: https://github.com/intel-lab-lkp/linux/commits/Feng-Tang/mm-slub-some-debug-enhancements/20220727-151318
> >> > base: git://git.kernel.org/cgit/linux/kernel/git/vbabka/slab.git for-next
> >> > patch link: https://lore.kernel.org/linux-mm/[email protected]
> >> >
> >> > in testcase: boot
> >> >
> >> > on test machine: qemu-system-x86_64 -enable-kvm -cpu SandyBridge -smp 2 -m 16G
> >> >
> >> > caused below changes (please refer to attached dmesg/kmsg for entire log/backtrace):
> >> >
> >> >
> >> > If you fix the issue, kindly add following tag
> >> > Reported-by: kernel test robot <[email protected]>
> >> >
> >> >
> >> > [ 50.637839][ T154] =============================================================================
> >> > [ 50.639937][ T154] BUG kmalloc-16 (Not tainted): kmalloc Redzone overwritten
> >> > [ 50.641291][ T154] -----------------------------------------------------------------------------
> >> > [ 50.641291][ T154]
> >> > [ 50.643617][ T154] 0xffff88810018464c-0xffff88810018464f @offset=1612. First byte 0x7 instead of 0xcc
> >> > [ 50.645311][ T154] Allocated in __sdt_alloc+0x258/0x457 age=14287 cpu=0 pid=1
> >> > [ 50.646584][ T154] ___slab_alloc+0x52b/0x5b6
> >> > [ 50.647411][ T154] __slab_alloc+0x1a/0x22
> >> > [ 50.648374][ T154] __kmalloc_node+0x10c/0x1e1
> >> > [ 50.649237][ T154] __sdt_alloc+0x258/0x457
> >> > [ 50.650060][ T154] build_sched_domains+0xae/0x10e8
> >> > [ 50.650981][ T154] sched_init_smp+0x30/0xa5
> >> > [ 50.651805][ T154] kernel_init_freeable+0x1c6/0x23b
> >> > [ 50.652767][ T154] kernel_init+0x14/0x127
> >> > [ 50.653594][ T154] ret_from_fork+0x1f/0x30
> >> > [ 50.654414][ T154] Slab 0xffffea0004006100 objects=28 used=28 fp=0x0000000000000000 flags=0x1fffc0000000201(locked|slab|node=0|zone=1|lastcpupid=0x3fff)
> >> > [ 50.656866][ T154] Object 0xffff888100184640 @offset=1600 fp=0xffff888100184520
> >> > [ 50.656866][ T154]
> >> > [ 50.658410][ T154] Redzone ffff888100184630: cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc ................
> >> > [ 50.660047][ T154] Object ffff888100184640: 00 32 80 00 81 88 ff ff 01 00 00 00 07 00 80 8a .2..............
> >> > [ 50.661837][ T154] Redzone ffff888100184650: cc cc cc cc cc cc cc cc ........
> >> > [ 50.663454][ T154] Padding ffff8881001846b4: 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a 5a ZZZZZZZZZZZZ
> >> > [ 50.665225][ T154] CPU: 0 PID: 154 Comm: systemd-udevd Not tainted 5.19.0-rc5-00010-g361679912861 #1
> >> > [ 50.666861][ T154] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.0-debian-1.16.0-4 04/01/2014
> >> > [ 50.668694][ T154] Call Trace:
> >> > [ 50.669331][ T154] <TASK>
> >> > [ 50.669832][ T154] dump_stack_lvl+0x57/0x7d
> >> > [ 50.670601][ T154] check_bytes_and_report+0xca/0xfe
> >> > [ 50.671436][ T154] check_object+0xdc/0x24d
> >> > [ 50.672163][ T154] free_debug_processing+0x98/0x210
> >> > [ 50.673904][ T154] __slab_free+0x46/0x198
> >> > [ 50.675746][ T154] qlist_free_all+0xae/0xde
> >> > [ 50.676552][ T154] kasan_quarantine_reduce+0x10d/0x145
> >> > [ 50.677507][ T154] __kasan_slab_alloc+0x1c/0x5a
> >> > [ 50.678327][ T154] slab_post_alloc_hook+0x5a/0xa2
> >> > [ 50.680069][ T154] kmem_cache_alloc+0x102/0x135
> >> > [ 50.680938][ T154] getname_flags+0x4b/0x314
> >> > [ 50.681781][ T154] do_sys_openat2+0x7a/0x15c
> >> > [ 50.706848][ T154] Disabling lock debugging due to kernel taint
> >> > [ 50.707913][ T154] FIX kmalloc-16: Restoring kmalloc Redzone 0xffff88810018464c-0xffff88810018464f=0xcc
> >>
> >> Thanks for the report!
> >>
> >> From the log it happened when kasan is enabled, and my first guess is
> >> the data processing from kmalloc redzone handling had some conflict
> >> with kasan's in allocation path (though I tested some kernel config
> >> with KASAN enabled)
> >>
> >> Will study more about kasan and reproduce/debug this. thanks
> >
> > Cc kansan mail list.
> >
> > This is really related with KASAN debug, that in free path, some
> > kmalloc redzone ([orig_size+1, object_size]) area is written by
> > kasan to save free meta info.
> >
> > The callstack is:
> >
> > kfree
> > slab_free
> > slab_free_freelist_hook
> > slab_free_hook
> > __kasan_slab_free
> > ____kasan_slab_free
> > kasan_set_free_info
> > kasan_set_track
> >
> > And this issue only happens with "kmalloc-16" slab. Kasan has 2
> > tracks: alloc_track and free_track, for x86_64 test platform, most
> > of the slabs will reserve space for alloc_track, and reuse the
> > 'object' area for free_track. The kasan free_track is 16 bytes
> > large, that it will occupy the whole 'kmalloc-16's object area,
> > so when kmalloc-redzone is enabled by this patch, the 'overwritten'
> > error is triggered.
> >
> > But it won't hurt other kmalloc slabs, as kasan's free meta won't
> > conflict with kmalloc-redzone which stay in the latter part of
> > kmalloc area.
> >
> > So the solution I can think of is:
> > * skip the kmalloc-redzone for kmalloc-16 only, or
> > * skip kmalloc-redzone if kasan is enabled, or
> > * let kasan reserve the free meta (16 bytes) outside of object
> > just like for alloc meta
>
> Maybe we could add some hack that if both kasan and SLAB_STORE_USER is
> enabled, we bump the stored orig_size from <16 to 16? Similar to what
> __ksize() does.

This looks like the simplest workaround. And with a proper comment I
think it's fine.


> > I don't have way to test kasan's SW/HW tag configuration, which
> > is only enabled on arm64 now. And I don't know if there will
> > also be some conflict.
> >
> > Thanks,
> > Feng
> >
>

2022-08-02 07:52:15

by Feng Tang

[permalink] [raw]
Subject: Re: [mm/slub] 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten

On Tue, Aug 02, 2022 at 03:06:41PM +0800, Dmitry Vyukov wrote:
> On Tue, 2 Aug 2022 at 08:55, Feng Tang <[email protected]> wrote:
> >
> > On Mon, Aug 01, 2022 at 10:23:23PM +0800, Vlastimil Babka wrote:
> > > On 8/1/22 08:21, Feng Tang wrote:
> > [snip]
> > > > Cc kansan mail list.
> > > >
> > > > This is really related with KASAN debug, that in free path, some
> > > > kmalloc redzone ([orig_size+1, object_size]) area is written by
> > > > kasan to save free meta info.
> > > >
> > > > The callstack is:
> > > >
> > > > kfree
> > > > slab_free
> > > > slab_free_freelist_hook
> > > > slab_free_hook
> > > > __kasan_slab_free
> > > > ____kasan_slab_free
> > > > kasan_set_free_info
> > > > kasan_set_track
> > > >
> > > > And this issue only happens with "kmalloc-16" slab. Kasan has 2
> > > > tracks: alloc_track and free_track, for x86_64 test platform, most
> > > > of the slabs will reserve space for alloc_track, and reuse the
> > > > 'object' area for free_track. The kasan free_track is 16 bytes
> > > > large, that it will occupy the whole 'kmalloc-16's object area,
> > > > so when kmalloc-redzone is enabled by this patch, the 'overwritten'
> > > > error is triggered.
> > > >
> > > > But it won't hurt other kmalloc slabs, as kasan's free meta won't
> > > > conflict with kmalloc-redzone which stay in the latter part of
> > > > kmalloc area.
> > > >
> > > > So the solution I can think of is:
> > > > * skip the kmalloc-redzone for kmalloc-16 only, or
> > > > * skip kmalloc-redzone if kasan is enabled, or
> > > > * let kasan reserve the free meta (16 bytes) outside of object
> > > > just like for alloc meta
> > >
> > > Maybe we could add some hack that if both kasan and SLAB_STORE_USER is
> > > enabled, we bump the stored orig_size from <16 to 16? Similar to what
> > > __ksize() does.
> >
> > How about the following patch:
> >
> > ---
> > diff --git a/mm/slub.c b/mm/slub.c
> > index added2653bb0..33bbac2afaef 100644
> > --- a/mm/slub.c
> > +++ b/mm/slub.c
> > @@ -830,6 +830,16 @@ static inline void set_orig_size(struct kmem_cache *s,
> > if (!slub_debug_orig_size(s))
> > return;
> >
> > +#ifdef CONFIG_KASAN
> > + /*
> > + * When kasan is enabled, it could save its free meta data in the
> > + * start part of object area, so skip the kmalloc redzone check
> > + * for small kmalloc slabs to avoid the data conflict.
> > + */
> > + if (s->object_size <= 32)
> > + orig_size = s->object_size;
> > +#endif
> > +
> > p += get_info_end(s);
> > p += sizeof(struct track) * 2;
> >
> > I extend the size to 32 for potential's kasan meta data size increase.
> > This is tested locally, if people are OK with it, I can ask for 0Day's
> > help to verify this.
>
> Where is set_orig_size() function defined? Don't see it upstream nor
> in linux-next.
> This looks fine but my only concern is that this should not increase
> memory consumption when slub debug tracking is not enabled, which
> should be the main operation mode when KASAN is enabled. But I can't
> figure this out w/o context.

Yes, the patchset was only posted on LKML, and not in any tree now.
The link to the original patches is:

https://lore.kernel.org/lkml/[email protected]/t/

Thanks,
Feng



2022-08-02 08:02:13

by Dmitry Vyukov

[permalink] [raw]
Subject: Re: [mm/slub] 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten

On Tue, 2 Aug 2022 at 09:47, Feng Tang <[email protected]> wrote:
> > > On Mon, Aug 01, 2022 at 10:23:23PM +0800, Vlastimil Babka wrote:
> > > > On 8/1/22 08:21, Feng Tang wrote:
> > > [snip]
> > > > > Cc kansan mail list.
> > > > >
> > > > > This is really related with KASAN debug, that in free path, some
> > > > > kmalloc redzone ([orig_size+1, object_size]) area is written by
> > > > > kasan to save free meta info.
> > > > >
> > > > > The callstack is:
> > > > >
> > > > > kfree
> > > > > slab_free
> > > > > slab_free_freelist_hook
> > > > > slab_free_hook
> > > > > __kasan_slab_free
> > > > > ____kasan_slab_free
> > > > > kasan_set_free_info
> > > > > kasan_set_track
> > > > >
> > > > > And this issue only happens with "kmalloc-16" slab. Kasan has 2
> > > > > tracks: alloc_track and free_track, for x86_64 test platform, most
> > > > > of the slabs will reserve space for alloc_track, and reuse the
> > > > > 'object' area for free_track. The kasan free_track is 16 bytes
> > > > > large, that it will occupy the whole 'kmalloc-16's object area,
> > > > > so when kmalloc-redzone is enabled by this patch, the 'overwritten'
> > > > > error is triggered.
> > > > >
> > > > > But it won't hurt other kmalloc slabs, as kasan's free meta won't
> > > > > conflict with kmalloc-redzone which stay in the latter part of
> > > > > kmalloc area.
> > > > >
> > > > > So the solution I can think of is:
> > > > > * skip the kmalloc-redzone for kmalloc-16 only, or
> > > > > * skip kmalloc-redzone if kasan is enabled, or
> > > > > * let kasan reserve the free meta (16 bytes) outside of object
> > > > > just like for alloc meta
> > > >
> > > > Maybe we could add some hack that if both kasan and SLAB_STORE_USER is
> > > > enabled, we bump the stored orig_size from <16 to 16? Similar to what
> > > > __ksize() does.
> > >
> > > How about the following patch:
> > >
> > > ---
> > > diff --git a/mm/slub.c b/mm/slub.c
> > > index added2653bb0..33bbac2afaef 100644
> > > --- a/mm/slub.c
> > > +++ b/mm/slub.c
> > > @@ -830,6 +830,16 @@ static inline void set_orig_size(struct kmem_cache *s,
> > > if (!slub_debug_orig_size(s))
> > > return;
> > >
> > > +#ifdef CONFIG_KASAN
> > > + /*
> > > + * When kasan is enabled, it could save its free meta data in the
> > > + * start part of object area, so skip the kmalloc redzone check
> > > + * for small kmalloc slabs to avoid the data conflict.
> > > + */
> > > + if (s->object_size <= 32)
> > > + orig_size = s->object_size;
> > > +#endif

I think this can be done only when CONFIG_KASAN_GENERIC.
Only CONFIG_KASAN_GENERIC stores free meta info in objects:
https://elixir.bootlin.com/linux/latest/source/mm/kasan/common.c#L176

And KASAN_HW_TAGS has chances of being enabled with DEBUG_SLUB in
real-world uses (with Arm MTE).


> > > +
> > > p += get_info_end(s);
> > > p += sizeof(struct track) * 2;
> > >
> > > I extend the size to 32 for potential's kasan meta data size increase.
> > > This is tested locally, if people are OK with it, I can ask for 0Day's
> > > help to verify this.
> >
> > Where is set_orig_size() function defined? Don't see it upstream nor
> > in linux-next.
> > This looks fine but my only concern is that this should not increase
> > memory consumption when slub debug tracking is not enabled, which
> > should be the main operation mode when KASAN is enabled. But I can't
> > figure this out w/o context.
>
> Yes, the patchset was only posted on LKML, and not in any tree now.
> The link to the original patches is:
>
> https://lore.kernel.org/lkml/[email protected]/t/

Lots of code...

This SLAB_STORE_USER seems to be set on all kmalloc slabs by default
when CONFIG_SLUB_DEBUG is enabled, right?
And KASAN enables CONFIG_SLUB_DEBUG, this means that this is stored
always when KASAN is enabled? Looks wrong.

2022-08-02 09:12:15

by Feng Tang

[permalink] [raw]
Subject: Re: [mm/slub] 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten

On Tue, Aug 02, 2022 at 03:59:00PM +0800, Dmitry Vyukov wrote:
> On Tue, 2 Aug 2022 at 09:47, Feng Tang <[email protected]> wrote:
> > > > On Mon, Aug 01, 2022 at 10:23:23PM +0800, Vlastimil Babka wrote:
> > > > > On 8/1/22 08:21, Feng Tang wrote:
> > > > [snip]
> > > > > > Cc kansan mail list.
> > > > > >
> > > > > > This is really related with KASAN debug, that in free path, some
> > > > > > kmalloc redzone ([orig_size+1, object_size]) area is written by
> > > > > > kasan to save free meta info.
> > > > > >
> > > > > > The callstack is:
> > > > > >
> > > > > > kfree
> > > > > > slab_free
> > > > > > slab_free_freelist_hook
> > > > > > slab_free_hook
> > > > > > __kasan_slab_free
> > > > > > ____kasan_slab_free
> > > > > > kasan_set_free_info
> > > > > > kasan_set_track
> > > > > >
> > > > > > And this issue only happens with "kmalloc-16" slab. Kasan has 2
> > > > > > tracks: alloc_track and free_track, for x86_64 test platform, most
> > > > > > of the slabs will reserve space for alloc_track, and reuse the
> > > > > > 'object' area for free_track. The kasan free_track is 16 bytes
> > > > > > large, that it will occupy the whole 'kmalloc-16's object area,
> > > > > > so when kmalloc-redzone is enabled by this patch, the 'overwritten'
> > > > > > error is triggered.
> > > > > >
> > > > > > But it won't hurt other kmalloc slabs, as kasan's free meta won't
> > > > > > conflict with kmalloc-redzone which stay in the latter part of
> > > > > > kmalloc area.
> > > > > >
> > > > > > So the solution I can think of is:
> > > > > > * skip the kmalloc-redzone for kmalloc-16 only, or
> > > > > > * skip kmalloc-redzone if kasan is enabled, or
> > > > > > * let kasan reserve the free meta (16 bytes) outside of object
> > > > > > just like for alloc meta
> > > > >
> > > > > Maybe we could add some hack that if both kasan and SLAB_STORE_USER is
> > > > > enabled, we bump the stored orig_size from <16 to 16? Similar to what
> > > > > __ksize() does.
> > > >
> > > > How about the following patch:
> > > >
> > > > ---
> > > > diff --git a/mm/slub.c b/mm/slub.c
> > > > index added2653bb0..33bbac2afaef 100644
> > > > --- a/mm/slub.c
> > > > +++ b/mm/slub.c
> > > > @@ -830,6 +830,16 @@ static inline void set_orig_size(struct kmem_cache *s,
> > > > if (!slub_debug_orig_size(s))
> > > > return;
> > > >
> > > > +#ifdef CONFIG_KASAN
> > > > + /*
> > > > + * When kasan is enabled, it could save its free meta data in the
> > > > + * start part of object area, so skip the kmalloc redzone check
> > > > + * for small kmalloc slabs to avoid the data conflict.
> > > > + */
> > > > + if (s->object_size <= 32)
> > > > + orig_size = s->object_size;
> > > > +#endif
>
> I think this can be done only when CONFIG_KASAN_GENERIC.
> Only CONFIG_KASAN_GENERIC stores free meta info in objects:
> https://elixir.bootlin.com/linux/latest/source/mm/kasan/common.c#L176

Thanks for the catch! will change.

> And KASAN_HW_TAGS has chances of being enabled with DEBUG_SLUB in
> real-world uses (with Arm MTE).

I only have device to test the kasan-generic mode, and not SW/HW tag.
But if there is conflict, we may have to apply the similar solution :)

>
> > > > +
> > > > p += get_info_end(s);
> > > > p += sizeof(struct track) * 2;
> > > >
> > > > I extend the size to 32 for potential's kasan meta data size increase.
> > > > This is tested locally, if people are OK with it, I can ask for 0Day's
> > > > help to verify this.
> > >
> > > Where is set_orig_size() function defined? Don't see it upstream nor
> > > in linux-next.
> > > This looks fine but my only concern is that this should not increase
> > > memory consumption when slub debug tracking is not enabled, which
> > > should be the main operation mode when KASAN is enabled. But I can't
> > > figure this out w/o context.
> >
> > Yes, the patchset was only posted on LKML, and not in any tree now.
> > The link to the original patches is:
> >
> > https://lore.kernel.org/lkml/[email protected]/t/
>
> Lots of code...
>
> This SLAB_STORE_USER seems to be set on all kmalloc slabs by default
> when CONFIG_SLUB_DEBUG is enabled, right?

Christoph has explained in one earlier mail that CONFIG_SLUB_DEBUG only
compile in the debug support but not activate it. Option CONFIG_SLUB_DEBUG_ON
will enable it, and each slub debug flag bits can also be enabled
by changing kernel cmdline for some or all slabs.

> And KASAN enables CONFIG_SLUB_DEBUG, this means that this is stored
> always when KASAN is enabled? Looks wrong.

Thanks,
Feng

2022-08-02 10:16:19

by Vlastimil Babka

[permalink] [raw]
Subject: Re: [mm/slub] 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten

On 8/2/22 09:06, Dmitry Vyukov wrote:
> On Tue, 2 Aug 2022 at 08:55, Feng Tang <[email protected]> wrote:
>>
>> On Mon, Aug 01, 2022 at 10:23:23PM +0800, Vlastimil Babka wrote:
>> > On 8/1/22 08:21, Feng Tang wrote:
>> [snip]
>> > > Cc kansan mail list.
>> > >
>> > > This is really related with KASAN debug, that in free path, some
>> > > kmalloc redzone ([orig_size+1, object_size]) area is written by
>> > > kasan to save free meta info.
>> > >
>> > > The callstack is:
>> > >
>> > > kfree
>> > > slab_free
>> > > slab_free_freelist_hook
>> > > slab_free_hook
>> > > __kasan_slab_free
>> > > ____kasan_slab_free
>> > > kasan_set_free_info
>> > > kasan_set_track
>> > >
>> > > And this issue only happens with "kmalloc-16" slab. Kasan has 2
>> > > tracks: alloc_track and free_track, for x86_64 test platform, most
>> > > of the slabs will reserve space for alloc_track, and reuse the
>> > > 'object' area for free_track. The kasan free_track is 16 bytes
>> > > large, that it will occupy the whole 'kmalloc-16's object area,
>> > > so when kmalloc-redzone is enabled by this patch, the 'overwritten'
>> > > error is triggered.
>> > >
>> > > But it won't hurt other kmalloc slabs, as kasan's free meta won't
>> > > conflict with kmalloc-redzone which stay in the latter part of
>> > > kmalloc area.
>> > >
>> > > So the solution I can think of is:
>> > > * skip the kmalloc-redzone for kmalloc-16 only, or
>> > > * skip kmalloc-redzone if kasan is enabled, or
>> > > * let kasan reserve the free meta (16 bytes) outside of object
>> > > just like for alloc meta
>> >
>> > Maybe we could add some hack that if both kasan and SLAB_STORE_USER is
>> > enabled, we bump the stored orig_size from <16 to 16? Similar to what
>> > __ksize() does.
>>
>> How about the following patch:
>>
>> ---
>> diff --git a/mm/slub.c b/mm/slub.c
>> index added2653bb0..33bbac2afaef 100644
>> --- a/mm/slub.c
>> +++ b/mm/slub.c
>> @@ -830,6 +830,16 @@ static inline void set_orig_size(struct kmem_cache *s,
>> if (!slub_debug_orig_size(s))
>> return;
>>
>> +#ifdef CONFIG_KASAN
>> + /*
>> + * When kasan is enabled, it could save its free meta data in the
>> + * start part of object area, so skip the kmalloc redzone check
>> + * for small kmalloc slabs to avoid the data conflict.
>> + */
>> + if (s->object_size <= 32)
>> + orig_size = s->object_size;
>> +#endif
>> +
>> p += get_info_end(s);
>> p += sizeof(struct track) * 2;
>>
>> I extend the size to 32 for potential's kasan meta data size increase.
>> This is tested locally, if people are OK with it, I can ask for 0Day's
>> help to verify this.

Is there maybe some KASAN macro we can use instead of hardcoding 32?

>
> Where is set_orig_size() function defined? Don't see it upstream nor
> in linux-next.
> This looks fine but my only concern is that this should not increase
> memory consumption when slub debug tracking is not enabled, which
> should be the main operation mode when KASAN is enabled. But I can't
> figure this out w/o context.

It won't increase memory consumption even if slub_debug tracking is enabled.
It just fakes a bit the size that was passed to kmalloc() and which we newly
store (thanks to Feng's patches) for statistics and debugging purposes.

>> Thanks,
>> Feng
>>
>> >
>> > > I don't have way to test kasan's SW/HW tag configuration, which
>> > > is only enabled on arm64 now. And I don't know if there will
>> > > also be some conflict.
>> > >
>> > > Thanks,
>> > > Feng
>> > >
>> >
>>
>> --
>> You received this message because you are subscribed to the Google Groups "kasan-dev" group.
>> To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
>> To view this discussion on the web visit https://groups.google.com/d/msgid/kasan-dev/YujKCxu2lJJFm73P%40feng-skl.


2022-08-02 10:42:48

by Dmitry Vyukov

[permalink] [raw]
Subject: Re: [mm/slub] 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten

.On Tue, 2 Aug 2022 at 11:43, Vlastimil Babka <[email protected]> wrote:
>
> On 8/2/22 09:06, Dmitry Vyukov wrote:
> > On Tue, 2 Aug 2022 at 08:55, Feng Tang <[email protected]> wrote:
> >>
> >> On Mon, Aug 01, 2022 at 10:23:23PM +0800, Vlastimil Babka wrote:
> >> > On 8/1/22 08:21, Feng Tang wrote:
> >> [snip]
> >> > > Cc kansan mail list.
> >> > >
> >> > > This is really related with KASAN debug, that in free path, some
> >> > > kmalloc redzone ([orig_size+1, object_size]) area is written by
> >> > > kasan to save free meta info.
> >> > >
> >> > > The callstack is:
> >> > >
> >> > > kfree
> >> > > slab_free
> >> > > slab_free_freelist_hook
> >> > > slab_free_hook
> >> > > __kasan_slab_free
> >> > > ____kasan_slab_free
> >> > > kasan_set_free_info
> >> > > kasan_set_track
> >> > >
> >> > > And this issue only happens with "kmalloc-16" slab. Kasan has 2
> >> > > tracks: alloc_track and free_track, for x86_64 test platform, most
> >> > > of the slabs will reserve space for alloc_track, and reuse the
> >> > > 'object' area for free_track. The kasan free_track is 16 bytes
> >> > > large, that it will occupy the whole 'kmalloc-16's object area,
> >> > > so when kmalloc-redzone is enabled by this patch, the 'overwritten'
> >> > > error is triggered.
> >> > >
> >> > > But it won't hurt other kmalloc slabs, as kasan's free meta won't
> >> > > conflict with kmalloc-redzone which stay in the latter part of
> >> > > kmalloc area.
> >> > >
> >> > > So the solution I can think of is:
> >> > > * skip the kmalloc-redzone for kmalloc-16 only, or
> >> > > * skip kmalloc-redzone if kasan is enabled, or
> >> > > * let kasan reserve the free meta (16 bytes) outside of object
> >> > > just like for alloc meta
> >> >
> >> > Maybe we could add some hack that if both kasan and SLAB_STORE_USER is
> >> > enabled, we bump the stored orig_size from <16 to 16? Similar to what
> >> > __ksize() does.
> >>
> >> How about the following patch:
> >>
> >> ---
> >> diff --git a/mm/slub.c b/mm/slub.c
> >> index added2653bb0..33bbac2afaef 100644
> >> --- a/mm/slub.c
> >> +++ b/mm/slub.c
> >> @@ -830,6 +830,16 @@ static inline void set_orig_size(struct kmem_cache *s,
> >> if (!slub_debug_orig_size(s))
> >> return;
> >>
> >> +#ifdef CONFIG_KASAN
> >> + /*
> >> + * When kasan is enabled, it could save its free meta data in the
> >> + * start part of object area, so skip the kmalloc redzone check
> >> + * for small kmalloc slabs to avoid the data conflict.
> >> + */
> >> + if (s->object_size <= 32)
> >> + orig_size = s->object_size;
> >> +#endif
> >> +
> >> p += get_info_end(s);
> >> p += sizeof(struct track) * 2;
> >>
> >> I extend the size to 32 for potential's kasan meta data size increase.
> >> This is tested locally, if people are OK with it, I can ask for 0Day's
> >> help to verify this.
>
> Is there maybe some KASAN macro we can use instead of hardcoding 32?

kasan_free_meta is placed in the object data after freeing, so it can
be sizeof(kasan_free_meta)


> > Where is set_orig_size() function defined? Don't see it upstream nor
> > in linux-next.
> > This looks fine but my only concern is that this should not increase
> > memory consumption when slub debug tracking is not enabled, which
> > should be the main operation mode when KASAN is enabled. But I can't
> > figure this out w/o context.
>
> It won't increase memory consumption even if slub_debug tracking is enabled.
> It just fakes a bit the size that was passed to kmalloc() and which we newly
> store (thanks to Feng's patches) for statistics and debugging purposes.
>
> >> Thanks,
> >> Feng
> >>
> >> >
> >> > > I don't have way to test kasan's SW/HW tag configuration, which
> >> > > is only enabled on arm64 now. And I don't know if there will
> >> > > also be some conflict.
> >> > >
> >> > > Thanks,
> >> > > Feng
> >> > >
> >> >
> >>
> >> --
> >> You received this message because you are subscribed to the Google Groups "kasan-dev" group.
> >> To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
> >> To view this discussion on the web visit https://groups.google.com/d/msgid/kasan-dev/YujKCxu2lJJFm73P%40feng-skl.
>

2022-08-02 10:56:25

by Dmitry Vyukov

[permalink] [raw]
Subject: Re: [mm/slub] 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten

On Tue, 2 Aug 2022 at 11:43, Vlastimil Babka <[email protected]> wrote:
>
> On 8/2/22 09:06, Dmitry Vyukov wrote:
> > On Tue, 2 Aug 2022 at 08:55, Feng Tang <[email protected]> wrote:
> >>
> >> On Mon, Aug 01, 2022 at 10:23:23PM +0800, Vlastimil Babka wrote:
> >> > On 8/1/22 08:21, Feng Tang wrote:
> >> [snip]
> >> > > Cc kansan mail list.
> >> > >
> >> > > This is really related with KASAN debug, that in free path, some
> >> > > kmalloc redzone ([orig_size+1, object_size]) area is written by
> >> > > kasan to save free meta info.
> >> > >
> >> > > The callstack is:
> >> > >
> >> > > kfree
> >> > > slab_free
> >> > > slab_free_freelist_hook
> >> > > slab_free_hook
> >> > > __kasan_slab_free
> >> > > ____kasan_slab_free
> >> > > kasan_set_free_info
> >> > > kasan_set_track
> >> > >
> >> > > And this issue only happens with "kmalloc-16" slab. Kasan has 2
> >> > > tracks: alloc_track and free_track, for x86_64 test platform, most
> >> > > of the slabs will reserve space for alloc_track, and reuse the
> >> > > 'object' area for free_track. The kasan free_track is 16 bytes
> >> > > large, that it will occupy the whole 'kmalloc-16's object area,
> >> > > so when kmalloc-redzone is enabled by this patch, the 'overwritten'
> >> > > error is triggered.
> >> > >
> >> > > But it won't hurt other kmalloc slabs, as kasan's free meta won't
> >> > > conflict with kmalloc-redzone which stay in the latter part of
> >> > > kmalloc area.
> >> > >
> >> > > So the solution I can think of is:
> >> > > * skip the kmalloc-redzone for kmalloc-16 only, or
> >> > > * skip kmalloc-redzone if kasan is enabled, or
> >> > > * let kasan reserve the free meta (16 bytes) outside of object
> >> > > just like for alloc meta
> >> >
> >> > Maybe we could add some hack that if both kasan and SLAB_STORE_USER is
> >> > enabled, we bump the stored orig_size from <16 to 16? Similar to what
> >> > __ksize() does.
> >>
> >> How about the following patch:
> >>
> >> ---
> >> diff --git a/mm/slub.c b/mm/slub.c
> >> index added2653bb0..33bbac2afaef 100644
> >> --- a/mm/slub.c
> >> +++ b/mm/slub.c
> >> @@ -830,6 +830,16 @@ static inline void set_orig_size(struct kmem_cache *s,
> >> if (!slub_debug_orig_size(s))
> >> return;
> >>
> >> +#ifdef CONFIG_KASAN
> >> + /*
> >> + * When kasan is enabled, it could save its free meta data in the
> >> + * start part of object area, so skip the kmalloc redzone check
> >> + * for small kmalloc slabs to avoid the data conflict.
> >> + */
> >> + if (s->object_size <= 32)
> >> + orig_size = s->object_size;
> >> +#endif
> >> +
> >> p += get_info_end(s);
> >> p += sizeof(struct track) * 2;
> >>
> >> I extend the size to 32 for potential's kasan meta data size increase.
> >> This is tested locally, if people are OK with it, I can ask for 0Day's
> >> help to verify this.
>
> Is there maybe some KASAN macro we can use instead of hardcoding 32?
>
> >
> > Where is set_orig_size() function defined? Don't see it upstream nor
> > in linux-next.
> > This looks fine but my only concern is that this should not increase
> > memory consumption when slub debug tracking is not enabled, which
> > should be the main operation mode when KASAN is enabled. But I can't
> > figure this out w/o context.
>
> It won't increase memory consumption even if slub_debug tracking is enabled.
> It just fakes a bit the size that was passed to kmalloc() and which we newly
> store (thanks to Feng's patches) for statistics and debugging purposes.

Then it looks good to me. Thanks for double checking.


> >> Thanks,
> >> Feng
> >>
> >> >
> >> > > I don't have way to test kasan's SW/HW tag configuration, which
> >> > > is only enabled on arm64 now. And I don't know if there will
> >> > > also be some conflict.
> >> > >
> >> > > Thanks,
> >> > > Feng
> >> > >
> >> >
> >>
> >> --
> >> You received this message because you are subscribed to the Google Groups "kasan-dev" group.
> >> To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].
> >> To view this discussion on the web visit https://groups.google.com/d/msgid/kasan-dev/YujKCxu2lJJFm73P%40feng-skl.
>

2022-08-02 13:39:07

by Feng Tang

[permalink] [raw]
Subject: Re: [mm/slub] 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten

On Tue, Aug 02, 2022 at 06:30:44PM +0800, Dmitry Vyukov wrote:
> .On Tue, 2 Aug 2022 at 11:43, Vlastimil Babka <[email protected]> wrote:
> >
> > On 8/2/22 09:06, Dmitry Vyukov wrote:
> > > On Tue, 2 Aug 2022 at 08:55, Feng Tang <[email protected]> wrote:
> > >>
> > >> On Mon, Aug 01, 2022 at 10:23:23PM +0800, Vlastimil Babka wrote:
> > >> > On 8/1/22 08:21, Feng Tang wrote:
> > >> [snip]
> > >> > > Cc kansan mail list.
> > >> > >
> > >> > > This is really related with KASAN debug, that in free path, some
> > >> > > kmalloc redzone ([orig_size+1, object_size]) area is written by
> > >> > > kasan to save free meta info.
> > >> > >
> > >> > > The callstack is:
> > >> > >
> > >> > > kfree
> > >> > > slab_free
> > >> > > slab_free_freelist_hook
> > >> > > slab_free_hook
> > >> > > __kasan_slab_free
> > >> > > ____kasan_slab_free
> > >> > > kasan_set_free_info
> > >> > > kasan_set_track
> > >> > >
> > >> > > And this issue only happens with "kmalloc-16" slab. Kasan has 2
> > >> > > tracks: alloc_track and free_track, for x86_64 test platform, most
> > >> > > of the slabs will reserve space for alloc_track, and reuse the
> > >> > > 'object' area for free_track. The kasan free_track is 16 bytes
> > >> > > large, that it will occupy the whole 'kmalloc-16's object area,
> > >> > > so when kmalloc-redzone is enabled by this patch, the 'overwritten'
> > >> > > error is triggered.
> > >> > >
> > >> > > But it won't hurt other kmalloc slabs, as kasan's free meta won't
> > >> > > conflict with kmalloc-redzone which stay in the latter part of
> > >> > > kmalloc area.
> > >> > >
> > >> > > So the solution I can think of is:
> > >> > > * skip the kmalloc-redzone for kmalloc-16 only, or
> > >> > > * skip kmalloc-redzone if kasan is enabled, or
> > >> > > * let kasan reserve the free meta (16 bytes) outside of object
> > >> > > just like for alloc meta
> > >> >
> > >> > Maybe we could add some hack that if both kasan and SLAB_STORE_USER is
> > >> > enabled, we bump the stored orig_size from <16 to 16? Similar to what
> > >> > __ksize() does.
> > >>
> > >> How about the following patch:
> > >>
> > >> ---
> > >> diff --git a/mm/slub.c b/mm/slub.c
> > >> index added2653bb0..33bbac2afaef 100644
> > >> --- a/mm/slub.c
> > >> +++ b/mm/slub.c
> > >> @@ -830,6 +830,16 @@ static inline void set_orig_size(struct kmem_cache *s,
> > >> if (!slub_debug_orig_size(s))
> > >> return;
> > >>
> > >> +#ifdef CONFIG_KASAN
> > >> + /*
> > >> + * When kasan is enabled, it could save its free meta data in the
> > >> + * start part of object area, so skip the kmalloc redzone check
> > >> + * for small kmalloc slabs to avoid the data conflict.
> > >> + */
> > >> + if (s->object_size <= 32)
> > >> + orig_size = s->object_size;
> > >> +#endif
> > >> +
> > >> p += get_info_end(s);
> > >> p += sizeof(struct track) * 2;
> > >>
> > >> I extend the size to 32 for potential's kasan meta data size increase.
> > >> This is tested locally, if people are OK with it, I can ask for 0Day's
> > >> help to verify this.
> >
> > Is there maybe some KASAN macro we can use instead of hardcoding 32?
>
> kasan_free_meta is placed in the object data after freeing, so it can
> be sizeof(kasan_free_meta)

'kasan_free_meta' is defined in mm/kasan/kasan.h, to use it we need to
include "../kasan/kasan.h" in slub.c, or move its definition to
"include/linux/kasan.h"

Another idea is to save the info in kasan_info, like:

---
diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index b092277bf48d..97e899948d0b 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -100,6 +100,7 @@ static inline bool kasan_has_integrated_init(void)
struct kasan_cache {
int alloc_meta_offset;
int free_meta_offset;
+ int free_meta_size;
bool is_kmalloc;
};

diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index c40c0e7b3b5f..7bd82c5ec264 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -178,6 +178,8 @@ void __kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
return;
}

+ cache->kasan_info.free_meta_size = sizeof(struct free_meta_offset);
+
/*
* Add free meta into redzone when it's not possible to store
* it in the object. This is the case when:

Thanks,
Feng

2022-08-02 14:49:29

by Dmitry Vyukov

[permalink] [raw]
Subject: Re: [mm/slub] 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten

On Tue, 2 Aug 2022 at 15:37, Feng Tang <[email protected]> wrote:
>
> On Tue, Aug 02, 2022 at 06:30:44PM +0800, Dmitry Vyukov wrote:
> > .On Tue, 2 Aug 2022 at 11:43, Vlastimil Babka <[email protected]> wrote:
> > >
> > > On 8/2/22 09:06, Dmitry Vyukov wrote:
> > > > On Tue, 2 Aug 2022 at 08:55, Feng Tang <[email protected]> wrote:
> > > >>
> > > >> On Mon, Aug 01, 2022 at 10:23:23PM +0800, Vlastimil Babka wrote:
> > > >> > On 8/1/22 08:21, Feng Tang wrote:
> > > >> [snip]
> > > >> > > Cc kansan mail list.
> > > >> > >
> > > >> > > This is really related with KASAN debug, that in free path, some
> > > >> > > kmalloc redzone ([orig_size+1, object_size]) area is written by
> > > >> > > kasan to save free meta info.
> > > >> > >
> > > >> > > The callstack is:
> > > >> > >
> > > >> > > kfree
> > > >> > > slab_free
> > > >> > > slab_free_freelist_hook
> > > >> > > slab_free_hook
> > > >> > > __kasan_slab_free
> > > >> > > ____kasan_slab_free
> > > >> > > kasan_set_free_info
> > > >> > > kasan_set_track
> > > >> > >
> > > >> > > And this issue only happens with "kmalloc-16" slab. Kasan has 2
> > > >> > > tracks: alloc_track and free_track, for x86_64 test platform, most
> > > >> > > of the slabs will reserve space for alloc_track, and reuse the
> > > >> > > 'object' area for free_track. The kasan free_track is 16 bytes
> > > >> > > large, that it will occupy the whole 'kmalloc-16's object area,
> > > >> > > so when kmalloc-redzone is enabled by this patch, the 'overwritten'
> > > >> > > error is triggered.
> > > >> > >
> > > >> > > But it won't hurt other kmalloc slabs, as kasan's free meta won't
> > > >> > > conflict with kmalloc-redzone which stay in the latter part of
> > > >> > > kmalloc area.
> > > >> > >
> > > >> > > So the solution I can think of is:
> > > >> > > * skip the kmalloc-redzone for kmalloc-16 only, or
> > > >> > > * skip kmalloc-redzone if kasan is enabled, or
> > > >> > > * let kasan reserve the free meta (16 bytes) outside of object
> > > >> > > just like for alloc meta
> > > >> >
> > > >> > Maybe we could add some hack that if both kasan and SLAB_STORE_USER is
> > > >> > enabled, we bump the stored orig_size from <16 to 16? Similar to what
> > > >> > __ksize() does.
> > > >>
> > > >> How about the following patch:
> > > >>
> > > >> ---
> > > >> diff --git a/mm/slub.c b/mm/slub.c
> > > >> index added2653bb0..33bbac2afaef 100644
> > > >> --- a/mm/slub.c
> > > >> +++ b/mm/slub.c
> > > >> @@ -830,6 +830,16 @@ static inline void set_orig_size(struct kmem_cache *s,
> > > >> if (!slub_debug_orig_size(s))
> > > >> return;
> > > >>
> > > >> +#ifdef CONFIG_KASAN
> > > >> + /*
> > > >> + * When kasan is enabled, it could save its free meta data in the
> > > >> + * start part of object area, so skip the kmalloc redzone check
> > > >> + * for small kmalloc slabs to avoid the data conflict.
> > > >> + */
> > > >> + if (s->object_size <= 32)
> > > >> + orig_size = s->object_size;
> > > >> +#endif
> > > >> +
> > > >> p += get_info_end(s);
> > > >> p += sizeof(struct track) * 2;
> > > >>
> > > >> I extend the size to 32 for potential's kasan meta data size increase.
> > > >> This is tested locally, if people are OK with it, I can ask for 0Day's
> > > >> help to verify this.
> > >
> > > Is there maybe some KASAN macro we can use instead of hardcoding 32?
> >
> > kasan_free_meta is placed in the object data after freeing, so it can
> > be sizeof(kasan_free_meta)
>
> 'kasan_free_meta' is defined in mm/kasan/kasan.h, to use it we need to
> include "../kasan/kasan.h" in slub.c, or move its definition to
> "include/linux/kasan.h"
>
> Another idea is to save the info in kasan_info, like:
>
> ---
> diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> index b092277bf48d..97e899948d0b 100644
> --- a/include/linux/kasan.h
> +++ b/include/linux/kasan.h
> @@ -100,6 +100,7 @@ static inline bool kasan_has_integrated_init(void)
> struct kasan_cache {
> int alloc_meta_offset;
> int free_meta_offset;
> + int free_meta_size;

Storing it here looks fine to me.
But I would name it based on the meaning for external users (i.e. that
many bytes are occupied by kasan in freed objects). For some caches
KASAN does not store anything in freed objects at all.



> bool is_kmalloc;
> };
>
> diff --git a/mm/kasan/common.c b/mm/kasan/common.c
> index c40c0e7b3b5f..7bd82c5ec264 100644
> --- a/mm/kasan/common.c
> +++ b/mm/kasan/common.c
> @@ -178,6 +178,8 @@ void __kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
> return;
> }
>
> + cache->kasan_info.free_meta_size = sizeof(struct free_meta_offset);
> +
> /*
> * Add free meta into redzone when it's not possible to store
> * it in the object. This is the case when:

2022-08-04 07:03:05

by Feng Tang

[permalink] [raw]
Subject: Re: [mm/slub] 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten

On Tue, Aug 02, 2022 at 10:38:59PM +0800, Dmitry Vyukov wrote:
> On Tue, 2 Aug 2022 at 15:37, Feng Tang <[email protected]> wrote:
> >
> > On Tue, Aug 02, 2022 at 06:30:44PM +0800, Dmitry Vyukov wrote:
> > > .On Tue, 2 Aug 2022 at 11:43, Vlastimil Babka <[email protected]> wrote:
> > > >
> > > > On 8/2/22 09:06, Dmitry Vyukov wrote:
> > > > > On Tue, 2 Aug 2022 at 08:55, Feng Tang <[email protected]> wrote:
> > > > >>
> > > > >> On Mon, Aug 01, 2022 at 10:23:23PM +0800, Vlastimil Babka wrote:
> > > > >> > On 8/1/22 08:21, Feng Tang wrote:
> > > > >> [snip]
> > > > >> > > Cc kansan mail list.
> > > > >> > >
> > > > >> > > This is really related with KASAN debug, that in free path, some
> > > > >> > > kmalloc redzone ([orig_size+1, object_size]) area is written by
> > > > >> > > kasan to save free meta info.
> > > > >> > >
> > > > >> > > The callstack is:
> > > > >> > >
> > > > >> > > kfree
> > > > >> > > slab_free
> > > > >> > > slab_free_freelist_hook
> > > > >> > > slab_free_hook
> > > > >> > > __kasan_slab_free
> > > > >> > > ____kasan_slab_free
> > > > >> > > kasan_set_free_info
> > > > >> > > kasan_set_track
> > > > >> > >
> > > > >> > > And this issue only happens with "kmalloc-16" slab. Kasan has 2
> > > > >> > > tracks: alloc_track and free_track, for x86_64 test platform, most
> > > > >> > > of the slabs will reserve space for alloc_track, and reuse the
> > > > >> > > 'object' area for free_track. The kasan free_track is 16 bytes
> > > > >> > > large, that it will occupy the whole 'kmalloc-16's object area,
> > > > >> > > so when kmalloc-redzone is enabled by this patch, the 'overwritten'
> > > > >> > > error is triggered.
> > > > >> > >
> > > > >> > > But it won't hurt other kmalloc slabs, as kasan's free meta won't
> > > > >> > > conflict with kmalloc-redzone which stay in the latter part of
> > > > >> > > kmalloc area.
> > > > >> > >
> > > > >> > > So the solution I can think of is:
> > > > >> > > * skip the kmalloc-redzone for kmalloc-16 only, or
> > > > >> > > * skip kmalloc-redzone if kasan is enabled, or
> > > > >> > > * let kasan reserve the free meta (16 bytes) outside of object
> > > > >> > > just like for alloc meta
> > > > >> >
> > > > >> > Maybe we could add some hack that if both kasan and SLAB_STORE_USER is
> > > > >> > enabled, we bump the stored orig_size from <16 to 16? Similar to what
> > > > >> > __ksize() does.
> > > > >>
> > > > >> How about the following patch:
> > > > >>
> > > > >> ---
> > > > >> diff --git a/mm/slub.c b/mm/slub.c
> > > > >> index added2653bb0..33bbac2afaef 100644
> > > > >> --- a/mm/slub.c
> > > > >> +++ b/mm/slub.c
> > > > >> @@ -830,6 +830,16 @@ static inline void set_orig_size(struct kmem_cache *s,
> > > > >> if (!slub_debug_orig_size(s))
> > > > >> return;
> > > > >>
> > > > >> +#ifdef CONFIG_KASAN
> > > > >> + /*
> > > > >> + * When kasan is enabled, it could save its free meta data in the
> > > > >> + * start part of object area, so skip the kmalloc redzone check
> > > > >> + * for small kmalloc slabs to avoid the data conflict.
> > > > >> + */
> > > > >> + if (s->object_size <= 32)
> > > > >> + orig_size = s->object_size;
> > > > >> +#endif
> > > > >> +
> > > > >> p += get_info_end(s);
> > > > >> p += sizeof(struct track) * 2;
> > > > >>
> > > > >> I extend the size to 32 for potential's kasan meta data size increase.
> > > > >> This is tested locally, if people are OK with it, I can ask for 0Day's
> > > > >> help to verify this.
> > > >
> > > > Is there maybe some KASAN macro we can use instead of hardcoding 32?
> > >
> > > kasan_free_meta is placed in the object data after freeing, so it can
> > > be sizeof(kasan_free_meta)
> >
> > 'kasan_free_meta' is defined in mm/kasan/kasan.h, to use it we need to
> > include "../kasan/kasan.h" in slub.c, or move its definition to
> > "include/linux/kasan.h"
> >
> > Another idea is to save the info in kasan_info, like:
> >
> > ---
> > diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> > index b092277bf48d..97e899948d0b 100644
> > --- a/include/linux/kasan.h
> > +++ b/include/linux/kasan.h
> > @@ -100,6 +100,7 @@ static inline bool kasan_has_integrated_init(void)
> > struct kasan_cache {
> > int alloc_meta_offset;
> > int free_meta_offset;
> > + int free_meta_size;
>
> Storing it here looks fine to me.
> But I would name it based on the meaning for external users (i.e. that
> many bytes are occupied by kasan in freed objects). For some caches
> KASAN does not store anything in freed objects at all.

OK, please review the below patch, thanks!

- Feng

---8<---
From c4fc739ea4d5222f0aba4b42b59668d64a010082 Mon Sep 17 00:00:00 2001
From: Feng Tang <[email protected]>
Date: Thu, 4 Aug 2022 13:25:35 +0800
Subject: [PATCH] mm: kasan: Add free_meta size info in struct kasan_cache

When kasan is enabled for slab/slub, it may save kasan' free_meta
data in the former part of slab object data area in slab object
free path, which works fine.

There is ongoing effort to extend slub's debug function which will
redzone the latter part of kmalloc object area, and when both of
the debug are enabled, there is possible conflict, especially when
the kmalloc object has small size, as caught by 0Day bot [1]

For better information for slab/slub, add free_meta's data size
info 'kasan_cache', so that its users can take right action to
avoid data conflict.

[1]. https://lore.kernel.org/lkml/YuYm3dWwpZwH58Hu@xsang-OptiPlex-9020/
Reported-by: kernel test robot <[email protected]>
Signed-off-by: Feng Tang <[email protected]>
---
include/linux/kasan.h | 2 ++
mm/kasan/common.c | 2 ++
2 files changed, 4 insertions(+)

diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index b092277bf48d..293bdaa0ba09 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -100,6 +100,8 @@ static inline bool kasan_has_integrated_init(void)
struct kasan_cache {
int alloc_meta_offset;
int free_meta_offset;
+ /* size of free_meta data saved in object's data area */
+ int free_meta_size_in_object;
bool is_kmalloc;
};

diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index 78be2beb7453..a627efa267d1 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -201,6 +201,8 @@ void __kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
cache->kasan_info.free_meta_offset = KASAN_NO_FREE_META;
*size = ok_size;
}
+ } else {
+ cache->kasan_info.free_meta_size_in_object = sizeof(struct kasan_free_meta);
}

/* Calculate size with optimal redzone. */
--
2.27.0


2022-08-04 11:19:03

by Dmitry Vyukov

[permalink] [raw]
Subject: Re: [mm/slub] 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten

On Thu, 4 Aug 2022 at 08:29, Feng Tang <[email protected]> wrote:
> > > > .On Tue, 2 Aug 2022 at 11:43, Vlastimil Babka <[email protected]> wrote:
> > > > >
> > > > > On 8/2/22 09:06, Dmitry Vyukov wrote:
> > > > > > On Tue, 2 Aug 2022 at 08:55, Feng Tang <[email protected]> wrote:
> > > > > >>
> > > > > >> On Mon, Aug 01, 2022 at 10:23:23PM +0800, Vlastimil Babka wrote:
> > > > > >> > On 8/1/22 08:21, Feng Tang wrote:
> > > > > >> [snip]
> > > > > >> > > Cc kansan mail list.
> > > > > >> > >
> > > > > >> > > This is really related with KASAN debug, that in free path, some
> > > > > >> > > kmalloc redzone ([orig_size+1, object_size]) area is written by
> > > > > >> > > kasan to save free meta info.
> > > > > >> > >
> > > > > >> > > The callstack is:
> > > > > >> > >
> > > > > >> > > kfree
> > > > > >> > > slab_free
> > > > > >> > > slab_free_freelist_hook
> > > > > >> > > slab_free_hook
> > > > > >> > > __kasan_slab_free
> > > > > >> > > ____kasan_slab_free
> > > > > >> > > kasan_set_free_info
> > > > > >> > > kasan_set_track
> > > > > >> > >
> > > > > >> > > And this issue only happens with "kmalloc-16" slab. Kasan has 2
> > > > > >> > > tracks: alloc_track and free_track, for x86_64 test platform, most
> > > > > >> > > of the slabs will reserve space for alloc_track, and reuse the
> > > > > >> > > 'object' area for free_track. The kasan free_track is 16 bytes
> > > > > >> > > large, that it will occupy the whole 'kmalloc-16's object area,
> > > > > >> > > so when kmalloc-redzone is enabled by this patch, the 'overwritten'
> > > > > >> > > error is triggered.
> > > > > >> > >
> > > > > >> > > But it won't hurt other kmalloc slabs, as kasan's free meta won't
> > > > > >> > > conflict with kmalloc-redzone which stay in the latter part of
> > > > > >> > > kmalloc area.
> > > > > >> > >
> > > > > >> > > So the solution I can think of is:
> > > > > >> > > * skip the kmalloc-redzone for kmalloc-16 only, or
> > > > > >> > > * skip kmalloc-redzone if kasan is enabled, or
> > > > > >> > > * let kasan reserve the free meta (16 bytes) outside of object
> > > > > >> > > just like for alloc meta
> > > > > >> >
> > > > > >> > Maybe we could add some hack that if both kasan and SLAB_STORE_USER is
> > > > > >> > enabled, we bump the stored orig_size from <16 to 16? Similar to what
> > > > > >> > __ksize() does.
> > > > > >>
> > > > > >> How about the following patch:
> > > > > >>
> > > > > >> ---
> > > > > >> diff --git a/mm/slub.c b/mm/slub.c
> > > > > >> index added2653bb0..33bbac2afaef 100644
> > > > > >> --- a/mm/slub.c
> > > > > >> +++ b/mm/slub.c
> > > > > >> @@ -830,6 +830,16 @@ static inline void set_orig_size(struct kmem_cache *s,
> > > > > >> if (!slub_debug_orig_size(s))
> > > > > >> return;
> > > > > >>
> > > > > >> +#ifdef CONFIG_KASAN
> > > > > >> + /*
> > > > > >> + * When kasan is enabled, it could save its free meta data in the
> > > > > >> + * start part of object area, so skip the kmalloc redzone check
> > > > > >> + * for small kmalloc slabs to avoid the data conflict.
> > > > > >> + */
> > > > > >> + if (s->object_size <= 32)
> > > > > >> + orig_size = s->object_size;
> > > > > >> +#endif
> > > > > >> +
> > > > > >> p += get_info_end(s);
> > > > > >> p += sizeof(struct track) * 2;
> > > > > >>
> > > > > >> I extend the size to 32 for potential's kasan meta data size increase.
> > > > > >> This is tested locally, if people are OK with it, I can ask for 0Day's
> > > > > >> help to verify this.
> > > > >
> > > > > Is there maybe some KASAN macro we can use instead of hardcoding 32?
> > > >
> > > > kasan_free_meta is placed in the object data after freeing, so it can
> > > > be sizeof(kasan_free_meta)
> > >
> > > 'kasan_free_meta' is defined in mm/kasan/kasan.h, to use it we need to
> > > include "../kasan/kasan.h" in slub.c, or move its definition to
> > > "include/linux/kasan.h"
> > >
> > > Another idea is to save the info in kasan_info, like:
> > >
> > > ---
> > > diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> > > index b092277bf48d..97e899948d0b 100644
> > > --- a/include/linux/kasan.h
> > > +++ b/include/linux/kasan.h
> > > @@ -100,6 +100,7 @@ static inline bool kasan_has_integrated_init(void)
> > > struct kasan_cache {
> > > int alloc_meta_offset;
> > > int free_meta_offset;
> > > + int free_meta_size;
> >
> > Storing it here looks fine to me.
> > But I would name it based on the meaning for external users (i.e. that
> > many bytes are occupied by kasan in freed objects). For some caches
> > KASAN does not store anything in freed objects at all.
>
> OK, please review the below patch, thanks!
>
> - Feng
>
> ---8<---
> From c4fc739ea4d5222f0aba4b42b59668d64a010082 Mon Sep 17 00:00:00 2001
> From: Feng Tang <[email protected]>
> Date: Thu, 4 Aug 2022 13:25:35 +0800
> Subject: [PATCH] mm: kasan: Add free_meta size info in struct kasan_cache
>
> When kasan is enabled for slab/slub, it may save kasan' free_meta
> data in the former part of slab object data area in slab object
> free path, which works fine.
>
> There is ongoing effort to extend slub's debug function which will
> redzone the latter part of kmalloc object area, and when both of
> the debug are enabled, there is possible conflict, especially when
> the kmalloc object has small size, as caught by 0Day bot [1]
>
> For better information for slab/slub, add free_meta's data size
> info 'kasan_cache', so that its users can take right action to
> avoid data conflict.
>
> [1]. https://lore.kernel.org/lkml/YuYm3dWwpZwH58Hu@xsang-OptiPlex-9020/
> Reported-by: kernel test robot <[email protected]>
> Signed-off-by: Feng Tang <[email protected]>

Acked-by: Dmitry Vyukov <[email protected]>

I assume there will be a second patch that uses
free_meta_size_in_object in slub debug code.

> ---
> include/linux/kasan.h | 2 ++
> mm/kasan/common.c | 2 ++
> 2 files changed, 4 insertions(+)
>
> diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> index b092277bf48d..293bdaa0ba09 100644
> --- a/include/linux/kasan.h
> +++ b/include/linux/kasan.h
> @@ -100,6 +100,8 @@ static inline bool kasan_has_integrated_init(void)
> struct kasan_cache {
> int alloc_meta_offset;
> int free_meta_offset;
> + /* size of free_meta data saved in object's data area */
> + int free_meta_size_in_object;
> bool is_kmalloc;
> };
>
> diff --git a/mm/kasan/common.c b/mm/kasan/common.c
> index 78be2beb7453..a627efa267d1 100644
> --- a/mm/kasan/common.c
> +++ b/mm/kasan/common.c
> @@ -201,6 +201,8 @@ void __kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
> cache->kasan_info.free_meta_offset = KASAN_NO_FREE_META;
> *size = ok_size;
> }
> + } else {
> + cache->kasan_info.free_meta_size_in_object = sizeof(struct kasan_free_meta);
> }
>
> /* Calculate size with optimal redzone. */
> --
> 2.27.0

2022-08-04 13:25:20

by Feng Tang

[permalink] [raw]
Subject: Re: [mm/slub] 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten

On Thu, Aug 04, 2022 at 06:47:58PM +0800, Dmitry Vyukov wrote:
> On Thu, 4 Aug 2022 at 08:29, Feng Tang <[email protected]> wrote:
[...]
> >
> > ---8<---
> > From c4fc739ea4d5222f0aba4b42b59668d64a010082 Mon Sep 17 00:00:00 2001
> > From: Feng Tang <[email protected]>
> > Date: Thu, 4 Aug 2022 13:25:35 +0800
> > Subject: [PATCH] mm: kasan: Add free_meta size info in struct kasan_cache
> >
> > When kasan is enabled for slab/slub, it may save kasan' free_meta
> > data in the former part of slab object data area in slab object
> > free path, which works fine.
> >
> > There is ongoing effort to extend slub's debug function which will
> > redzone the latter part of kmalloc object area, and when both of
> > the debug are enabled, there is possible conflict, especially when
> > the kmalloc object has small size, as caught by 0Day bot [1]
> >
> > For better information for slab/slub, add free_meta's data size
> > info 'kasan_cache', so that its users can take right action to
> > avoid data conflict.
> >
> > [1]. https://lore.kernel.org/lkml/YuYm3dWwpZwH58Hu@xsang-OptiPlex-9020/
> > Reported-by: kernel test robot <[email protected]>
> > Signed-off-by: Feng Tang <[email protected]>
>
> Acked-by: Dmitry Vyukov <[email protected]>

Thanks for your suggestion and review!

> I assume there will be a second patch that uses
> free_meta_size_in_object in slub debug code.

Yes, it will be called in the slub kmalloc object redzone debug code.

Thanks,
Feng

> > ---
> > include/linux/kasan.h | 2 ++
> > mm/kasan/common.c | 2 ++
> > 2 files changed, 4 insertions(+)
> >
> > diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> > index b092277bf48d..293bdaa0ba09 100644
> > --- a/include/linux/kasan.h
> > +++ b/include/linux/kasan.h
> > @@ -100,6 +100,8 @@ static inline bool kasan_has_integrated_init(void)
> > struct kasan_cache {
> > int alloc_meta_offset;
> > int free_meta_offset;
> > + /* size of free_meta data saved in object's data area */
> > + int free_meta_size_in_object;
> > bool is_kmalloc;
> > };
> >
> > diff --git a/mm/kasan/common.c b/mm/kasan/common.c
> > index 78be2beb7453..a627efa267d1 100644
> > --- a/mm/kasan/common.c
> > +++ b/mm/kasan/common.c
> > @@ -201,6 +201,8 @@ void __kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
> > cache->kasan_info.free_meta_offset = KASAN_NO_FREE_META;
> > *size = ok_size;
> > }
> > + } else {
> > + cache->kasan_info.free_meta_size_in_object = sizeof(struct kasan_free_meta);
> > }
> >
> > /* Calculate size with optimal redzone. */
> > --
> > 2.27.0
>

2022-08-15 07:33:39

by Feng Tang

[permalink] [raw]
Subject: Re: [mm/slub] 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten

Hi Oliver,

Could you help to check if the below combined patch fix the problem
you reported? thanks!

- Feng

---

diff --git a/include/linux/kasan.h b/include/linux/kasan.h
index b092277bf48d6..293bdaa0ba09c 100644
--- a/include/linux/kasan.h
+++ b/include/linux/kasan.h
@@ -100,6 +100,8 @@ static inline bool kasan_has_integrated_init(void)
struct kasan_cache {
int alloc_meta_offset;
int free_meta_offset;
+ /* size of free_meta data saved in object's data area */
+ int free_meta_size_in_object;
bool is_kmalloc;
};

diff --git a/mm/kasan/common.c b/mm/kasan/common.c
index c40c0e7b3b5f1..9d2994dbe4e7a 100644
--- a/mm/kasan/common.c
+++ b/mm/kasan/common.c
@@ -200,6 +200,8 @@ void __kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
cache->kasan_info.free_meta_offset = KASAN_NO_FREE_META;
*size = ok_size;
}
+ } else {
+ cache->kasan_info.free_meta_size_in_object = sizeof(struct kasan_free_meta);
}

/* Calculate size with optimal redzone. */
diff --git a/mm/slub.c b/mm/slub.c
index added2653bb03..272dcdbaaa03b 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -830,6 +830,16 @@ static inline void set_orig_size(struct kmem_cache *s,
if (!slub_debug_orig_size(s))
return;

+#ifdef CONFIG_KASAN_GENERIC
+ /*
+ * kasn could save its free meta data in the start part of object
+ * area, so skip the redzone check if kasan's meta data size is
+ * bigger enough to possibly overlap with kmalloc redzone
+ */
+ if (s->kasan_info.free_meta_size_in_object * 2 > s->object_size)
+ orig_size = s->object_size;
+#endif
+
p += get_info_end(s);
p += sizeof(struct track) * 2;

On Thu, Aug 04, 2022 at 08:22:31PM +0800, Tang, Feng wrote:
> On Thu, Aug 04, 2022 at 06:47:58PM +0800, Dmitry Vyukov wrote:
> > On Thu, 4 Aug 2022 at 08:29, Feng Tang <[email protected]> wrote:
> [...]
> > >
> > > ---8<---
> > > From c4fc739ea4d5222f0aba4b42b59668d64a010082 Mon Sep 17 00:00:00 2001
> > > From: Feng Tang <[email protected]>
> > > Date: Thu, 4 Aug 2022 13:25:35 +0800
> > > Subject: [PATCH] mm: kasan: Add free_meta size info in struct kasan_cache
> > >
> > > When kasan is enabled for slab/slub, it may save kasan' free_meta
> > > data in the former part of slab object data area in slab object
> > > free path, which works fine.
> > >
> > > There is ongoing effort to extend slub's debug function which will
> > > redzone the latter part of kmalloc object area, and when both of
> > > the debug are enabled, there is possible conflict, especially when
> > > the kmalloc object has small size, as caught by 0Day bot [1]
> > >
> > > For better information for slab/slub, add free_meta's data size
> > > info 'kasan_cache', so that its users can take right action to
> > > avoid data conflict.
> > >
> > > [1]. https://lore.kernel.org/lkml/YuYm3dWwpZwH58Hu@xsang-OptiPlex-9020/
> > > Reported-by: kernel test robot <[email protected]>
> > > Signed-off-by: Feng Tang <[email protected]>
> >
> > Acked-by: Dmitry Vyukov <[email protected]>
>
> Thanks for your suggestion and review!
>
> > I assume there will be a second patch that uses
> > free_meta_size_in_object in slub debug code.
>
> Yes, it will be called in the slub kmalloc object redzone debug code.
>
> Thanks,
> Feng
>
> > > ---
> > > include/linux/kasan.h | 2 ++
> > > mm/kasan/common.c | 2 ++
> > > 2 files changed, 4 insertions(+)
> > >
> > > diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> > > index b092277bf48d..293bdaa0ba09 100644
> > > --- a/include/linux/kasan.h
> > > +++ b/include/linux/kasan.h
> > > @@ -100,6 +100,8 @@ static inline bool kasan_has_integrated_init(void)
> > > struct kasan_cache {
> > > int alloc_meta_offset;
> > > int free_meta_offset;
> > > + /* size of free_meta data saved in object's data area */
> > > + int free_meta_size_in_object;
> > > bool is_kmalloc;
> > > };
> > >
> > > diff --git a/mm/kasan/common.c b/mm/kasan/common.c
> > > index 78be2beb7453..a627efa267d1 100644
> > > --- a/mm/kasan/common.c
> > > +++ b/mm/kasan/common.c
> > > @@ -201,6 +201,8 @@ void __kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
> > > cache->kasan_info.free_meta_offset = KASAN_NO_FREE_META;
> > > *size = ok_size;
> > > }
> > > + } else {
> > > + cache->kasan_info.free_meta_size_in_object = sizeof(struct kasan_free_meta);
> > > }
> > >
> > > /* Calculate size with optimal redzone. */
> > > --
> > > 2.27.0
> >

2022-08-16 13:53:27

by Oliver Sang

[permalink] [raw]
Subject: Re: [mm/slub] 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten

Hi Feng,

On Mon, Aug 15, 2022 at 03:27:43PM +0800, Feng Tang wrote:
> Hi Oliver,
>
> Could you help to check if the below combined patch fix the problem
> you reported? thanks!

I applied below patch upon 3616799128:
28b34693c816e9 (linux-devel/fixup-3616799128) fix for 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten
3616799128612e (linux-review/Feng-Tang/mm-slub-some-debug-enhancements/20220727-151318) mm/slub: extend redzone check to cover extra allocated kmalloc space than requested
acc77d62f91ccc mm/slub: only zero the requested size of buffer for kzalloc


confirmed the issue gone:

=========================================================================================
compiler/kconfig/rootfs/sleep/tbox_group/testcase:
gcc-11/x86_64-randconfig-a005-20220117/debian-11.1-x86_64-20220510.cgz/300/vm-snb/boot


acc77d62f91ccca2 3616799128612e04ed919579e2c 28b34693c816e9fcbe42bdd341e
---------------- --------------------------- ---------------------------
fail:runs %reproduction fail:runs %reproduction fail:runs
| | | | |
:20 95% 19:20 0% :22 dmesg.BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten
:20 95% 19:20 0% :22 dmesg.BUG_kmalloc-#(Tainted:G_B):kmalloc_Redzone_overwritten



>
> - Feng
>
> ---
>
> diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> index b092277bf48d6..293bdaa0ba09c 100644
> --- a/include/linux/kasan.h
> +++ b/include/linux/kasan.h
> @@ -100,6 +100,8 @@ static inline bool kasan_has_integrated_init(void)
> struct kasan_cache {
> int alloc_meta_offset;
> int free_meta_offset;
> + /* size of free_meta data saved in object's data area */
> + int free_meta_size_in_object;
> bool is_kmalloc;
> };
>
> diff --git a/mm/kasan/common.c b/mm/kasan/common.c
> index c40c0e7b3b5f1..9d2994dbe4e7a 100644
> --- a/mm/kasan/common.c
> +++ b/mm/kasan/common.c
> @@ -200,6 +200,8 @@ void __kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
> cache->kasan_info.free_meta_offset = KASAN_NO_FREE_META;
> *size = ok_size;
> }
> + } else {
> + cache->kasan_info.free_meta_size_in_object = sizeof(struct kasan_free_meta);
> }
>
> /* Calculate size with optimal redzone. */
> diff --git a/mm/slub.c b/mm/slub.c
> index added2653bb03..272dcdbaaa03b 100644
> --- a/mm/slub.c
> +++ b/mm/slub.c
> @@ -830,6 +830,16 @@ static inline void set_orig_size(struct kmem_cache *s,
> if (!slub_debug_orig_size(s))
> return;
>
> +#ifdef CONFIG_KASAN_GENERIC
> + /*
> + * kasn could save its free meta data in the start part of object
> + * area, so skip the redzone check if kasan's meta data size is
> + * bigger enough to possibly overlap with kmalloc redzone
> + */
> + if (s->kasan_info.free_meta_size_in_object * 2 > s->object_size)
> + orig_size = s->object_size;
> +#endif
> +
> p += get_info_end(s);
> p += sizeof(struct track) * 2;
>
> On Thu, Aug 04, 2022 at 08:22:31PM +0800, Tang, Feng wrote:
> > On Thu, Aug 04, 2022 at 06:47:58PM +0800, Dmitry Vyukov wrote:
> > > On Thu, 4 Aug 2022 at 08:29, Feng Tang <[email protected]> wrote:
> > [...]
> > > >
> > > > ---8<---
> > > > From c4fc739ea4d5222f0aba4b42b59668d64a010082 Mon Sep 17 00:00:00 2001
> > > > From: Feng Tang <[email protected]>
> > > > Date: Thu, 4 Aug 2022 13:25:35 +0800
> > > > Subject: [PATCH] mm: kasan: Add free_meta size info in struct kasan_cache
> > > >
> > > > When kasan is enabled for slab/slub, it may save kasan' free_meta
> > > > data in the former part of slab object data area in slab object
> > > > free path, which works fine.
> > > >
> > > > There is ongoing effort to extend slub's debug function which will
> > > > redzone the latter part of kmalloc object area, and when both of
> > > > the debug are enabled, there is possible conflict, especially when
> > > > the kmalloc object has small size, as caught by 0Day bot [1]
> > > >
> > > > For better information for slab/slub, add free_meta's data size
> > > > info 'kasan_cache', so that its users can take right action to
> > > > avoid data conflict.
> > > >
> > > > [1]. https://lore.kernel.org/lkml/YuYm3dWwpZwH58Hu@xsang-OptiPlex-9020/
> > > > Reported-by: kernel test robot <[email protected]>
> > > > Signed-off-by: Feng Tang <[email protected]>
> > >
> > > Acked-by: Dmitry Vyukov <[email protected]>
> >
> > Thanks for your suggestion and review!
> >
> > > I assume there will be a second patch that uses
> > > free_meta_size_in_object in slub debug code.
> >
> > Yes, it will be called in the slub kmalloc object redzone debug code.
> >
> > Thanks,
> > Feng
> >
> > > > ---
> > > > include/linux/kasan.h | 2 ++
> > > > mm/kasan/common.c | 2 ++
> > > > 2 files changed, 4 insertions(+)
> > > >
> > > > diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> > > > index b092277bf48d..293bdaa0ba09 100644
> > > > --- a/include/linux/kasan.h
> > > > +++ b/include/linux/kasan.h
> > > > @@ -100,6 +100,8 @@ static inline bool kasan_has_integrated_init(void)
> > > > struct kasan_cache {
> > > > int alloc_meta_offset;
> > > > int free_meta_offset;
> > > > + /* size of free_meta data saved in object's data area */
> > > > + int free_meta_size_in_object;
> > > > bool is_kmalloc;
> > > > };
> > > >
> > > > diff --git a/mm/kasan/common.c b/mm/kasan/common.c
> > > > index 78be2beb7453..a627efa267d1 100644
> > > > --- a/mm/kasan/common.c
> > > > +++ b/mm/kasan/common.c
> > > > @@ -201,6 +201,8 @@ void __kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
> > > > cache->kasan_info.free_meta_offset = KASAN_NO_FREE_META;
> > > > *size = ok_size;
> > > > }
> > > > + } else {
> > > > + cache->kasan_info.free_meta_size_in_object = sizeof(struct kasan_free_meta);
> > > > }
> > > >
> > > > /* Calculate size with optimal redzone. */
> > > > --
> > > > 2.27.0
> > >

2022-08-16 15:02:45

by Feng Tang

[permalink] [raw]
Subject: Re: [mm/slub] 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten

On Tue, Aug 16, 2022 at 09:27:39PM +0800, Sang, Oliver wrote:
> Hi Feng,
>
> On Mon, Aug 15, 2022 at 03:27:43PM +0800, Feng Tang wrote:
> > Hi Oliver,
> >
> > Could you help to check if the below combined patch fix the problem
> > you reported? thanks!
>
> I applied below patch upon 3616799128:
> 28b34693c816e9 (linux-devel/fixup-3616799128) fix for 3616799128: BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten
> 3616799128612e (linux-review/Feng-Tang/mm-slub-some-debug-enhancements/20220727-151318) mm/slub: extend redzone check to cover extra allocated kmalloc space than requested
> acc77d62f91ccc mm/slub: only zero the requested size of buffer for kzalloc
>
>
> confirmed the issue gone:

Many thanks for helping testing!

- Feng


> =========================================================================================
> compiler/kconfig/rootfs/sleep/tbox_group/testcase:
> gcc-11/x86_64-randconfig-a005-20220117/debian-11.1-x86_64-20220510.cgz/300/vm-snb/boot
>
>
> acc77d62f91ccca2 3616799128612e04ed919579e2c 28b34693c816e9fcbe42bdd341e
> ---------------- --------------------------- ---------------------------
> fail:runs %reproduction fail:runs %reproduction fail:runs
> | | | | |
> :20 95% 19:20 0% :22 dmesg.BUG_kmalloc-#(Not_tainted):kmalloc_Redzone_overwritten
> :20 95% 19:20 0% :22 dmesg.BUG_kmalloc-#(Tainted:G_B):kmalloc_Redzone_overwritten
>
>
>
> >
> > - Feng
> >
> > ---
> >
> > diff --git a/include/linux/kasan.h b/include/linux/kasan.h
> > index b092277bf48d6..293bdaa0ba09c 100644
> > --- a/include/linux/kasan.h
> > +++ b/include/linux/kasan.h
> > @@ -100,6 +100,8 @@ static inline bool kasan_has_integrated_init(void)
> > struct kasan_cache {
> > int alloc_meta_offset;
> > int free_meta_offset;
> > + /* size of free_meta data saved in object's data area */
> > + int free_meta_size_in_object;
> > bool is_kmalloc;
> > };
> >
> > diff --git a/mm/kasan/common.c b/mm/kasan/common.c
> > index c40c0e7b3b5f1..9d2994dbe4e7a 100644
> > --- a/mm/kasan/common.c
> > +++ b/mm/kasan/common.c
> > @@ -200,6 +200,8 @@ void __kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
> > cache->kasan_info.free_meta_offset = KASAN_NO_FREE_META;
> > *size = ok_size;
> > }
> > + } else {
> > + cache->kasan_info.free_meta_size_in_object = sizeof(struct kasan_free_meta);
> > }
> >
> > /* Calculate size with optimal redzone. */
> > diff --git a/mm/slub.c b/mm/slub.c
> > index added2653bb03..272dcdbaaa03b 100644
> > --- a/mm/slub.c
> > +++ b/mm/slub.c
> > @@ -830,6 +830,16 @@ static inline void set_orig_size(struct kmem_cache *s,
> > if (!slub_debug_orig_size(s))
> > return;
> >
> > +#ifdef CONFIG_KASAN_GENERIC
> > + /*
> > + * kasn could save its free meta data in the start part of object
> > + * area, so skip the redzone check if kasan's meta data size is
> > + * bigger enough to possibly overlap with kmalloc redzone
> > + */
> > + if (s->kasan_info.free_meta_size_in_object * 2 > s->object_size)
> > + orig_size = s->object_size;
> > +#endif
> > +
> > p += get_info_end(s);
> > p += sizeof(struct track) * 2;
> >