* [PATCH] mm: kmemleak: confirm suspected leaks with a second scan
@ 2026-07-09 17:24 Catalin Marinas
2026-07-10 3:13 ` Andrew Morton
2026-07-10 8:51 ` Breno Leitao
0 siblings, 2 replies; 3+ messages in thread
From: Catalin Marinas @ 2026-07-09 17:24 UTC (permalink / raw)
To: leitao; +Cc: linux-mm, linux-kernel, Andrew Morton
The kmemleak marking phase is not atomic. While the object graph is
traversed, the kernel can modify pointers, free objects or allocate new
ones. If a reference to an object is moved from one location to another,
kmemleak scanning may miss it. We have explicit annotations like
kmemleak_transient_leak() but identifying and maintaining them is not
trivial.
Given that such transient leaks are short-lived, rather than just
reporting such objects as leaks, do another scan to confirm the
suspected objects. If no new leaks are found during the first scan, skip
the confirmation one.
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
Assisted-by: Claude:claude-opus-4-8
Cc: Breno Leitao <leitao@debian.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
---
As discussed here:
https://lore.kernel.org/r/ako1sMPVu4dfQR4K@casper.infradead.org/
attempting some more heuristics to reduce the transient leaks. It
overlaps a bit with Breno's minimum scans patchset but this one limits
it to two scans only back to back and only if new leaks are found. I
would say it is complementary.
The difference from the link above is that we now use the same scan loop
to mark the suspected leaks instead of a separate, heavier one.
I told claude to refactor kmemleak_scan(), hence the assisted-by above.
Ideas mine ;).
BTW, I'll be away from Saturday for three weeks. I may reply
occasionally but won't be able to test anything.
Thanks.
mm/kmemleak.c | 57 ++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 54 insertions(+), 3 deletions(-)
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index 7c7ba17ce7af..505b5c3a423b 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -175,6 +175,8 @@ struct kmemleak_object {
#define OBJECT_PHYS (1 << 4)
/* flag set for per-CPU pointers */
#define OBJECT_PERCPU (1 << 5)
+/* flag set on an object left unreferenced by the full scan, pending confirmation */
+#define OBJECT_SUSPECT (1 << 6)
/* set when __remove_object() called */
#define DELSTATE_REMOVED (1 << 0)
@@ -235,6 +237,8 @@ static unsigned long jiffies_min_age;
static unsigned long jiffies_last_scan;
/* delay between automatic memory scannings */
static unsigned long jiffies_scan_wait;
+/* number of objects flagged OBJECT_SUSPECT during the current scan */
+static int nr_suspects;
/* enables or disables the task stacks scanning */
static int kmemleak_stack_scan = 1;
/* protects the memory scanning, parameters and debug/kmemleak file access */
@@ -1439,6 +1443,11 @@ static void update_refs(struct kmemleak_object *object)
*/
object->count++;
if (color_gray(object)) {
+ /* referenced after all, no longer a suspect */
+ if (object->flags & OBJECT_SUSPECT) {
+ object->flags &= ~OBJECT_SUSPECT;
+ nr_suspects--;
+ }
/* put_object() called when removing from gray_list */
WARN_ON(!get_object(object));
list_add_tail(&object->gray_list, &gray_list);
@@ -1797,15 +1806,15 @@ static void dedup_flush(struct xarray *dedup)
* kernel's standard allocators. This function must be called with the
* scan_mutex held.
*/
-static void kmemleak_scan(void)
+static int __kmemleak_scan(bool full)
{
struct kmemleak_object *object;
struct zone *zone;
int __maybe_unused i;
- struct xarray dedup;
- int new_leaks = 0;
jiffies_last_scan = jiffies;
+ if (full)
+ nr_suspects = 0;
/* prepare the kmemleak_object's */
rcu_read_lock();
@@ -1835,6 +1844,8 @@ static void kmemleak_scan(void)
/* reset the reference count (whiten the object) */
object->count = 0;
+ if (full)
+ object->flags &= ~OBJECT_SUSPECT;
if (color_gray(object) && get_object(object))
list_add_tail(&object->gray_list, &gray_list);
@@ -1904,6 +1915,10 @@ static void kmemleak_scan(void)
*/
scan_gray_list();
+ /* a confirmation scan does not look for modified objects */
+ if (!full)
+ return nr_suspects;
+
/*
* Check for new or unreferenced objects modified since the previous
* scan and color them gray until the next scan.
@@ -1926,6 +1941,11 @@ static void kmemleak_scan(void)
/* color it gray temporarily */
object->count = object->min_count;
list_add_tail(&object->gray_list, &gray_list);
+ } else if (unreferenced_object(object) &&
+ !(object->flags & OBJECT_REPORTED)) {
+ /* flag the objects left unreferenced by this scan */
+ object->flags |= OBJECT_SUSPECT;
+ nr_suspects++;
}
raw_spin_unlock_irq(&object->lock);
}
@@ -1936,12 +1956,42 @@ static void kmemleak_scan(void)
*/
scan_gray_list();
+ return nr_suspects;
+}
+
+/*
+ * Scan the memory and report the unreferenced objects as leaks. Must be
+ * called with the scan_mutex held.
+ */
+static void kmemleak_scan(void)
+{
+ struct kmemleak_object *object;
+ struct xarray dedup;
+ int new_leaks = 0;
+
+ /*
+ * Full scan. Objects left unreferenced are flagged OBJECT_SUSPECT and
+ * counted in the return value; nothing to confirm or report otherwise.
+ */
+ if (!__kmemleak_scan(true))
+ return;
+
/*
* If scanning was stopped do not report any new unreferenced objects.
*/
if (scan_should_stop())
return;
+ /*
+ * A live object whose only reference is moved by, for example, a
+ * concurrent RCU update can be missed for one scan and reported as a
+ * transient false positive. Scan again and only report the objects
+ * left unreferenced (still flagged OBJECT_SUSPECT) by both scans.
+ */
+ __kmemleak_scan(false);
+ if (scan_should_stop())
+ return;
+
/*
* Scanning result reporting. When verbose printing is enabled, dedupe
* by stackdepot trace_handle so each unique backtrace is logged once
@@ -1969,6 +2019,7 @@ static void kmemleak_scan(void)
trace_handle = 0;
dedup_print = false;
if (unreferenced_object(object) &&
+ (object->flags & OBJECT_SUSPECT) &&
!(object->flags & OBJECT_REPORTED)) {
object->flags |= OBJECT_REPORTED;
if (kmemleak_verbose) {
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH] mm: kmemleak: confirm suspected leaks with a second scan
2026-07-09 17:24 [PATCH] mm: kmemleak: confirm suspected leaks with a second scan Catalin Marinas
@ 2026-07-10 3:13 ` Andrew Morton
2026-07-10 8:51 ` Breno Leitao
1 sibling, 0 replies; 3+ messages in thread
From: Andrew Morton @ 2026-07-10 3:13 UTC (permalink / raw)
To: Catalin Marinas; +Cc: leitao, linux-mm, linux-kernel
On Thu, 9 Jul 2026 18:24:47 +0100 Catalin Marinas <catalin.marinas@arm.com> wrote:
> The kmemleak marking phase is not atomic. While the object graph is
> traversed, the kernel can modify pointers, free objects or allocate new
> ones. If a reference to an object is moved from one location to another,
> kmemleak scanning may miss it. We have explicit annotations like
> kmemleak_transient_leak() but identifying and maintaining them is not
> trivial.
>
> Given that such transient leaks are short-lived, rather than just
> reporting such objects as leaks, do another scan to confirm the
> suspected objects. If no new leaks are found during the first scan, skip
> the confirmation one.
All sort of build errors here due to other changes which are queued in
mm.git.
> BTW, I'll be away from Saturday for three weeks. I may reply
> occasionally but won't be able to test anything.
Have a great time - we'll be here when you get back.
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH] mm: kmemleak: confirm suspected leaks with a second scan
2026-07-09 17:24 [PATCH] mm: kmemleak: confirm suspected leaks with a second scan Catalin Marinas
2026-07-10 3:13 ` Andrew Morton
@ 2026-07-10 8:51 ` Breno Leitao
1 sibling, 0 replies; 3+ messages in thread
From: Breno Leitao @ 2026-07-10 8:51 UTC (permalink / raw)
To: Catalin Marinas; +Cc: linux-mm, linux-kernel, Andrew Morton
On Thu, Jul 09, 2026 at 06:24:47PM +0100, Catalin Marinas wrote:
> The kmemleak marking phase is not atomic. While the object graph is
> traversed, the kernel can modify pointers, free objects or allocate new
> ones. If a reference to an object is moved from one location to another,
> kmemleak scanning may miss it. We have explicit annotations like
> kmemleak_transient_leak() but identifying and maintaining them is not
> trivial.
>
> Given that such transient leaks are short-lived, rather than just
> reporting such objects as leaks, do another scan to confirm the
> suspected objects. If no new leaks are found during the first scan, skip
> the confirmation one.
>
> Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
> Assisted-by: Claude:claude-opus-4-8
> Cc: Breno Leitao <leitao@debian.org>
> Cc: Andrew Morton <akpm@linux-foundation.org>
Tested-by: Breno Leitao <leitao@debian.org>
Reviewed-by: Breno Leitao <leitao@debian.org>
PS: This is now conflicting with commit 946935b07cc94 ("mm/kmemleak:
skip the remaining scan phases when interrupted"), which has just showed
up in linux-next. So, a respin might be required.
> BTW, I'll be away from Saturday for three weeks. I may reply
> occasionally but won't be able to test anything.
Let me know if you want me to respin it based on linux-next.
BTW: Really thanks for doing it. I will backport it to Meta's kernel to
pressure-test it and keep an eye on false positives.
--breno
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-07-10 8:51 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-09 17:24 [PATCH] mm: kmemleak: confirm suspected leaks with a second scan Catalin Marinas
2026-07-10 3:13 ` Andrew Morton
2026-07-10 8:51 ` Breno Leitao
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox