Linux-mtd Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/9] Add __must_init and require explicit kobj_type::release
@ 2026-10-27 22:38 Ian Rogers
  2026-10-27 22:38 ` [PATCH v2 1/9] Compiler Attributes: Add __must_init macro Ian Rogers
                   ` (8 more replies)
  0 siblings, 9 replies; 13+ messages in thread
From: Ian Rogers @ 2026-10-27 22:38 UTC (permalink / raw)
  To: Kees Cook, Greg Kroah-Hartman, Miguel Ojeda, Rafael J . Wysocki,
	Danilo Krummrich
  Cc: Nathan Chancellor, Nick Desaulniers, Miguel Ojeda,
	Christian König, Zhihao Cheng, Zhongqiu Han,
	Sumanth Korikkar, Bill Wendling, Justin Stitt, driver-core, llvm,
	linux-hardening, linux-fsdevel, linux-doc, linux-acpi, linux-pm,
	linuxppc-dev, linux-sh, linux-s390, gfs2, xen-devel, linux-mtd,
	amd-gfx, dri-devel, linux-kernel, Ian Rogers

Clang supports the 'require_explicit_initialization' attribute on struct
fields to enforce that the field is explicitly initialized when an
aggregate object is constructed, emitting -Wuninitialized-explicit-init
(enabled by default) if the field is omitted.

Following discussion at the Linux Plumbers Conference [1], patch 1 adds
the attribute to include/linux/compiler_attributes.h as __must_init. In
v1 it was called __require_explicit_initialization. Kees picked up that
patch with a first seq_file user [2], and in that thread Greg suggested
the shorter __must_init spelling, which Kees and Miguel agreed to. As
the attribute did not land in the v7.4 merge window, Kees asked that
this series carry the renamed attribute. The Acked-by/Reviewed-by tags
on patch 1 were given for the original spelling; the rename is
mechanical.

As Documentation/core-api/kobject.rst notes:
  "One important point cannot be overstated: every kobject must have a
  release() method, and the kobject must persist (in a consistent state)
  until that method is called. If these constraints are not met, the
  code is flawed."

Annotating struct kobj_type::release caught struct kobj_type definitions
across the tree that omitted .release:
- Patches 2-8 fix struct kobj_type definitions where dynamically
  allocated kobjects, ksets, or enclosing structures were either leaked
  on kobject_put(), freed prematurely before kobject release, or missing
  proper static initializers.
- Patch 9 annotates struct kobj_type::release with __must_init and
  explicitly sets .release = NULL (with explanatory comments prefixed
  with "Pre-existing:") on the remaining legacy struct kobj_type
  definitions whose kobjects are static, per-CPU, permanent firmware
  structures, or embedded in devm- or parent-managed structures.

Note on tool use: An LLM coding assistant was used to help audit the
compiler diagnostics across the tree, draft the fixes and changelog
descriptions, and verify builds and review feedback.

Changes in v2:
- Rebased on v7.3-16928-g83f32c773255 (v7.4 merge window).
- Patch 1: Rename __require_explicit_initialization to __must_init per
  Greg Kroah-Hartman; document the Clang >= 20 requirement per Miguel
  Ojeda; note the Clang gap for file-scope objects without an
  initializer reported by Kees Cook; add tags from v1 and from Kees's
  posting.
- Move LLM assistance attribution from Assisted-by tags to this cover
  letter per commit 1e035297ffda ("docs: remove Assisted-by
  references").
- Patch 4 (cpufreq): Use "cpufreq: governor:" prefix, drop Fixes tag,
  fix typo, and remove the redundant runtime assignment in
  cpufreq_dbs_governor_init() per Zhongqiu Han.
- Dropped v1 patch 5 (ACPI: CPPC), already fixed upstream by
  commit 27954e29d7de ("ACPI: CPPC: Release CPC descriptors through
  kobject").
- Patch 5 (dlm): Call kobject_del() before dlm_recoverd_stop() in
  release_lockspace() and the new_lockspace() error path, and wait on a
  new ls_kobj_done completion before freeing the lockspace or dropping
  the module reference, avoiding races with delayed kobject release.
- Dropped v1 patch 8 (s390/sclp_mem) per Sumanth Korikkar: the
  /sys/firmware/memory/memoryX kobjects are permanent, so sclp_mem.c is
  folded into patch 9 with .release = NULL.
- Patch 7 (ubifs): Add Tested-by and Reviewed-by from Zhihao Cheng.
- Patch 8 (drm/amdkfd): Check q->kobj.state_in_sysfs before
  kobject_del() in kfd_procfs_del_queue().
- Patch 9 (kobject): Cover sclp_mem.c and the new amdgpu_ualink.c
  ualink_xcp_info_ktype, fix the overlay-sysfs.c comment, and prefix
  legacy .release = NULL comments with "Pre-existing:".
- Patch 9 (kobject): The ioat, kunpeng_hccs and omapfb display comments
  now say that the existing teardown can use-after-free under
  CONFIG_DEBUG_KOBJECT_RELEASE (reported by Sashiko). Fixing those
  drivers is left to follow-up patches.

v1: https://lore.kernel.org/all/20261013223946.1836757-1-irogers@google.com/
[1] https://lpc.events/event/20/contributions/2392/
[2] https://lore.kernel.org/lkml/20261014225811.i.852-kees@kernel.org/

Ian Rogers (9):
  Compiler Attributes: Add __must_init macro
  powerpc/secvar: Add missing kobject release callback to secvar_ktype
  sh: sq: Add missing kobject release callback to ktype_percpu_entry
  cpufreq: governor: Initialize kobj_type release callback statically
  dlm: Free dlm_ls in kobject release callback
  xen/sys-hypervisor: Add release callback to hyp_sysfs_kobj_type
  ubifs: sysfs: Use kset_create_and_add() for ubifs_kset
  drm/amdkfd: Free queue in procfs_queue_type kobject release callback
  kobject: Require explicit initialization of struct kobj_type::release

 Documentation/conf.py                         |  1 +
 arch/arm64/kernel/cpuinfo.c                   |  5 ++++
 arch/powerpc/kernel/secvar-sysfs.c            |  6 +++++
 arch/sh/kernel/cpu/sh4/sq.c                   |  6 +++++
 drivers/acpi/sysfs.c                          |  2 ++
 drivers/cpufreq/cpufreq_conservative.c        |  5 +++-
 drivers/cpufreq/cpufreq_governor.c            |  4 +--
 drivers/cpufreq/cpufreq_governor.h            |  1 +
 drivers/cpufreq/cpufreq_ondemand.c            |  5 +++-
 drivers/dma/ioat/sysfs.c                      |  7 +++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c    |  5 ++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c       | 10 +++++++
 drivers/gpu/drm/amd/amdkfd/kfd_process.c      | 12 ++++++---
 drivers/gpu/drm/amd/amdkfd/kfd_queue.c        |  5 +++-
 drivers/infiniband/hw/hfi1/sysfs.c            |  5 ++++
 drivers/infiniband/hw/usnic/usnic_ib_sysfs.c  |  2 ++
 drivers/parisc/pdc_stable.c                   |  5 ++++
 drivers/power/supply/ab8500_fg.c              |  5 ++++
 drivers/s390/char/sclp_mem.c                  |  2 ++
 drivers/soc/hisilicon/kunpeng_hccs.c          | 21 +++++++++++++++
 .../fbdev/omap2/omapfb/dss/display-sysfs.c    |  7 +++++
 .../fbdev/omap2/omapfb/dss/manager-sysfs.c    |  5 ++++
 .../fbdev/omap2/omapfb/dss/overlay-sysfs.c    |  5 ++++
 drivers/xen/sys-hypervisor.c                  |  6 +++++
 fs/dlm/dlm_internal.h                         |  1 +
 fs/dlm/lockspace.c                            | 26 ++++++++++++++-----
 fs/erofs/sysfs.c                              | 10 +++++++
 fs/f2fs/sysfs.c                               | 15 +++++++++++
 fs/ocfs2/cluster/masklog.c                    |  5 ++++
 fs/ubifs/sysfs.c                              | 24 +++++------------
 include/linux/compiler_attributes.h           | 12 +++++++++
 include/linux/kobject.h                       |  2 +-
 scripts/checkpatch.pl                         |  1 +
 tools/lib/python/kdoc/xforms_lists.py         |  1 +
 34 files changed, 202 insertions(+), 32 deletions(-)


base-commit: 83f32c773255720a661aa45d83e36278135f23f5
-- 
2.56.0.313.g2479322e68-goog


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v2 1/9] Compiler Attributes: Add __must_init macro
  2026-10-27 22:38 [PATCH v2 0/9] Add __must_init and require explicit kobj_type::release Ian Rogers
@ 2026-10-27 22:38 ` Ian Rogers
  2026-10-27 22:38 ` [PATCH v2 2/9] powerpc/secvar: Add missing kobject release callback to secvar_ktype Ian Rogers
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Ian Rogers @ 2026-10-27 22:38 UTC (permalink / raw)
  To: Kees Cook, Greg Kroah-Hartman, Miguel Ojeda, Rafael J . Wysocki,
	Danilo Krummrich
  Cc: Nathan Chancellor, Nick Desaulniers, Miguel Ojeda,
	Christian König, Zhihao Cheng, Zhongqiu Han,
	Sumanth Korikkar, Bill Wendling, Justin Stitt, driver-core, llvm,
	linux-hardening, linux-fsdevel, linux-doc, linux-acpi, linux-pm,
	linuxppc-dev, linux-sh, linux-s390, gfs2, xen-devel, linux-mtd,
	amd-gfx, dri-devel, linux-kernel, Ian Rogers, Jonathan Corbet,
	Shuah Khan, Randy Dunlap, Andy Whitcroft, Joe Perches

Clang supports the 'require_explicit_initialization' attribute on struct
fields to indicate that a field must be initialized explicitly by the
user when the object is constructed. When an aggregate initializer or
uninitialized variable omits an annotated field, Clang emits a
-Wuninitialized-explicit-init warning (enabled by default).

Add the __must_init macro to include/linux/compiler_attributes.h (which
is included by include/linux/compiler_types.h and
include/linux/compiler.h) so kernel structs with error-prone
initialization (such as mandatory callbacks or cleanup handlers) can
enforce explicit initialization at compile time, as discussed at the
Linux Plumbers Conference. The shorter __must_init spelling, rather than
the attribute's full name, keeps annotated struct members readable and
was suggested by Greg Kroah-Hartman.

Note that Clang does not yet diagnose file-scope objects declared
without any initializer (initializers at file scope that omit the field
are diagnosed), see https://github.com/llvm/llvm-project/issues/232483.

Also teach Sphinx (Documentation/conf.py), kernel-doc
(tools/lib/python/kdoc/xforms_lists.py), and checkpatch.pl about the new
attribute macro.

Link: https://lpc.events/event/20/contributions/2392/
Link: https://lore.kernel.org/lkml/2026101532-fantastic-deafness-e04c@gregkh/
Acked-by: Miguel Ojeda <ojeda@kernel.org>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Nathan Chancellor <nathan@kernel.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Ian Rogers <irogers@google.com>
---
 Documentation/conf.py                 |  1 +
 include/linux/compiler_attributes.h   | 12 ++++++++++++
 scripts/checkpatch.pl                 |  1 +
 tools/lib/python/kdoc/xforms_lists.py |  1 +
 4 files changed, 15 insertions(+)

diff --git a/Documentation/conf.py b/Documentation/conf.py
index 5ab26ce89daf..baaa4035258c 100644
--- a/Documentation/conf.py
+++ b/Documentation/conf.py
@@ -203,6 +203,7 @@ c_id_attributes = [
     "__noreturn",
     "__packed",
     "__pure",
+    "__must_init",
     "__section",
     "__always_unused",
     "__maybe_unused",
diff --git a/include/linux/compiler_attributes.h b/include/linux/compiler_attributes.h
index 476c4c560d17..b9c0b56dd22e 100644
--- a/include/linux/compiler_attributes.h
+++ b/include/linux/compiler_attributes.h
@@ -322,6 +322,18 @@
  */
 #define __pure                          __attribute__((__pure__))
 
+/*
+ * Optional: not supported by gcc
+ * Optional: only supported since clang >= 20.0
+ *
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#require-explicit-initialization
+ */
+#if __has_attribute(__require_explicit_initialization__)
+# define __must_init __attribute__((__require_explicit_initialization__))
+#else
+# define __must_init
+#endif
+
 /*
  *   gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-section-function-attribute
  *   gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-section-variable-attribute
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index c9840f5219c2..5232f66d2b80 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -6860,6 +6860,7 @@ sub process {
 				"noreturn"			=> "__noreturn",
 				"packed"			=> "__packed",
 				"pure"				=> "__pure",
+				"require_explicit_initialization" => "__must_init",
 				"section"			=> "__section",
 				"used"				=> "__used",
 				"weak"				=> "__weak"
diff --git a/tools/lib/python/kdoc/xforms_lists.py b/tools/lib/python/kdoc/xforms_lists.py
index 320f977c5bac..3c744cbd2f34 100644
--- a/tools/lib/python/kdoc/xforms_lists.py
+++ b/tools/lib/python/kdoc/xforms_lists.py
@@ -36,6 +36,7 @@ class CTransforms:
         (CMatch("CRYPTO_MINALIGN_ATTR"), ""),
         (CMatch("__private"), ""),
         (CMatch("__rcu"), ""),
+        (CMatch("__must_init"), ""),
         (CMatch("____cacheline_aligned_in_smp"), ""),
         (CMatch("____cacheline_aligned"), ""),
         (CMatch("__cacheline_group_(?:begin|end)"), ""),
-- 
2.56.0.313.g2479322e68-goog


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 2/9] powerpc/secvar: Add missing kobject release callback to secvar_ktype
  2026-10-27 22:38 [PATCH v2 0/9] Add __must_init and require explicit kobj_type::release Ian Rogers
  2026-10-27 22:38 ` [PATCH v2 1/9] Compiler Attributes: Add __must_init macro Ian Rogers
@ 2026-10-27 22:38 ` Ian Rogers
  2026-10-27 22:38 ` [PATCH v2 3/9] sh: sq: Add missing kobject release callback to ktype_percpu_entry Ian Rogers
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Ian Rogers @ 2026-10-27 22:38 UTC (permalink / raw)
  To: Kees Cook, Greg Kroah-Hartman, Miguel Ojeda, Rafael J . Wysocki,
	Danilo Krummrich
  Cc: Nathan Chancellor, Nick Desaulniers, Miguel Ojeda,
	Christian König, Zhihao Cheng, Zhongqiu Han,
	Sumanth Korikkar, Bill Wendling, Justin Stitt, driver-core, llvm,
	linux-hardening, linux-fsdevel, linux-doc, linux-acpi, linux-pm,
	linuxppc-dev, linux-sh, linux-s390, gfs2, xen-devel, linux-mtd,
	amd-gfx, dri-devel, linux-kernel, Ian Rogers, Madhavan Srinivasan,
	Michael Ellerman, Nicholas Piggin, Christophe Leroy (CS GROUP),
	Ritesh Harjani (IBM), Shrikanth Hegde, Nayna Jain, Eric Richter

In add_var(), a struct kobject is dynamically allocated with
kzalloc_obj() and initialized with secvar_ktype. If kobject_add() or
sysfs_create_file() fails, kobject_put(kobj) is called to clean up.
However, secvar_ktype does not define a .release callback, which results
in a memory leak of kobj (and a pr_debug warning in kobject_cleanup()
when CONFIG_DEBUG_KOBJECT_RELEASE is enabled).

Provide a secvar_release() callback that calls kfree(kobj).

Fixes: bd5d9c743d38 ("powerpc: expose secure variables to userspace via sysfs")
Signed-off-by: Ian Rogers <irogers@google.com>
---
 arch/powerpc/kernel/secvar-sysfs.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/powerpc/kernel/secvar-sysfs.c b/arch/powerpc/kernel/secvar-sysfs.c
index 395399bbab2c..f3f6ac25ea78 100644
--- a/arch/powerpc/kernel/secvar-sysfs.c
+++ b/arch/powerpc/kernel/secvar-sysfs.c
@@ -126,7 +126,13 @@ static const struct attribute_group secvar_attr_group = {
 };
 __ATTRIBUTE_GROUPS(secvar_attr);
 
+static void secvar_release(struct kobject *kobj)
+{
+	kfree(kobj);
+}
+
 static const struct kobj_type secvar_ktype = {
+	.release	= secvar_release,
 	.sysfs_ops	= &kobj_sysfs_ops,
 	.default_groups = secvar_attr_groups,
 };
-- 
2.56.0.313.g2479322e68-goog


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 3/9] sh: sq: Add missing kobject release callback to ktype_percpu_entry
  2026-10-27 22:38 [PATCH v2 0/9] Add __must_init and require explicit kobj_type::release Ian Rogers
  2026-10-27 22:38 ` [PATCH v2 1/9] Compiler Attributes: Add __must_init macro Ian Rogers
  2026-10-27 22:38 ` [PATCH v2 2/9] powerpc/secvar: Add missing kobject release callback to secvar_ktype Ian Rogers
@ 2026-10-27 22:38 ` Ian Rogers
  2026-10-27 22:38 ` [PATCH v2 4/9] cpufreq: governor: Initialize kobj_type release callback statically Ian Rogers
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Ian Rogers @ 2026-10-27 22:38 UTC (permalink / raw)
  To: Kees Cook, Greg Kroah-Hartman, Miguel Ojeda, Rafael J . Wysocki,
	Danilo Krummrich
  Cc: Nathan Chancellor, Nick Desaulniers, Miguel Ojeda,
	Christian König, Zhihao Cheng, Zhongqiu Han,
	Sumanth Korikkar, Bill Wendling, Justin Stitt, driver-core, llvm,
	linux-hardening, linux-fsdevel, linux-doc, linux-acpi, linux-pm,
	linuxppc-dev, linux-sh, linux-s390, gfs2, xen-devel, linux-mtd,
	amd-gfx, dri-devel, linux-kernel, Ian Rogers, Yoshinori Sato,
	Rich Felker, John Paul Adrian Glaubitz, Paul Mundt

In sq_dev_add(), sq_kobject[cpu] is dynamically allocated with
kzalloc_obj() and initialized with ktype_percpu_entry. When
sq_dev_remove() calls kobject_put(kobj), the kobject is never freed
because ktype_percpu_entry lacks a .release callback.

Provide a sq_kobj_release() callback that calls kfree(kobj).

Fixes: d7c30c682a27 ("sh: Store Queue API rework.")
Signed-off-by: Ian Rogers <irogers@google.com>
---
 arch/sh/kernel/cpu/sh4/sq.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c
index 908a8e09113b..f33864958487 100644
--- a/arch/sh/kernel/cpu/sh4/sq.c
+++ b/arch/sh/kernel/cpu/sh4/sq.c
@@ -331,7 +331,13 @@ static const struct sysfs_ops sq_sysfs_ops = {
 	.store	= sq_sysfs_store,
 };
 
+static void sq_kobj_release(struct kobject *kobj)
+{
+	kfree(kobj);
+}
+
 static struct kobj_type ktype_percpu_entry = {
+	.release	= sq_kobj_release,
 	.sysfs_ops	= &sq_sysfs_ops,
 	.default_groups	= sq_sysfs_groups,
 };
-- 
2.56.0.313.g2479322e68-goog


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 4/9] cpufreq: governor: Initialize kobj_type release callback statically
  2026-10-27 22:38 [PATCH v2 0/9] Add __must_init and require explicit kobj_type::release Ian Rogers
                   ` (2 preceding siblings ...)
  2026-10-27 22:38 ` [PATCH v2 3/9] sh: sq: Add missing kobject release callback to ktype_percpu_entry Ian Rogers
@ 2026-10-27 22:38 ` Ian Rogers
  2026-10-28  3:36   ` Zhongqiu Han
  2026-10-27 22:38 ` [PATCH v2 5/9] dlm: Free dlm_ls in kobject release callback Ian Rogers
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 13+ messages in thread
From: Ian Rogers @ 2026-10-27 22:38 UTC (permalink / raw)
  To: Kees Cook, Greg Kroah-Hartman, Miguel Ojeda, Rafael J . Wysocki,
	Danilo Krummrich
  Cc: Nathan Chancellor, Nick Desaulniers, Miguel Ojeda,
	Christian König, Zhihao Cheng, Zhongqiu Han,
	Sumanth Korikkar, Bill Wendling, Justin Stitt, driver-core, llvm,
	linux-hardening, linux-fsdevel, linux-doc, linux-acpi, linux-pm,
	linuxppc-dev, linux-sh, linux-s390, gfs2, xen-devel, linux-mtd,
	amd-gfx, dri-devel, linux-kernel, Ian Rogers, Viresh Kumar

Export cpufreq_dbs_data_release() and set .kobj_type.release statically
in the ondemand and conservative governors so their gov_attr_set
kobjects have a valid release callback statically initialized, matching
cpufreq_governor_dbs. Remove the redundant runtime assignment in
cpufreq_dbs_governor_init().

This prepares for annotating struct kobj_type::release with
__must_init.

Signed-off-by: Ian Rogers <irogers@google.com>
---
 drivers/cpufreq/cpufreq_conservative.c | 5 ++++-
 drivers/cpufreq/cpufreq_governor.c     | 4 ++--
 drivers/cpufreq/cpufreq_governor.h     | 1 +
 drivers/cpufreq/cpufreq_ondemand.c     | 5 ++++-
 4 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 02bfd46543e9..146a2353b1a2 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -318,7 +318,10 @@ static void cs_limits(struct cpufreq_policy *policy)
 
 static struct dbs_governor cs_governor = {
 	.gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("conservative"),
-	.kobj_type = { .default_groups = cs_groups },
+	.kobj_type = {
+		.release = cpufreq_dbs_data_release,
+		.default_groups = cs_groups,
+	},
 	.gov_dbs_update = cs_dbs_update,
 	.alloc = cs_alloc,
 	.free = cs_free,
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
index f3bd3dbe7c41..f8b5aca09b6b 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -419,7 +419,7 @@ static void free_policy_dbs_info(struct policy_dbs_info *policy_dbs,
 	gov->free(policy_dbs);
 }
 
-static void cpufreq_dbs_data_release(struct kobject *kobj)
+void cpufreq_dbs_data_release(struct kobject *kobj)
 {
 	struct dbs_data *dbs_data = to_dbs_data(to_gov_attr_set(kobj));
 	struct dbs_governor *gov = dbs_data->gov;
@@ -427,6 +427,7 @@ static void cpufreq_dbs_data_release(struct kobject *kobj)
 	gov->exit(dbs_data);
 	kfree(dbs_data);
 }
+EXPORT_SYMBOL_GPL(cpufreq_dbs_data_release);
 
 int cpufreq_dbs_governor_init(struct cpufreq_policy *policy)
 {
@@ -488,7 +489,6 @@ int cpufreq_dbs_governor_init(struct cpufreq_policy *policy)
 	policy->governor_data = policy_dbs;
 
 	gov->kobj_type.sysfs_ops = &governor_sysfs_ops;
-	gov->kobj_type.release = cpufreq_dbs_data_release;
 	ret = kobject_init_and_add(&dbs_data->attr_set.kobj, &gov->kobj_type,
 				   get_governor_parent_kobj(policy),
 				   "%s", gov->gov.name);
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h
index 806d8fb4dff1..1026712bb79b 100644
--- a/drivers/cpufreq/cpufreq_governor.h
+++ b/drivers/cpufreq/cpufreq_governor.h
@@ -150,6 +150,7 @@ static inline struct dbs_governor *dbs_governor_of(struct cpufreq_policy *policy
 }
 
 /* Governor callback routines */
+void cpufreq_dbs_data_release(struct kobject *kobj);
 int cpufreq_dbs_governor_init(struct cpufreq_policy *policy);
 void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy);
 int cpufreq_dbs_governor_start(struct cpufreq_policy *policy);
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 9942dbb38dae..7386d043c665 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -374,7 +374,10 @@ static struct od_ops od_ops = {
 
 static struct dbs_governor od_dbs_gov = {
 	.gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("ondemand"),
-	.kobj_type = { .default_groups = od_groups },
+	.kobj_type = {
+		.release = cpufreq_dbs_data_release,
+		.default_groups = od_groups,
+	},
 	.gov_dbs_update = od_dbs_update,
 	.alloc = od_alloc,
 	.free = od_free,
-- 
2.56.0.313.g2479322e68-goog


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 5/9] dlm: Free dlm_ls in kobject release callback
  2026-10-27 22:38 [PATCH v2 0/9] Add __must_init and require explicit kobj_type::release Ian Rogers
                   ` (3 preceding siblings ...)
  2026-10-27 22:38 ` [PATCH v2 4/9] cpufreq: governor: Initialize kobj_type release callback statically Ian Rogers
@ 2026-10-27 22:38 ` Ian Rogers
  2026-10-27 22:38 ` [PATCH v2 6/9] xen/sys-hypervisor: Add release callback to hyp_sysfs_kobj_type Ian Rogers
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Ian Rogers @ 2026-10-27 22:38 UTC (permalink / raw)
  To: Kees Cook, Greg Kroah-Hartman, Miguel Ojeda, Rafael J . Wysocki,
	Danilo Krummrich
  Cc: Nathan Chancellor, Nick Desaulniers, Miguel Ojeda,
	Christian König, Zhihao Cheng, Zhongqiu Han,
	Sumanth Korikkar, Bill Wendling, Justin Stitt, driver-core, llvm,
	linux-hardening, linux-fsdevel, linux-doc, linux-acpi, linux-pm,
	linuxppc-dev, linux-sh, linux-s390, gfs2, xen-devel, linux-mtd,
	amd-gfx, dri-devel, linux-kernel, Ian Rogers, Alexander Aring,
	David Teigland, Greg Kroah-Hartman

struct dlm_ls embeds a struct kobject (ls_kobj), but dlm_ktype lacked a
.release callback and dlm freed the lockspace structure directly via
kfree(ls). With CONFIG_DEBUG_KOBJECT_RELEASE=y, freeing ls before the
delayed kobject release runs causes a use-after-free, and unloading the
module while the delayed release is pending results in an instruction
page fault.

Add a completion ls_kobj_done and dlm_ls_release() to complete it when
the last kobject reference is dropped, waiting for it in free_lockspace()
before kfree(ls) and in the new_lockspace() error path before module_put().
Also delete the kobject via kobject_del() before stopping dlm_recoverd
to close the window where concurrent sysfs writes could wake the stopped
recovery task.

Fixes: 3514faca19a6 ("kobject: remove struct kobj_type from struct kset")
Signed-off-by: Ian Rogers <irogers@google.com>
---
 fs/dlm/dlm_internal.h |  1 +
 fs/dlm/lockspace.c    | 26 ++++++++++++++++++++------
 2 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
index 74c2e77d1b55..95b3bff0cb57 100644
--- a/fs/dlm/dlm_internal.h
+++ b/fs/dlm/dlm_internal.h
@@ -576,6 +576,7 @@ struct dlm_ls {
 	int			ls_create_count; /* create/release refcount */
 	unsigned long		ls_flags;	/* LSFL_ */
 	struct kobject		ls_kobj;
+	struct completion	ls_kobj_done;
 
 	struct xarray		ls_lkbxa;
 	rwlock_t		ls_lkbxa_lock;
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index a9c98b4f378f..2dccd080a10f 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -179,7 +179,15 @@ static const struct sysfs_ops dlm_attr_ops = {
 	.store = dlm_attr_store,
 };
 
+static void dlm_ls_release(struct kobject *kobj)
+{
+	struct dlm_ls *ls = container_of(kobj, struct dlm_ls, ls_kobj);
+
+	complete(&ls->ls_kobj_done);
+}
+
 static struct kobj_type dlm_ktype = {
+	.release        = dlm_ls_release,
 	.default_groups = dlm_groups,
 	.sysfs_ops     = &dlm_attr_ops,
 };
@@ -355,6 +363,8 @@ static void free_lockspace(struct work_struct *work)
 	 */
 	rhashtable_free_and_destroy(&ls->ls_rsbtbl, rhash_free_rsb, NULL);
 
+	kobject_put(&ls->ls_kobj);
+	wait_for_completion(&ls->ls_kobj_done);
 	kfree(ls);
 }
 
@@ -435,7 +445,10 @@ static int new_lockspace(const char *name, const char *cluster,
 	ls->ls_lvblen = lvblen;
 	atomic_set(&ls->ls_count, 0);
 	init_waitqueue_head(&ls->ls_count_wait);
+	init_completion(&ls->ls_kobj_done);
 	ls->ls_flags = 0;
+	ls->ls_kobj.kset = dlm_kset;
+	kobject_init(&ls->ls_kobj, &dlm_ktype);
 
 	if (ops && dlm_config.ci_recover_callbacks) {
 		ls->ls_ops = ops;
@@ -567,9 +580,7 @@ static int new_lockspace(const char *name, const char *cluster,
 	wait_event(ls->ls_recover_lock_wait,
 		   test_bit(LSFL_RECOVER_LOCK, &ls->ls_flags));
 
-	ls->ls_kobj.kset = dlm_kset;
-	error = kobject_init_and_add(&ls->ls_kobj, &dlm_ktype, NULL,
-				     "%s", ls->ls_name);
+	error = kobject_add(&ls->ls_kobj, NULL, "%s", ls->ls_name);
 	if (error)
 		goto out_recoverd;
 	kobject_uevent(&ls->ls_kobj, KOBJ_ADD);
@@ -582,7 +593,7 @@ static int new_lockspace(const char *name, const char *cluster,
 
 	error = do_uevent(ls, 1, 0);
 	if (error < 0)
-		goto out_recoverd;
+		goto out_kobj;
 
 	/* wait until recovery is successful or failed */
 	wait_for_completion(&ls->ls_recovery_done);
@@ -600,6 +611,8 @@ static int new_lockspace(const char *name, const char *cluster,
 	do_uevent(ls, 0, 0);
 	dlm_clear_members(ls);
 	kfree(ls->ls_node_array);
+ out_kobj:
+	kobject_del(&ls->ls_kobj);
  out_recoverd:
 	dlm_recoverd_stop(ls);
  out_callback:
@@ -615,6 +628,7 @@ static int new_lockspace(const char *name, const char *cluster,
 	rhashtable_destroy(&ls->ls_rsbtbl);
  out_lsfree:
 	kobject_put(&ls->ls_kobj);
+	wait_for_completion(&ls->ls_kobj_done);
 	kfree(ls);
  out:
 	module_put(THIS_MODULE);
@@ -740,6 +754,8 @@ static int release_lockspace(struct dlm_ls *ls, unsigned int release_option)
 	    dlm_user_daemon_available())
 		do_uevent(ls, 0, (release_option == DLM_RELEASE_RECOVER));
 
+	kobject_del(&ls->ls_kobj);
+
 	dlm_recoverd_stop(ls);
 
 	/* clear the LSFL_RUNNING flag to fast up
@@ -759,8 +775,6 @@ static int release_lockspace(struct dlm_ls *ls, unsigned int release_option)
 
 	dlm_delete_debug_file(ls);
 
-	kobject_put(&ls->ls_kobj);
-
 	xa_destroy(&ls->ls_recover_xa);
 	kfree(ls->ls_recover_buf);
 
-- 
2.56.0.313.g2479322e68-goog


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 6/9] xen/sys-hypervisor: Add release callback to hyp_sysfs_kobj_type
  2026-10-27 22:38 [PATCH v2 0/9] Add __must_init and require explicit kobj_type::release Ian Rogers
                   ` (4 preceding siblings ...)
  2026-10-27 22:38 ` [PATCH v2 5/9] dlm: Free dlm_ls in kobject release callback Ian Rogers
@ 2026-10-27 22:38 ` Ian Rogers
  2026-10-27 22:38 ` [PATCH v2 7/9] ubifs: sysfs: Use kset_create_and_add() for ubifs_kset Ian Rogers
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 13+ messages in thread
From: Ian Rogers @ 2026-10-27 22:38 UTC (permalink / raw)
  To: Kees Cook, Greg Kroah-Hartman, Miguel Ojeda, Rafael J . Wysocki,
	Danilo Krummrich
  Cc: Nathan Chancellor, Nick Desaulniers, Miguel Ojeda,
	Christian König, Zhihao Cheng, Zhongqiu Han,
	Sumanth Korikkar, Bill Wendling, Justin Stitt, driver-core, llvm,
	linux-hardening, linux-fsdevel, linux-doc, linux-acpi, linux-pm,
	linuxppc-dev, linux-sh, linux-s390, gfs2, xen-devel, linux-mtd,
	amd-gfx, dri-devel, linux-kernel, Ian Rogers, Juergen Gross,
	Stefano Stabellini, Oleksandr Tyshchenko, Jeremy Fitzhardinge

hypervisor_init() in drivers/base/hypervisor.c creates hypervisor_kobj
with kobject_create_and_add() (which allocates a dynamic kobject using
dynamic_kobj_ktype), and hypervisor_subsys_init() in
drivers/xen/sys-hypervisor.c then overwrites hypervisor_kobj->ktype with
&hyp_sysfs_kobj_type, which had no .release callback.

Add hyp_sysfs_release() calling kfree(kobj) to preserve the dynamic
kobject release behavior.

Fixes: cff7e81b3dd7 ("xen: add /sys/hypervisor support")
Signed-off-by: Ian Rogers <irogers@google.com>
---
 drivers/xen/sys-hypervisor.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/xen/sys-hypervisor.c b/drivers/xen/sys-hypervisor.c
index 91923242a5ae..0e8a2cd69fd6 100644
--- a/drivers/xen/sys-hypervisor.c
+++ b/drivers/xen/sys-hypervisor.c
@@ -659,7 +659,13 @@ static const struct sysfs_ops hyp_sysfs_ops = {
 	.store = hyp_sysfs_store,
 };
 
+static void hyp_sysfs_release(struct kobject *kobj)
+{
+	kfree(kobj);
+}
+
 static const struct kobj_type hyp_sysfs_kobj_type = {
+	.release = hyp_sysfs_release,
 	.sysfs_ops = &hyp_sysfs_ops,
 };
 
-- 
2.56.0.313.g2479322e68-goog


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 7/9] ubifs: sysfs: Use kset_create_and_add() for ubifs_kset
  2026-10-27 22:38 [PATCH v2 0/9] Add __must_init and require explicit kobj_type::release Ian Rogers
                   ` (5 preceding siblings ...)
  2026-10-27 22:38 ` [PATCH v2 6/9] xen/sys-hypervisor: Add release callback to hyp_sysfs_kobj_type Ian Rogers
@ 2026-10-27 22:38 ` Ian Rogers
  2026-10-27 22:38 ` [PATCH v2 8/9] drm/amdkfd: Free queue in procfs_queue_type kobject release callback Ian Rogers
  2026-10-27 22:38 ` [PATCH v2 9/9] kobject: Require explicit initialization of struct kobj_type::release Ian Rogers
  8 siblings, 0 replies; 13+ messages in thread
From: Ian Rogers @ 2026-10-27 22:38 UTC (permalink / raw)
  To: Kees Cook, Greg Kroah-Hartman, Miguel Ojeda, Rafael J . Wysocki,
	Danilo Krummrich
  Cc: Nathan Chancellor, Nick Desaulniers, Miguel Ojeda,
	Christian König, Zhihao Cheng, Zhongqiu Han,
	Sumanth Korikkar, Bill Wendling, Justin Stitt, driver-core, llvm,
	linux-hardening, linux-fsdevel, linux-doc, linux-acpi, linux-pm,
	linuxppc-dev, linux-sh, linux-s390, gfs2, xen-devel, linux-mtd,
	amd-gfx, dri-devel, linux-kernel, Ian Rogers, Richard Weinberger,
	Liu Shixin

ubifs_kset was a static struct kset using a custom ubifs_ktype that
had no default_groups and no .release callback. With
CONFIG_DEBUG_KOBJECT_RELEASE=y, unloading the ubifs module while delayed
kobject release is pending causes a use-after-free on the static kset.

Replace the static ubifs_kset and empty ubifs_ktype with a dynamically
allocated kset via kset_create_and_add().

Fixes: 203a55f04f66 ("ubifs: Fix memory leak in ubifs_sysfs_init()")
Tested-by: Zhihao Cheng <chengzhihao1@huawei.com>
Reviewed-by: Zhihao Cheng <chengzhihao1@huawei.com>
Signed-off-by: Ian Rogers <irogers@google.com>
---
 fs/ubifs/sysfs.c | 24 +++++++-----------------
 1 file changed, 7 insertions(+), 17 deletions(-)

diff --git a/fs/ubifs/sysfs.c b/fs/ubifs/sysfs.c
index dbf967dcf26e..e20931e3a62f 100644
--- a/fs/ubifs/sysfs.c
+++ b/fs/ubifs/sysfs.c
@@ -80,13 +80,7 @@ static const struct kobj_type ubifs_sb_ktype = {
 	.release	= ubifs_sb_release,
 };
 
-static const struct kobj_type ubifs_ktype = {
-	.sysfs_ops	= &ubifs_attr_ops,
-};
-
-static struct kset ubifs_kset = {
-	.kobj	= {.ktype = &ubifs_ktype},
-};
+static struct kset *ubifs_kset;
 
 int ubifs_sysfs_register(struct ubifs_info *c)
 {
@@ -107,7 +101,7 @@ int ubifs_sysfs_register(struct ubifs_info *c)
 		goto out_free;
 	}
 
-	c->kobj.kset = &ubifs_kset;
+	c->kobj.kset = ubifs_kset;
 	init_completion(&c->kobj_unregister);
 
 	ret = kobject_init_and_add(&c->kobj, &ubifs_sb_ktype, NULL,
@@ -139,18 +133,14 @@ void ubifs_sysfs_unregister(struct ubifs_info *c)
 
 int __init ubifs_sysfs_init(void)
 {
-	int ret;
+	ubifs_kset = kset_create_and_add("ubifs", NULL, fs_kobj);
+	if (!ubifs_kset)
+		return -ENOMEM;
 
-	kobject_set_name(&ubifs_kset.kobj, "ubifs");
-	ubifs_kset.kobj.parent = fs_kobj;
-	ret = kset_register(&ubifs_kset);
-	if (ret)
-		kset_put(&ubifs_kset);
-
-	return ret;
+	return 0;
 }
 
 void ubifs_sysfs_exit(void)
 {
-	kset_unregister(&ubifs_kset);
+	kset_unregister(ubifs_kset);
 }
-- 
2.56.0.313.g2479322e68-goog


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 8/9] drm/amdkfd: Free queue in procfs_queue_type kobject release callback
  2026-10-27 22:38 [PATCH v2 0/9] Add __must_init and require explicit kobj_type::release Ian Rogers
                   ` (6 preceding siblings ...)
  2026-10-27 22:38 ` [PATCH v2 7/9] ubifs: sysfs: Use kset_create_and_add() for ubifs_kset Ian Rogers
@ 2026-10-27 22:38 ` Ian Rogers
  2026-10-27 23:15   ` Felix Kuehling
  2026-10-27 22:38 ` [PATCH v2 9/9] kobject: Require explicit initialization of struct kobj_type::release Ian Rogers
  8 siblings, 1 reply; 13+ messages in thread
From: Ian Rogers @ 2026-10-27 22:38 UTC (permalink / raw)
  To: Kees Cook, Greg Kroah-Hartman, Miguel Ojeda, Rafael J . Wysocki,
	Danilo Krummrich
  Cc: Nathan Chancellor, Nick Desaulniers, Miguel Ojeda,
	Christian König, Zhihao Cheng, Zhongqiu Han,
	Sumanth Korikkar, Bill Wendling, Justin Stitt, driver-core, llvm,
	linux-hardening, linux-fsdevel, linux-doc, linux-acpi, linux-pm,
	linuxppc-dev, linux-sh, linux-s390, gfs2, xen-devel, linux-mtd,
	amd-gfx, dri-devel, linux-kernel, Ian Rogers, Felix Kuehling,
	Alex Deucher, David Airlie, Simona Vetter, Amber Lin

struct queue embeds a struct kobject (q->kobj) for procfs entries, but
procfs_queue_type had no .release callback and uninit_queue() freed q
immediately after kfd_procfs_del_queue() called kobject_put(&q->kobj).
With CONFIG_DEBUG_KOBJECT_RELEASE=y, this causes a use-after-free.

Add kfd_procfs_queue_release() to free struct queue from the kobject
release callback, change kfd_procfs_del_queue() to only remove the
kobject from sysfs via kobject_del(), and drop the final reference in
uninit_queue() via kobject_put(). Check q->kobj.state_in_sysfs before
calling kobject_del() in kfd_procfs_del_queue() to avoid warnings if
sysfs creation previously failed.

Fixes: 6d220a7e7971 ("drm/amdkfd: Add queue information to sysfs")
Signed-off-by: Ian Rogers <irogers@google.com>
---
 drivers/gpu/drm/amd/amdkfd/kfd_process.c | 12 +++++++++---
 drivers/gpu/drm/amd/amdkfd/kfd_queue.c   |  5 ++++-
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index 226f52626e84..8e6136d52a50 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -512,7 +512,15 @@ static const struct sysfs_ops procfs_queue_ops = {
 	.show = kfd_procfs_queue_show,
 };
 
+static void kfd_procfs_queue_release(struct kobject *kobj)
+{
+	struct queue *q = container_of(kobj, struct queue, kobj);
+
+	kfree(q);
+}
+
 static const struct kobj_type procfs_queue_type = {
+	.release = kfd_procfs_queue_release,
 	.sysfs_ops = &procfs_queue_ops,
 	.default_groups = procfs_queue_groups,
 };
@@ -552,7 +560,6 @@ int kfd_procfs_add_queue(struct queue *q)
 	if (ret < 0) {
 		pr_warn("Creating proc/<pid>/queues/%u failed",
 			q->properties.queue_id);
-		kobject_put(&q->kobj);
 		return ret;
 	}
 
@@ -697,11 +704,10 @@ static void kfd_procfs_add_sysfs_files(struct kfd_process *p)
 
 void kfd_procfs_del_queue(struct queue *q)
 {
-	if (!q || !q->process->kobj)
+	if (!q || !q->process || !q->process->kobj || !q->kobj.state_in_sysfs)
 		return;
 
 	kobject_del(&q->kobj);
-	kobject_put(&q->kobj);
 }
 
 int kfd_process_create_wq(void)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
index ae3e7c54014a..4666110aebe0 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
@@ -83,7 +83,10 @@ int init_queue(struct queue **q, const struct queue_properties *properties)
 
 void uninit_queue(struct queue *q)
 {
-	kfree(q);
+	if (q && q->kobj.state_initialized)
+		kobject_put(&q->kobj);
+	else
+		kfree(q);
 }
 
 #if IS_ENABLED(CONFIG_HSA_AMD_SVM)
-- 
2.56.0.313.g2479322e68-goog


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v2 9/9] kobject: Require explicit initialization of struct kobj_type::release
  2026-10-27 22:38 [PATCH v2 0/9] Add __must_init and require explicit kobj_type::release Ian Rogers
                   ` (7 preceding siblings ...)
  2026-10-27 22:38 ` [PATCH v2 8/9] drm/amdkfd: Free queue in procfs_queue_type kobject release callback Ian Rogers
@ 2026-10-27 22:38 ` Ian Rogers
  2026-10-27 22:56   ` sashiko-bot
  8 siblings, 1 reply; 13+ messages in thread
From: Ian Rogers @ 2026-10-27 22:38 UTC (permalink / raw)
  To: Kees Cook, Greg Kroah-Hartman, Miguel Ojeda, Rafael J . Wysocki,
	Danilo Krummrich
  Cc: Nathan Chancellor, Nick Desaulniers, Miguel Ojeda,
	Christian König, Zhihao Cheng, Zhongqiu Han,
	Sumanth Korikkar, Bill Wendling, Justin Stitt, driver-core, llvm,
	linux-hardening, linux-fsdevel, linux-doc, linux-acpi, linux-pm,
	linuxppc-dev, linux-sh, linux-s390, gfs2, xen-devel, linux-mtd,
	amd-gfx, dri-devel, linux-kernel, Ian Rogers, Catalin Marinas,
	Will Deacon, Mark Rutland, Len Brown, Vinod Koul, Frank Li,
	Alex Deucher, David Airlie, Simona Vetter, Dennis Dalessandro,
	Jason Gunthorpe, Leon Romanovsky, Nelson Escobar, Satish Kharat,
	James E.J. Bottomley, Helge Deller, Linus Walleij,
	Sebastian Reichel, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Huisong Li, Gao Xiang, Chao Yu, Yue Hu, Jingbo Xu,
	Sandeep Dhavale, Hongbo Li, Chunhai Guo, Jaegeuk Kim, Mark Fasheh,
	Joel Becker, Joseph Qi, Heming Zhao, Johan Hovold,
	linux-arm-kernel, dmaengine, linux-rdma, linux-parisc, linux-omap,
	linux-fbdev, linux-erofs, linux-f2fs-devel, ocfs2-devel

Documentation/core-api/kobject.rst states:

  "One important point cannot be overstated: every kobject must have a
  release() method, and the kobject must persist (in a consistent state)
  until that method is called. If these constraints are not met, the code
  is flawed. Note that the kernel will warn you if you forget to provide
  a release() method. Do not try to get rid of this warning by providing
  an \"empty\" release function."

Annotate struct kobj_type::release with __must_init
so the compiler diagnoses any struct kobj_type initializer that omits
.release.

For the remaining legacy struct kobj_type definitions where the kobject
is static, per-CPU, permanent firmware structures, or embedded inside a
devm- or parent-managed structure rather than freed by kobject_put(),
explicitly initialize .release = NULL with a comment documenting why no
release callback is provided.

Where the existing teardown is not safe with CONFIG_DEBUG_KOBJECT_RELEASE,
because the kobject's memory can be freed or cleared while the delayed
kobject cleanup is still pending (ioat, kunpeng_hccs and omapfb display),
the comment says so. Fixing those is left to follow-up patches; this
change does not alter their behavior.

Link: https://lpc.events/event/20/contributions/2392/
Signed-off-by: Ian Rogers <irogers@google.com>
---
 arch/arm64/kernel/cpuinfo.c                   |  5 +++++
 drivers/acpi/sysfs.c                          |  2 ++
 drivers/dma/ioat/sysfs.c                      |  7 +++++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c    |  5 +++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c       | 10 +++++++++
 drivers/infiniband/hw/hfi1/sysfs.c            |  5 +++++
 drivers/infiniband/hw/usnic/usnic_ib_sysfs.c  |  2 ++
 drivers/parisc/pdc_stable.c                   |  5 +++++
 drivers/power/supply/ab8500_fg.c              |  5 +++++
 drivers/s390/char/sclp_mem.c                  |  2 ++
 drivers/soc/hisilicon/kunpeng_hccs.c          | 21 +++++++++++++++++++
 .../fbdev/omap2/omapfb/dss/display-sysfs.c    |  7 +++++++
 .../fbdev/omap2/omapfb/dss/manager-sysfs.c    |  5 +++++
 .../fbdev/omap2/omapfb/dss/overlay-sysfs.c    |  5 +++++
 fs/erofs/sysfs.c                              | 10 +++++++++
 fs/f2fs/sysfs.c                               | 15 +++++++++++++
 fs/ocfs2/cluster/masklog.c                    |  5 +++++
 include/linux/kobject.h                       |  2 +-
 18 files changed, 117 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 94e6cd211d70..7a4ac8dd0b86 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -295,6 +295,11 @@ const struct seq_operations cpuinfo_op = {
 
 
 static const struct kobj_type cpuregs_kobj_type = {
+	/*
+	 * Pre-existing: info->kobj is embedded in per-CPU cpu_data;
+	 * cpuid_cpu_offline() only calls kobject_del().
+	 */
+	.release = NULL,
 	.sysfs_ops = &kobj_sysfs_ops,
 };
 
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index a99373547126..1948b80e8a4a 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -973,6 +973,8 @@ static struct attribute *hotplug_profile_attrs[] = {
 ATTRIBUTE_GROUPS(hotplug_profile);
 
 static const struct kobj_type acpi_hotplug_profile_ktype = {
+	/* Pre-existing: hotplug->kobj is embedded in static struct acpi_scan_hotplug objects. */
+	.release = NULL,
 	.sysfs_ops = &kobj_sysfs_ops,
 	.default_groups = hotplug_profile_groups,
 };
diff --git a/drivers/dma/ioat/sysfs.c b/drivers/dma/ioat/sysfs.c
index e796ddb5383f..5ba44876eb96 100644
--- a/drivers/dma/ioat/sysfs.c
+++ b/drivers/dma/ioat/sysfs.c
@@ -167,6 +167,13 @@ static const struct attribute *const ioat_attrs[] = {
 ATTRIBUTE_GROUPS(ioat);
 
 const struct kobj_type ioat_ktype = {
+	/*
+	 * Pre-existing: ioatdma_chan is freed by release_ioatdma(), not
+	 * by kobject_put(). With CONFIG_DEBUG_KOBJECT_RELEASE the delayed
+	 * kobject cleanup queued by ioat_kobject_del() may run after
+	 * that kfree(), a use-after-free.
+	 */
+	.release = NULL,
 	.sysfs_ops = &ioat_sysfs_ops,
 	.default_groups = ioat_groups,
 };
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
index 17888cf54447..c2cccd924b03 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
@@ -885,6 +885,11 @@ static const struct attribute_group ualink_xcp_info_group = {
 };
 
 static const struct kobj_type ualink_xcp_info_ktype = {
+	/*
+	 * Pre-existing: xcp->ualink.kobj is embedded in struct amdgpu_xcp_mgr
+	 * rather than freed individually by kobject_put().
+	 */
+	.release = NULL,
 	.sysfs_ops = &kobj_sysfs_ops
 };
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
index ab14079d1c42..0847134a1391 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
@@ -797,6 +797,11 @@ static const struct sysfs_ops xcp_cfg_res_sysfs_ops = {
 };
 
 static const struct kobj_type xcp_cfg_res_sysfs_ktype = {
+	/*
+	 * Pre-existing: xcp_res is embedded in struct amdgpu_xcp_cfg
+	 * rather than freed individually by kobject_put().
+	 */
+	.release = NULL,
 	.sysfs_ops = &xcp_cfg_res_sysfs_ops,
 	.default_groups = xcp_cfg_res_sysfs_groups,
 };
@@ -1061,6 +1066,11 @@ static const struct attribute_group amdgpu_xcp_attrs_group = {
 };
 
 static const struct kobj_type xcp_sysfs_ktype = {
+	/*
+	 * Pre-existing: xcp is embedded in struct amdgpu_xcp_mgr
+	 * rather than freed individually by kobject_put().
+	 */
+	.release = NULL,
 	.sysfs_ops = &kobj_sysfs_ops,
 };
 
diff --git a/drivers/infiniband/hw/hfi1/sysfs.c b/drivers/infiniband/hw/hfi1/sysfs.c
index 372cfd13dc61..5a1aca06b542 100644
--- a/drivers/infiniband/hw/hfi1/sysfs.c
+++ b/drivers/infiniband/hw/hfi1/sysfs.c
@@ -608,6 +608,11 @@ static const struct sysfs_ops sde_sysfs_ops = {
 };
 
 static struct kobj_type sde_ktype = {
+	/*
+	 * Pre-existing: sdma_engine is embedded in dd->per_sdma array
+	 * rather than freed by kobject_put().
+	 */
+	.release = NULL,
 	.sysfs_ops = &sde_sysfs_ops,
 };
 
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c b/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
index fdb63a8fb997..df0e48070c2e 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
@@ -245,6 +245,8 @@ static struct attribute *usnic_ib_qpn_default_attrs[] = {
 ATTRIBUTE_GROUPS(usnic_ib_qpn_default);
 
 static struct kobj_type usnic_ib_qpn_type = {
+	/* Pre-existing: usnic_ib_qp_grp is embedded in RDMA core-managed struct usnic_ib_qp_grp. */
+	.release = NULL,
 	.sysfs_ops = &usnic_ib_qpn_sysfs_ops,
 	.default_groups = usnic_ib_qpn_default_groups,
 };
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index 6b567a74fc2c..2f530e8c6757 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -484,6 +484,11 @@ ATTRIBUTE_GROUPS(paths_subsys);
 
 /* Specific kobject type for our PDC paths */
 static const struct kobj_type ktype_pdcspath = {
+	/*
+	 * Pre-existing: pdcspath_entry instances are static; lifetime
+	 * is not controlled by kobject_put().
+	 */
+	.release = NULL,
 	.sysfs_ops = &pdcspath_attr_ops,
 	.default_groups = paths_subsys_groups,
 };
diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c
index e6b5efdf5dc9..d62411e4f535 100644
--- a/drivers/power/supply/ab8500_fg.c
+++ b/drivers/power/supply/ab8500_fg.c
@@ -2531,6 +2531,11 @@ static struct attribute *ab8500_fg_attrs[] = {
 ATTRIBUTE_GROUPS(ab8500_fg);
 
 static const struct kobj_type ab8500_fg_ktype = {
+	/*
+	 * Pre-existing: fg_kobject is embedded in devm-allocated struct
+	 * ab8500_fg; ab8500_fg_sysfs_exit() only calls kobject_del().
+	 */
+	.release = NULL,
 	.sysfs_ops = &ab8500_fg_sysfs_ops,
 	.default_groups = ab8500_fg_groups,
 };
diff --git a/drivers/s390/char/sclp_mem.c b/drivers/s390/char/sclp_mem.c
index 6df1926d4c62..2fb7271dce36 100644
--- a/drivers/s390/char/sclp_mem.c
+++ b/drivers/s390/char/sclp_mem.c
@@ -305,6 +305,8 @@ static ssize_t sclp_memmap_on_memory_store(struct kobject *kobj, struct kobj_att
 }
 
 static const struct kobj_type ktype = {
+	/* Pre-existing: permanent firmware kobjects, never freed */
+	.release = NULL,
 	.sysfs_ops = &kobj_sysfs_ops,
 };
 
diff --git a/drivers/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c
index 0cc2953d59a5..da7a64c95058 100644
--- a/drivers/soc/hisilicon/kunpeng_hccs.c
+++ b/drivers/soc/hisilicon/kunpeng_hccs.c
@@ -1038,6 +1038,13 @@ static struct attribute *hccs_port_default_attrs[] = {
 ATTRIBUTE_GROUPS(hccs_port_default);
 
 static const struct kobj_type hccs_port_type = {
+	/*
+	 * Pre-existing: hccs_port_info is allocated via devm_kzalloc()
+	 * rather than freed by kobject_put(). With
+	 * CONFIG_DEBUG_KOBJECT_RELEASE the delayed kobject cleanup may run
+	 * after devm frees it on unbind, a use-after-free.
+	 */
+	.release = NULL,
 	.sysfs_ops = &hccs_comm_ops,
 	.default_groups = hccs_port_default_groups,
 };
@@ -1110,6 +1117,13 @@ static struct attribute *hccs_die_default_attrs[] = {
 ATTRIBUTE_GROUPS(hccs_die_default);
 
 static const struct kobj_type hccs_die_type = {
+	/*
+	 * Pre-existing: hccs_die_info is allocated via devm_kzalloc()
+	 * rather than freed by kobject_put(). With
+	 * CONFIG_DEBUG_KOBJECT_RELEASE the delayed kobject cleanup may run
+	 * after devm frees it on unbind, a use-after-free.
+	 */
+	.release = NULL,
 	.sysfs_ops = &hccs_comm_ops,
 	.default_groups = hccs_die_default_groups,
 };
@@ -1213,6 +1227,13 @@ static struct attribute *hccs_chip_default_attrs[] = {
 ATTRIBUTE_GROUPS(hccs_chip_default);
 
 static const struct kobj_type hccs_chip_type = {
+	/*
+	 * Pre-existing: hccs_chip_info is allocated via devm_kzalloc()
+	 * rather than freed by kobject_put(). With
+	 * CONFIG_DEBUG_KOBJECT_RELEASE the delayed kobject cleanup may run
+	 * after devm frees it on unbind, a use-after-free.
+	 */
+	.release = NULL,
 	.sysfs_ops = &hccs_comm_ops,
 	.default_groups = hccs_chip_default_groups,
 };
diff --git a/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c b/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c
index ae937854403b..452920a4e2a9 100644
--- a/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c
+++ b/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c
@@ -304,6 +304,13 @@ static const struct sysfs_ops display_sysfs_ops = {
 };
 
 static struct kobj_type display_ktype = {
+	/*
+	 * Pre-existing: dssdev->kobj is embedded in struct omap_dss_device
+	 * and zeroed in display_uninit_sysfs() right after kobject_put().
+	 * With CONFIG_DEBUG_KOBJECT_RELEASE that memset() clobbers the
+	 * pending delayed kobject cleanup.
+	 */
+	.release = NULL,
 	.sysfs_ops = &display_sysfs_ops,
 	.default_groups = display_sysfs_groups,
 };
diff --git a/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c b/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c
index 1b644be5fe2e..40ec750f4315 100644
--- a/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c
+++ b/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c
@@ -496,6 +496,11 @@ static const struct sysfs_ops manager_sysfs_ops = {
 };
 
 static struct kobj_type manager_ktype = {
+	/*
+	 * Pre-existing: mgr->kobj is embedded in static managers[] and
+	 * zeroed in dss_manager_kobj_uninit().
+	 */
+	.release = NULL,
 	.sysfs_ops = &manager_sysfs_ops,
 	.default_groups = manager_sysfs_groups,
 };
diff --git a/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c b/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c
index 1da4fb1c77b4..4d333031b18d 100644
--- a/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c
+++ b/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c
@@ -429,6 +429,11 @@ static const struct sysfs_ops overlay_sysfs_ops = {
 };
 
 static struct kobj_type overlay_ktype = {
+	/*
+	 * Pre-existing: ovl->kobj is embedded in static overlays[];
+	 * dss_overlay_kobj_uninit() drops the kobject ref.
+	 */
+	.release = NULL,
 	.sysfs_ops = &overlay_sysfs_ops,
 	.default_groups = overlay_sysfs_groups,
 };
diff --git a/fs/erofs/sysfs.c b/fs/erofs/sysfs.c
index dfcec9376cd5..2ea6773cd98f 100644
--- a/fs/erofs/sysfs.c
+++ b/fs/erofs/sysfs.c
@@ -238,6 +238,11 @@ static const struct kobj_type erofs_sb_ktype = {
 static const struct kobj_type erofs_ktype = {
 	.default_groups = erofs_groups,
 	.sysfs_ops	= &erofs_attr_ops,
+	/*
+	 * Pre-existing: erofs_root is a static struct kset; lifetime
+	 * is not controlled by kobject_put().
+	 */
+	.release	= NULL,
 };
 
 static struct kset erofs_root = {
@@ -247,6 +252,11 @@ static struct kset erofs_root = {
 static const struct kobj_type erofs_feat_ktype = {
 	.default_groups = erofs_feat_groups,
 	.sysfs_ops	= &erofs_attr_ops,
+	/*
+	 * Pre-existing: erofs_feat is a static struct kobject; lifetime
+	 * is not controlled by kobject_put().
+	 */
+	.release	= NULL,
 };
 
 static struct kobject erofs_feat = {
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index 430356e500af..6e15695cb75f 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -1683,6 +1683,11 @@ static const struct kobj_type f2fs_sb_ktype = {
 
 static const struct kobj_type f2fs_ktype = {
 	.sysfs_ops	= &f2fs_attr_ops,
+	/*
+	 * Pre-existing: f2fs_kset is a static struct kset; lifetime
+	 * is not controlled by kobject_put().
+	 */
+	.release	= NULL,
 };
 
 static struct kset f2fs_kset = {
@@ -1697,6 +1702,11 @@ static const struct sysfs_ops f2fs_feat_attr_ops = {
 static const struct kobj_type f2fs_feat_ktype = {
 	.default_groups = f2fs_feat_groups,
 	.sysfs_ops	= &f2fs_feat_attr_ops,
+	/*
+	 * Pre-existing: f2fs_feat is a static struct kobject; lifetime
+	 * is not controlled by kobject_put().
+	 */
+	.release	= NULL,
 };
 
 static struct kobject f2fs_feat = {
@@ -1711,6 +1721,11 @@ static const struct sysfs_ops f2fs_tune_attr_ops = {
 static const struct kobj_type f2fs_tune_ktype = {
 	.default_groups = f2fs_tune_groups,
 	.sysfs_ops	= &f2fs_tune_attr_ops,
+	/*
+	 * Pre-existing: f2fs_tune is a static struct kobject; lifetime
+	 * is not controlled by kobject_put().
+	 */
+	.release	= NULL,
 };
 
 static struct kobject f2fs_tune = {
diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c
index 563881ddbf00..ff8a1cf51e72 100644
--- a/fs/ocfs2/cluster/masklog.c
+++ b/fs/ocfs2/cluster/masklog.c
@@ -147,6 +147,11 @@ static const struct sysfs_ops mlog_attr_ops = {
 static struct kobj_type mlog_ktype = {
 	.default_groups = mlog_default_groups,
 	.sysfs_ops      = &mlog_attr_ops,
+	/*
+	 * Pre-existing: mlog_kset is a static struct kset; lifetime
+	 * is not controlled by kobject_put().
+	 */
+	.release        = NULL,
 };
 
 static struct kset mlog_kset = {
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 55e37a5d405e..8a1332030884 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -114,7 +114,7 @@ void kobject_get_ownership(const struct kobject *kobj, kuid_t *uid, kgid_t *gid)
 char *kobject_get_path(const struct kobject *kobj, gfp_t flag);
 
 struct kobj_type {
-	void (*release)(struct kobject *kobj);
+	void (*release)(struct kobject *kobj) __must_init;
 	const struct sysfs_ops *sysfs_ops;
 	const struct attribute_group **default_groups;
 	const struct kobj_ns_type_operations *(*child_ns_type)(const struct kobject *kobj);
-- 
2.56.0.313.g2479322e68-goog


______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 9/9] kobject: Require explicit initialization of struct kobj_type::release
  2026-10-27 22:38 ` [PATCH v2 9/9] kobject: Require explicit initialization of struct kobj_type::release Ian Rogers
@ 2026-10-27 22:56   ` sashiko-bot
  0 siblings, 0 replies; 13+ messages in thread
From: sashiko-bot @ 2026-10-27 22:56 UTC (permalink / raw)
  To: Ian Rogers, Kees Cook, Greg Kroah-Hartman, Miguel Ojeda,
	Rafael J . Wysocki, Danilo Krummrich
  Cc: Nathan Chancellor, Nick Desaulniers, Miguel Ojeda,
	Christian König, Zhihao Cheng, Zhongqiu Han,
	Sumanth Korikkar, Bill Wendling, Justin Stitt, linux-s390,
	linux-mtd, dri-devel, Catalin Marinas, Will Deacon, Mark Rutland,
	Len Brown, Vinod Koul, Frank Li, Alex Deucher, David Airlie,
	Simona Vetter, Dennis Dalessandro, Jason Gunthorpe,
	Leon Romanovsky, Nelson Escobar, Satish Kharat,
	James E.J. Bottomley, Helge Deller, Linus Walleij,
	Sebastian Reichel, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Huisong Li, Gao Xiang, Chao Yu, Yue Hu, Jingbo Xu,
	Sandeep Dhavale, Hongbo Li, Chunhai Guo, Jaegeuk Kim, Mark Fasheh,
	Joel Becker, Joseph Qi, Heming Zhao, Johan Hovold, dmaengine,
	linux-rdma

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Low] fbdev: omapdss: inaccurate kobj_type comments for managers and overlays
- [Low] kobject: inaccurate kobj_type comments on static lifetime and delayed release
--

commit 2811dd0d4494f584b7b3fad73d8e6b9f2f067c96
Author: Ian Rogers <irogers@google.com>

kobject: Require explicit initialization of struct kobj_type::release

This commit annotates struct kobj_type::release with __must_init so the
compiler diagnoses any struct kobj_type initializer that omits .release. For
remaining legacy struct kobj_type definitions that do not free their kobject
via kobject_put(), it explicitly initializes .release = NULL with comments
documenting the kobject lifetime and CONFIG_DEBUG_KOBJECT_RELEASE behavior.

Link: https://lpc.events/event/20/contributions/2392/

>     kobject: Require explicit initialization of struct kobj_type::release
>     
>     Documentation/core-api/kobject.rst states:
>     
>       "One important point cannot be overstated: every kobject must have a
>       release() method, and the kobject must persist (in a consistent state)
>       until that method is called. If these constraints are not met, the code
>       is flawed. Note that the kernel will warn you if you forget to provide
>       a release() method. Do not try to get rid of this warning by providing
>       an \"empty\" release function."
>     
>     Annotate struct kobj_type::release with __must_init
>     so the compiler diagnoses any struct kobj_type initializer that omits
>     .release.
>     
>     For the remaining legacy struct kobj_type definitions where the kobject
>     is static, per-CPU, permanent firmware structures, or embedded inside a
>     devm- or parent-managed structure rather than freed by kobject_put(),
>     explicitly initialize .release = NULL with a comment documenting why no
>     release callback is provided.
>     
>     Where the existing teardown is not safe with CONFIG_DEBUG_KOBJECT_RELEASE,
>     because the kobject's memory can be freed or cleared while the delayed
>     kobject cleanup is still pending (ioat, kunpeng_hccs and omapfb display),
>     the comment says so. Fixing those is left to follow-up patches; this
>     change does not alter their behavior.
>     
>     Link: https://lpc.events/event/20/contributions/2392/
>     Signed-off-by: Ian Rogers <irogers@google.com>

[Severity: Low]
The commit message notes that where existing teardown is not safe with
CONFIG_DEBUG_KOBJECT_RELEASE (listing ioat, kunpeng_hccs, and omapfb
display), the comment says so.

Are there additional kobj_type definitions touched in this patch where the
backing memory is freed, zeroed, or unmapped while delayed kobject cleanup is
still pending under CONFIG_DEBUG_KOBJECT_RELEASE, such as omapfb manager_ktype
and overlay_ktype, amdgpu ualink_xcp_info_ktype and xcp_sysfs_ktype, hfi1
sde_ktype, usnic usnic_ib_qpn_type, ab8500_fg_ktype (on the
kobject_init_and_add() error path in ab8500_fg_sysfs_init() before devm frees
di), and the static kobjects/ksets in loadable modules (erofs, f2fs, ocfs2,
and pdc_stable on module unload)?

> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
> index 17888cf544472..c2cccd924b03c 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
> @@ -885,6 +885,11 @@ static const struct attribute_group ualink_xcp_info_group = {
>  };
>  
>  static const struct kobj_type ualink_xcp_info_ktype = {
> +	/*
> +	 * Pre-existing: xcp->ualink.kobj is embedded in struct amdgpu_xcp_mgr
> +	 * rather than freed individually by kobject_put().
> +	 */
> +	.release = NULL,
>  	.sysfs_ops = &kobj_sysfs_ops
>  };
>  
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
> index ab14079d1c422..0847134a13917 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c

[ ... ]

> @@ -1061,6 +1066,11 @@ static const struct attribute_group amdgpu_xcp_attrs_group = {
>  };
>  
>  static const struct kobj_type xcp_sysfs_ktype = {
> +	/*
> +	 * Pre-existing: xcp is embedded in struct amdgpu_xcp_mgr
> +	 * rather than freed individually by kobject_put().
> +	 */
> +	.release = NULL,
>  	.sysfs_ops = &kobj_sysfs_ops,
>  };

[Severity: Low]
Should the comments on ualink_xcp_info_ktype and xcp_sysfs_ktype also note the
CONFIG_DEBUG_KOBJECT_RELEASE use-after-free hazard?

During teardown, amdgpu_device_fini_hw() calls amdgpu_ualink_sysfs_fini() and
amdgpu_xcp_sysfs_fini(), which call kobject_put(&xcp->ualink.kobj) and
kobject_put(&xcp->kobj), and then amdgpu_device_fini_sw() frees adev->xcp_mgr
while delayed kobject cleanup may still be pending.

> diff --git a/drivers/infiniband/hw/hfi1/sysfs.c b/drivers/infiniband/hw/hfi1/sysfs.c
> index 372cfd13dc616..5a1aca06b542b 100644
> --- a/drivers/infiniband/hw/hfi1/sysfs.c
> +++ b/drivers/infiniband/hw/hfi1/sysfs.c
> @@ -608,6 +608,11 @@ static const struct sysfs_ops sde_sysfs_ops = {
>  };
>  
>  static struct kobj_type sde_ktype = {
> +	/*
> +	 * Pre-existing: sdma_engine is embedded in dd->per_sdma array
> +	 * rather than freed by kobject_put().
> +	 */
> +	.release = NULL,
>  	.sysfs_ops = &sde_sysfs_ops,
>  };

[Severity: Low]
Does sde_ktype also have the same CONFIG_DEBUG_KOBJECT_RELEASE use-after-free
issue worth noting in this comment?

In the device removal path, hfi1_verbs_unregister_sysfs() calls
kobject_put(&dd->per_sdma[i].kobj) right before remove_one() ->
hfi1_free_devdata() -> sdma_clean() calls kfree(dd->per_sdma).

> diff --git a/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c b/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
> index fdb63a8fb9974..df0e48070c2ee 100644
> --- a/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
> +++ b/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
> @@ -245,6 +245,8 @@ static struct attribute *usnic_ib_qpn_default_attrs[] = {
>  ATTRIBUTE_GROUPS(usnic_ib_qpn_default);
>  
>  static struct kobj_type usnic_ib_qpn_type = {
> +	/* Pre-existing: usnic_ib_qp_grp is embedded in RDMA core-managed struct usnic_ib_qp_grp. */
> +	.release = NULL,
>  	.sysfs_ops = &usnic_ib_qpn_sysfs_ops,
>  	.default_groups = usnic_ib_qpn_default_groups,
>  };

[Severity: Low]
Should this comment on usnic_ib_qpn_type also mention
CONFIG_DEBUG_KOBJECT_RELEASE?

When destroying a QP, ib_destroy_qp_user() calls usnic_ib_destroy_qp() ->
usnic_ib_sysfs_qpn_remove(), which calls kobject_put(&qp_grp->kobj)
immediately before the RDMA core frees the struct usnic_ib_qp_grp allocation.

> diff --git a/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c b/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c
> index 1b644be5fe2ed..40ec750f43155 100644
> --- a/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c
> +++ b/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c
> @@ -496,6 +496,11 @@ static const struct sysfs_ops manager_sysfs_ops = {
>  };
>  
>  static struct kobj_type manager_ktype = {
> +	/*
> +	 * Pre-existing: mgr->kobj is embedded in static managers[] and
> +	 * zeroed in dss_manager_kobj_uninit().
> +	 */
> +	.release = NULL,
>  	.sysfs_ops = &manager_sysfs_ops,
>  	.default_groups = manager_sysfs_groups,
>  };

[Severity: Low]
Is managers[] actually a static array here, and does this teardown also
corrupt pending delayed cleanup under CONFIG_DEBUG_KOBJECT_RELEASE?

In drivers/video/fbdev/omap2/omapfb/dss/manager.c, managers is dynamically
allocated on the heap in dss_init_overlay_managers() and freed in
dss_uninit_overlay_managers():

static struct omap_overlay_manager *managers;

int dss_init_overlay_managers(void)
{
	int i;

	num_managers = dss_feat_get_num_mgrs();

	managers = kzalloc_objs(struct omap_overlay_manager, num_managers);
	...
}

In addition, dss_manager_kobj_uninit() calls
memset(&mgr->kobj, 0, sizeof(mgr->kobj)) right after kobject_put(&mgr->kobj)
(and dss_uninit_overlay_managers() then calls kfree(managers)), which clobbers
and frees the pending delayed kobject cleanup under
CONFIG_DEBUG_KOBJECT_RELEASE just like display_uninit_sysfs() in
display-sysfs.c.

> diff --git a/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c b/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c
> index 1da4fb1c77b4a..4d333031b18d6 100644
> --- a/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c
> +++ b/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c
> @@ -429,6 +429,11 @@ static const struct sysfs_ops overlay_sysfs_ops = {
>  };
>  
>  static struct kobj_type overlay_ktype = {
> +	/*
> +	 * Pre-existing: ovl->kobj is embedded in static overlays[];
> +	 * dss_overlay_kobj_uninit() drops the kobject ref.
> +	 */
> +	.release = NULL,
>  	.sysfs_ops = &overlay_sysfs_ops,
>  	.default_groups = overlay_sysfs_groups,
>  };

[Severity: Low]
Similarly, is overlays[] heap-allocated rather than static, with a
use-after-free under CONFIG_DEBUG_KOBJECT_RELEASE?

In drivers/video/fbdev/omap2/omapfb/dss/overlay.c, overlays is allocated via
kzalloc_objs(struct omap_overlay, num_overlays) in dss_init_overlays(), and
dss_uninit_overlays() frees it immediately after dss_overlay_kobj_uninit()
calls kobject_put(&ovl->kobj):

void dss_uninit_overlays(struct platform_device *pdev)
{
	int i;

	for (i = 0; i < num_overlays; ++i) {
		struct omap_overlay *ovl = &overlays[i];
		dss_overlay_kobj_uninit(ovl);
	}

	kfree(overlays);
	overlays = NULL;
	num_overlays = 0;
}

Should the comments on manager_ktype and overlay_ktype describe managers and
overlays as dynamically allocated arrays and note the
CONFIG_DEBUG_KOBJECT_RELEASE hazard as well?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261027223847.652884-1-irogers@google.com?part=9

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 8/9] drm/amdkfd: Free queue in procfs_queue_type kobject release callback
  2026-10-27 22:38 ` [PATCH v2 8/9] drm/amdkfd: Free queue in procfs_queue_type kobject release callback Ian Rogers
@ 2026-10-27 23:15   ` Felix Kuehling
  0 siblings, 0 replies; 13+ messages in thread
From: Felix Kuehling @ 2026-10-27 23:15 UTC (permalink / raw)
  To: Ian Rogers, Kees Cook, Greg Kroah-Hartman, Miguel Ojeda,
	Rafael J . Wysocki, Danilo Krummrich
  Cc: Nathan Chancellor, Nick Desaulniers, Miguel Ojeda,
	Christian König, Zhihao Cheng, Zhongqiu Han,
	Sumanth Korikkar, Bill Wendling, Justin Stitt, driver-core, llvm,
	linux-hardening, linux-fsdevel, linux-doc, linux-acpi, linux-pm,
	linuxppc-dev, linux-sh, linux-s390, gfs2, xen-devel, linux-mtd,
	amd-gfx, dri-devel, linux-kernel, Alex Deucher, David Airlie,
	Simona Vetter, Amber Lin

On 2026-10-27 18:38, Ian Rogers wrote:
> struct queue embeds a struct kobject (q->kobj) for procfs entries, but
> procfs_queue_type had no .release callback and uninit_queue() freed q
> immediately after kfd_procfs_del_queue() called kobject_put(&q->kobj).
> With CONFIG_DEBUG_KOBJECT_RELEASE=y, this causes a use-after-free.
>
> Add kfd_procfs_queue_release() to free struct queue from the kobject
> release callback, change kfd_procfs_del_queue() to only remove the
> kobject from sysfs via kobject_del(), and drop the final reference in
> uninit_queue() via kobject_put(). Check q->kobj.state_in_sysfs before
> calling kobject_del() in kfd_procfs_del_queue() to avoid warnings if
> sysfs creation previously failed.
>
> Fixes: 6d220a7e7971 ("drm/amdkfd: Add queue information to sysfs")
> Signed-off-by: Ian Rogers <irogers@google.com>

Reviewed-by: Felix Kuehling <felix.kuehling@amd.com>


> ---
>   drivers/gpu/drm/amd/amdkfd/kfd_process.c | 12 +++++++++---
>   drivers/gpu/drm/amd/amdkfd/kfd_queue.c   |  5 ++++-
>   2 files changed, 13 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
> index 226f52626e84..8e6136d52a50 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
> @@ -512,7 +512,15 @@ static const struct sysfs_ops procfs_queue_ops = {
>   	.show = kfd_procfs_queue_show,
>   };
>   
> +static void kfd_procfs_queue_release(struct kobject *kobj)
> +{
> +	struct queue *q = container_of(kobj, struct queue, kobj);
> +
> +	kfree(q);
> +}
> +
>   static const struct kobj_type procfs_queue_type = {
> +	.release = kfd_procfs_queue_release,
>   	.sysfs_ops = &procfs_queue_ops,
>   	.default_groups = procfs_queue_groups,
>   };
> @@ -552,7 +560,6 @@ int kfd_procfs_add_queue(struct queue *q)
>   	if (ret < 0) {
>   		pr_warn("Creating proc/<pid>/queues/%u failed",
>   			q->properties.queue_id);
> -		kobject_put(&q->kobj);
>   		return ret;
>   	}
>   
> @@ -697,11 +704,10 @@ static void kfd_procfs_add_sysfs_files(struct kfd_process *p)
>   
>   void kfd_procfs_del_queue(struct queue *q)
>   {
> -	if (!q || !q->process->kobj)
> +	if (!q || !q->process || !q->process->kobj || !q->kobj.state_in_sysfs)
>   		return;
>   
>   	kobject_del(&q->kobj);
> -	kobject_put(&q->kobj);
>   }
>   
>   int kfd_process_create_wq(void)
> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
> index ae3e7c54014a..4666110aebe0 100644
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
> @@ -83,7 +83,10 @@ int init_queue(struct queue **q, const struct queue_properties *properties)
>   
>   void uninit_queue(struct queue *q)
>   {
> -	kfree(q);
> +	if (q && q->kobj.state_initialized)
> +		kobject_put(&q->kobj);
> +	else
> +		kfree(q);
>   }
>   
>   #if IS_ENABLED(CONFIG_HSA_AMD_SVM)

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v2 4/9] cpufreq: governor: Initialize kobj_type release callback statically
  2026-10-27 22:38 ` [PATCH v2 4/9] cpufreq: governor: Initialize kobj_type release callback statically Ian Rogers
@ 2026-10-28  3:36   ` Zhongqiu Han
  0 siblings, 0 replies; 13+ messages in thread
From: Zhongqiu Han @ 2026-10-28  3:36 UTC (permalink / raw)
  To: Ian Rogers, Kees Cook, Greg Kroah-Hartman, Miguel Ojeda,
	Rafael J . Wysocki, Danilo Krummrich
  Cc: Nathan Chancellor, Nick Desaulniers, Miguel Ojeda,
	Christian König, Zhihao Cheng, Sumanth Korikkar,
	Bill Wendling, Justin Stitt, driver-core, llvm, linux-hardening,
	linux-fsdevel, linux-doc, linux-acpi, linux-pm, linuxppc-dev,
	linux-sh, linux-s390, gfs2, xen-devel, linux-mtd, amd-gfx,
	dri-devel, linux-kernel, Viresh Kumar, zhongqiu.han

Hi Ian,

Thanks for the update.

On 10/28/2026 6:38 AM, Ian Rogers wrote:
> Export cpufreq_dbs_data_release() and set .kobj_type.release statically
> in the ondemand and conservative governors so their gov_attr_set
> kobjects have a valid release callback statically initialized, matching
> cpufreq_governor_dbs. Remove the redundant runtime assignment in

"matching cpufreq_governor_dbs" is a bit confusing to me
(cpufreq_governor_dbs() was removed back in v4.8 by commit e788892ba3cc
("cpufreq: governor: Get rid of governor events")), as it doesn't
seem to refer to anything in the tree. Perhaps we could just drop it,
e.g.:

Export cpufreq_dbs_data_release() and initialize .kobj_type.release
statically in the ondemand and conservative governors instead of
assigning it at runtime in cpufreq_dbs_governor_init().


The code change itself looks good to me. With the changelog updated
(in a respin if the series needs one for other reasons, or when
applying):

Reviewed-by: Zhongqiu Han <zhongqiu.han@oss.qualcomm.com>

> cpufreq_dbs_governor_init().
> 
> This prepares for annotating struct kobj_type::release with
> __must_init.
> 
> Signed-off-by: Ian Rogers <irogers@google.com>
> ---
>   drivers/cpufreq/cpufreq_conservative.c | 5 ++++-
>   drivers/cpufreq/cpufreq_governor.c     | 4 ++--
>   drivers/cpufreq/cpufreq_governor.h     | 1 +
>   drivers/cpufreq/cpufreq_ondemand.c     | 5 ++++-
>   4 files changed, 11 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
> index 02bfd46543e9..146a2353b1a2 100644
> --- a/drivers/cpufreq/cpufreq_conservative.c
> +++ b/drivers/cpufreq/cpufreq_conservative.c
> @@ -318,7 +318,10 @@ static void cs_limits(struct cpufreq_policy *policy)
>   
>   static struct dbs_governor cs_governor = {
>   	.gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("conservative"),
> -	.kobj_type = { .default_groups = cs_groups },
> +	.kobj_type = {
> +		.release = cpufreq_dbs_data_release,
> +		.default_groups = cs_groups,
> +	},
>   	.gov_dbs_update = cs_dbs_update,
>   	.alloc = cs_alloc,
>   	.free = cs_free,
> diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
> index f3bd3dbe7c41..f8b5aca09b6b 100644
> --- a/drivers/cpufreq/cpufreq_governor.c
> +++ b/drivers/cpufreq/cpufreq_governor.c
> @@ -419,7 +419,7 @@ static void free_policy_dbs_info(struct policy_dbs_info *policy_dbs,
>   	gov->free(policy_dbs);
>   }
>   
> -static void cpufreq_dbs_data_release(struct kobject *kobj)
> +void cpufreq_dbs_data_release(struct kobject *kobj)
>   {
>   	struct dbs_data *dbs_data = to_dbs_data(to_gov_attr_set(kobj));
>   	struct dbs_governor *gov = dbs_data->gov;
> @@ -427,6 +427,7 @@ static void cpufreq_dbs_data_release(struct kobject *kobj)
>   	gov->exit(dbs_data);
>   	kfree(dbs_data);
>   }
> +EXPORT_SYMBOL_GPL(cpufreq_dbs_data_release);
>   
>   int cpufreq_dbs_governor_init(struct cpufreq_policy *policy)
>   {
> @@ -488,7 +489,6 @@ int cpufreq_dbs_governor_init(struct cpufreq_policy *policy)
>   	policy->governor_data = policy_dbs;
>   
>   	gov->kobj_type.sysfs_ops = &governor_sysfs_ops;
> -	gov->kobj_type.release = cpufreq_dbs_data_release;
>   	ret = kobject_init_and_add(&dbs_data->attr_set.kobj, &gov->kobj_type,
>   				   get_governor_parent_kobj(policy),
>   				   "%s", gov->gov.name);
> diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h
> index 806d8fb4dff1..1026712bb79b 100644
> --- a/drivers/cpufreq/cpufreq_governor.h
> +++ b/drivers/cpufreq/cpufreq_governor.h
> @@ -150,6 +150,7 @@ static inline struct dbs_governor *dbs_governor_of(struct cpufreq_policy *policy
>   }
>   
>   /* Governor callback routines */
> +void cpufreq_dbs_data_release(struct kobject *kobj);
>   int cpufreq_dbs_governor_init(struct cpufreq_policy *policy);
>   void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy);
>   int cpufreq_dbs_governor_start(struct cpufreq_policy *policy);
> diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
> index 9942dbb38dae..7386d043c665 100644
> --- a/drivers/cpufreq/cpufreq_ondemand.c
> +++ b/drivers/cpufreq/cpufreq_ondemand.c
> @@ -374,7 +374,10 @@ static struct od_ops od_ops = {
>   
>   static struct dbs_governor od_dbs_gov = {
>   	.gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("ondemand"),
> -	.kobj_type = { .default_groups = od_groups },
> +	.kobj_type = {
> +		.release = cpufreq_dbs_data_release,
> +		.default_groups = od_groups,
> +	},
>   	.gov_dbs_update = od_dbs_update,
>   	.alloc = od_alloc,
>   	.free = od_free,


-- 
Thx and BRs,
Zhongqiu Han

______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2026-10-28  3:36 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-27 22:38 [PATCH v2 0/9] Add __must_init and require explicit kobj_type::release Ian Rogers
2026-10-27 22:38 ` [PATCH v2 1/9] Compiler Attributes: Add __must_init macro Ian Rogers
2026-10-27 22:38 ` [PATCH v2 2/9] powerpc/secvar: Add missing kobject release callback to secvar_ktype Ian Rogers
2026-10-27 22:38 ` [PATCH v2 3/9] sh: sq: Add missing kobject release callback to ktype_percpu_entry Ian Rogers
2026-10-27 22:38 ` [PATCH v2 4/9] cpufreq: governor: Initialize kobj_type release callback statically Ian Rogers
2026-10-28  3:36   ` Zhongqiu Han
2026-10-27 22:38 ` [PATCH v2 5/9] dlm: Free dlm_ls in kobject release callback Ian Rogers
2026-10-27 22:38 ` [PATCH v2 6/9] xen/sys-hypervisor: Add release callback to hyp_sysfs_kobj_type Ian Rogers
2026-10-27 22:38 ` [PATCH v2 7/9] ubifs: sysfs: Use kset_create_and_add() for ubifs_kset Ian Rogers
2026-10-27 22:38 ` [PATCH v2 8/9] drm/amdkfd: Free queue in procfs_queue_type kobject release callback Ian Rogers
2026-10-27 23:15   ` Felix Kuehling
2026-10-27 22:38 ` [PATCH v2 9/9] kobject: Require explicit initialization of struct kobj_type::release Ian Rogers
2026-10-27 22:56   ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox