From nobody Tue Sep 29 09:09:43 2026 Received: from stravinsky.debian.org (stravinsky.debian.org [82.195.75.108]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7DDA9356767 for ; Mon, 10 Aug 2026 11:47:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=82.195.75.108 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786362432; cv=none; b=Bfe/R3XUOtGB52JkGEd3Z60rQ7eO/3XnQg1J8X+L3y5bVaM1jy5zUfmT2PP1jFnTjGknpYoQPfdUfU0YtrxM394RdmeYD+4uUnHUWFOPP29lHkpIX4cKSvfcj5uCdjKbFUStOdbJVlhEnfxXBKcfjfwkIJp85cO0+I1sNbdht24= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786362432; c=relaxed/simple; bh=IWE6FCUdfLUBswJH7GKRJAQjZ3aNqLPQgVXxYxuw02k=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To:Cc; b=F9TL0yUoaymuHN3nkMGy5Jx9SFcRJlEBexzsD2BQxQM6T8yA4ArgGVg8ed+jijUPVqeoSRdUBUXcPJEGUGspVUOKuBHJxJ5zLKzChhLJrHLUwtRmqkYY85mYTVH5xJ1NIK0CoGq60UEYJ+zu0IIcCAAz8rF2n8vZmYrxz/QqXZ8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=debian.org; spf=pass smtp.mailfrom=debian.org; dkim=pass (2048-bit key) header.d=debian.org header.i=@debian.org header.b=v5cLVkyg; arc=none smtp.client-ip=82.195.75.108 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=debian.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=debian.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=debian.org header.i=@debian.org header.b="v5cLVkyg" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=debian.org; s=smtpauto.stravinsky; h=X-Debian-User:Cc:To:Message-Id: Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date:From: Reply-To:Content-ID:Content-Description:In-Reply-To:References; bh=O2iezPMu28AQ9FiVBZAVJm9ak52jtf2G3+ur1e6CHCY=; b=v5cLVkygc6Yr1ezUXP8nKmXaKF QMjIOOrZGjMIUgdn0rhL2yd0MIFkZS/nvsn1Cg4mPiStPk/DA9/n1xcGJGGF++l3mqumczkFVjLhR 72t99AeikyuoDtLYJDYzeSW2T/s1XYNjPkSgw4XsnxBKhZyTu6oXaRyVyiGk6xzS9TwTslo4WFFms jlezgJ0LPao/K6VpTmgytX4JwRK8QzriMbFCAFQO86GfDyztU/XjzE22HZqeIqQm/zXpNxDPNbG6s d2t4U7Ba+tAupMcue0dqzQh61vCxFAMqzRq/c9+92cogH0F98k268B6k6jTrjqUKXchDSm1oGoYAV nMo9ZRGg==; Received: from authenticated-user by stravinsky.debian.org with esmtpsa (TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.96) (envelope-from ) id 1wtOTB-002j8w-3D; Mon, 10 Aug 2026 11:47:06 +0000 From: Breno Leitao Date: Mon, 10 Aug 2026 04:46:45 -0700 Subject: [PATCH] sched/topology: don't claim sched_domain_shared twice on the same domain Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260810-b4-sched_shared_leak-v1-1-3eacd249d0a3@debian.org> X-B4-Tracking: v=1; b=H4sIACS6eWoC/yXMUQqDMBCE4avIPjcQg0jpVaSUbJyYbUUl25aCe HdTfRq+h/lXUmSB0q1aKeMrKvNUUF8qCslPA4z0xeSsa+21toYboyGhf2jyucwI/zKRfWwDw7J rqFyXjCi/I9vdT+uHnwjvf4u2bQf8GI4seAAAAA== X-Change-ID: 20260810-b4-sched_shared_leak-fbaf6cbe0b24 To: Ingo Molnar , Peter Zijlstra , Juri Lelli , Vincent Guittot , Dietmar Eggemann , Steven Rostedt , Ben Segall , Mel Gorman , Valentin Schneider , K Prateek Nayak Cc: linux-kernel@vger.kernel.org, Breno Leitao X-Mailer: b4 0.15-dev-47773 X-Developer-Signature: v=1; a=openpgp-sha256; l=3727; i=leitao@debian.org; h=from:subject:message-id; bh=IWE6FCUdfLUBswJH7GKRJAQjZ3aNqLPQgVXxYxuw02k=; b=owEBbQKS/ZANAwAIATWjk5/8eHdtAcsmYgBqebo14hh73/JfICc+QgAvVMJfGqt+MsmVgmvF7 n+xRgDypiaJAjMEAAEIAB0WIQSshTmm6PRnAspKQ5s1o5Of/Hh3bQUCanm6NQAKCRA1o5Of/Hh3 bQoND/4+VIRMkoSsMUDnVasAjHv5If+c1mW3yZtr0IXBvscd9ObAwati6ULTfgrzU8+6t8bjMOs zO0OjAYRbtunSOen9c+B5grva9LWd4b6l/LqzYJgzIu5+ywbK+tujk/REIRRikkAs9hVw83BZln 3xZvpquthUujM2jJr5v9TCV/pRVQwphuzHkfd0Wq/QQj7NH2JO7AivxfGGbq+nPgma9e9zGjXAI x1JmfgjEBvX+Re8LFS/Lm03zxeIpfCr1soXaUAl9mJQ1wE4KkFFtfgwc6sWwQ5zAo921iO7I607 ndPFVgEuQZf0qrutEpgMdQRMgSaeDA7eXYGkPGD3yigjxfHXXtWI3OhxYT9dS9u2UXR+eMsy18k k4AplwULp0qp3PPlHNN02pK/pm2vgI+bE4vAfIOfFQRFs2ZGq+of5fGuuP+YSZ0+78R4bso0Zzf DGK6ib/IWD6Ba7Jp9kF0zTXlSBpfI0XHzw1mfE8SmO45lObLqGNyWOnjHJXZ3xxnfXlYJn1I2sp 39sMfO4JAPuRaUBrdsqGiC6wdqh10n/cFpKLWzDYIAg/CPy7P5g/+76HDAAfrBGxj0v6RYCfayZ Uo2OCVE6bmI/CaHx3ZAmM7KgUvTtysI2pGK3t3d6XC83VI68pVTUpC5+7eR6TrIu+ltFoZjw6lh 2gE7DNa/5vdX9Tg== X-Developer-Key: i=leitao@debian.org; a=openpgp; fpr=AC8539A6E8F46702CA4A439B35A3939FFC78776D X-Debian-User: leitao build_sched_domains() lets the asymmetric capacity path claim a sched_domain_shared object on the lowest SD_ASYM_CPUCAPACITY_FULL ancestor, and then unconditionally claims one for the topmost SD_SHARE_LLC domain. When those are the same sched_domain - a system whose single LLC spans CPUs of differing capacity, for example an arm64 machine with one MC domain covering every CPU - init_sched_domain_shared() runs twice on that domain. The second call overwrites sd->shared without dropping the reference the first call took, so the asym blob ends up with a refcount equal to the CPU count and nothing pointing at it. claim_allocations() sees the non-zero refcount and clears the per-CPU slot, so __sds_free() does not reclaim it either, and the object leaks. kmemleak reports one 32-byte object per build_sched_domains() call: unreferenced object 0xffff0000c02432a0 (size 32): comm "swapper/0", pid 1, jiffies 4294667436 hex dump (first 32 bytes): 08 00 00 00 08 00 00 00 00 00 00 00 20 00 00 00 ............ ... 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ backtrace (crc f4478cb7): kmemleak_alloc+0x44/0xd8 __kmalloc_cache_node_noprof+0x344/0x5d0 build_sched_domains+0x2f8/0x2110 sched_init_domains+0xec/0x160 sched_init_smp+0x48/0x108 kernel_init_freeable+0x1cc/0x2b8 ref and nr_busy_cpus are both the online CPU count and alloc_flags is 0x20, SD_ASYM_CPUCAPACITY, identifying it as the blob the asym path claimed. Only claim a shared object for the LLC domain when the domain does not already have one. sd_init() zero initialises sd->shared for every domain it builds, so a non-NULL sd->shared here means the asym path already claimed this very domain. Cache aware scheduling still finds a shared object on sd_llc, the same one, covering the same span. Reproduced under QEMU/virtme-ng on arm64 with two capacity tiers (capacity-dmips-mhz 0x400 on cpu0-3 and 0x200 on cpu4-7), where the MC domain spans all CPUs and carries both SD_SHARE_LLC and SD_ASYM_CPUCAPACITY_FULL. Leaked sched_domain_shared objects reported by kmemleak, with a kmemleak-test module loaded as a positive control: before after after boot 1 0 after 12 rebuilds via CPU hotplug 13 0 That is exactly one leak per build_sched_domains(), and none once the domain is only claimed once. Fixes: 9e005ed21152 ("sched/topology: Allow multiple domains to claim sched= _domain_shared") Signed-off-by: Breno Leitao --- The hunk context is identical in v7.2-rc7 and in current linux-next, so this applies cleanly to both. --- kernel/sched/topology.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c index 5a29e506c25d5..206552d51ce2e 100644 --- a/kernel/sched/topology.c +++ b/kernel/sched/topology.c @@ -3169,7 +3169,13 @@ build_sched_domains(const struct cpumask *cpu_map, s= truct sched_domain_attr *att sd =3D sd->parent; =20 if (sd->flags & SD_SHARE_LLC) { - init_sched_domain_shared(&d, sd, SD_SHARE_LLC); + /* + * The asym path above may have claimed a shared object + * on this very domain; claiming it again overwrites + * sd->shared and leaks the first reference. + */ + if (!sd->shared) + init_sched_domain_shared(&d, sd, SD_SHARE_LLC); =20 /* * In presence of higher domains, adjust the --- base-commit: 6b8c8af514d739d0335f5579b585e02babe8a727 change-id: 20260810-b4-sched_shared_leak-fbaf6cbe0b24 Best regards, -- =20 Breno Leitao