On Thu, Jul 02, 2026 at 07:55:42AM -0700, Breno Leitao wrote:
> On Thu, Jul 02, 2026 at 09:41:14AM +0100, Catalin Marinas wrote:
> > On Fri, Jun 26, 2026 at 08:52:03AM -0700, Breno Leitao wrote:
> > > +pass "min_unref_scans=1 immediate; =2 gated to 2nd scan (counts 
> > > $first/$s1/$s2); param read-back ok"
> > 
> > Are these off by one?
> 
> They seem to be OK, and I've tested it multiple times.
> 
> > Kmemleak has a mechanism to detect live objects
> > via the checksum. A side effect is that on allocation, the checksum is 0
> > and only after the first scan the checksum is changed.
> 
> I got the impression that checksum continues to be zero for these
> objects during the whole life time? (weird). 

I've investigated this a bit more and I found something interesting, in
our per_pcu checksum. The code in update_checksum() is:

        for_each_possible_cpu(cpu) {
                void *ptr = per_cpu_ptr((void __percpu *)object->pointer, cpu);

                object->checksum ^= crc32(0, kasan_reset_tag((void *)ptr), 
object->size);
        }

>From my naive view, this has two concerns:

1) In the kernel, crc32(0, <64 zero bytes>, 64) is zero, and the samples' test
I am using (kmemleak-test.c) has:

        pr_info("__alloc_percpu(64, 4) = 0x%px\n", __alloc_percpu(64, 4)); 

alloc_percpu returns ZEROed memory, so, we are checkingsuming zero content.
Because we are using 0 as seed, that is returning zero.

object->checksum is a bunch of 0 XOR 0 XOR 0 and so forth.

2) that XOR above seems very weird. Basically we want to detect if some of
those per-cpu areas changed, here, but, if checksum goes to zero if two object 
content is similar.

Let me give you a simple example. We have SMP=2, and both objects have crc32 =
0x42. At the end of that function, object->checksum will be zero, given 0x42
XOR 0x42 is zero.

If both object changes their content at the same time, object->checksum will
continue to be zero (although the content (and checksum) HAS changed).

I understand we want to detect any change in any of these per cpu field and
catch it independent of the CPU. I am inclined toward that.

        --- a/mm/kmemleak.c
        +++ b/mm/kmemleak.c
        @@ -1409,8 +1409,9 @@ static bool update_checksum(struct 
kmemleak_object *object)
                        object->checksum = 0;
                        for_each_possible_cpu(cpu) {
                                void *ptr = per_cpu_ptr((void __percpu 
*)object->pointer, cpu);
        +                       u32 seed = object->checksum + cpu;

        -                       object->checksum ^= crc32(0, 
kasan_reset_tag((void *)ptr), object->size);
        +                       object->checksum ^= crc32(seed, 
kasan_reset_tag((void *)ptr), object->size);
                        }
                } else {
                        object->checksum = crc32(0, kasan_reset_tag((void 
*)object->pointer), object->size);



Once this is fixed, then I priming would make sense.

Please let me know if my flaky logic is worse than usual this Friday.
 --breno

Reply via email to