All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/11] kobject: Require explicit initialization of struct kobj_type::release
@ 2026-10-13 22:39 ` Ian Rogers
  0 siblings, 0 replies; 40+ messages in thread
From: Ian Rogers @ 2026-10-13 22:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, driver-core, llvm, linux-hardening,
	linux-doc, linuxppc-dev, linux-sh, linux-pm, linux-acpi, gfs2,
	xen-devel, linux-s390, 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], this series
introduces __require_explicit_initialization in
include/linux/compiler_attributes.h and applies it to
struct kobj_type::release.

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 30 struct kobj_type
definitions across the tree that omitted .release:
- Patches 2-10 fix 10 struct kobj_type definitions where dynamically
  allocated kobjects, ksets, or enclosing structures were either leaked on
  kobject_put() or freed prematurely before kobject release (risking a
  use-after-free when CONFIG_DEBUG_KOBJECT_RELEASE=y).
- Patch 11 annotates struct kobj_type::release with
  __require_explicit_initialization and explicitly sets .release = NULL
  (with explanatory comments) on the remaining legacy struct kobj_type
  definitions whose kobjects are static, per-CPU, or embedded in devm- or
  parent-managed structures.

[1] https://lpc.events/event/20/contributions/2392/

Ian Rogers (11):
  Compiler Attributes: Add __require_explicit_initialization macro
  powerpc/secvar: Add missing kobject release callback to secvar_ktype
  sh: sq: Add missing kobject release callback to ktype_percpu_entry
  cpufreq: Initialize kobj_type release callback in ondemand and
    conservative governors
  ACPI: CPPC: Free cpc_desc in kobject release callback
  dlm: Free dlm_ls in kobject release callback
  xen/sys-hypervisor: Add release callback to hyp_sysfs_kobj_type
  s390/sclp_mem: Allocate struct sclp_mem dynamically and add kobject
    release
  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                   |  2 +
 arch/powerpc/kernel/secvar-sysfs.c            |  6 ++
 arch/sh/kernel/cpu/sh4/sq.c                   |  6 ++
 drivers/acpi/cppc_acpi.c                      | 39 +++++-----
 drivers/acpi/sysfs.c                          |  2 +
 drivers/cpufreq/cpufreq_conservative.c        |  5 +-
 drivers/cpufreq/cpufreq_governor.c            |  3 +-
 drivers/cpufreq/cpufreq_governor.h            |  1 +
 drivers/cpufreq/cpufreq_ondemand.c            |  5 +-
 drivers/dma/ioat/sysfs.c                      |  2 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c       |  4 +
 drivers/gpu/drm/amd/amdkfd/kfd_process.c      | 10 ++-
 drivers/gpu/drm/amd/amdkfd/kfd_queue.c        |  5 +-
 drivers/infiniband/hw/hfi1/sysfs.c            |  2 +
 drivers/infiniband/hw/usnic/usnic_ib_sysfs.c  |  2 +
 drivers/parisc/pdc_stable.c                   |  2 +
 drivers/power/supply/ab8500_fg.c              |  2 +
 drivers/s390/char/sclp_mem.c                  | 73 +++++++++----------
 drivers/soc/hisilicon/kunpeng_hccs.c          |  6 ++
 .../fbdev/omap2/omapfb/dss/display-sysfs.c    |  2 +
 .../fbdev/omap2/omapfb/dss/manager-sysfs.c    |  2 +
 .../fbdev/omap2/omapfb/dss/overlay-sysfs.c    |  2 +
 drivers/xen/sys-hypervisor.c                  |  6 ++
 fs/dlm/lockspace.c                            | 19 +++--
 fs/erofs/sysfs.c                              |  4 +
 fs/f2fs/sysfs.c                               |  6 ++
 fs/ocfs2/cluster/masklog.c                    |  2 +
 fs/ubifs/sysfs.c                              | 24 ++----
 include/linux/compiler_attributes.h           | 11 +++
 include/linux/kobject.h                       |  2 +-
 scripts/checkpatch.pl                         |  1 +
 tools/lib/python/kdoc/xforms_lists.py         |  1 +
 33 files changed, 170 insertions(+), 90 deletions(-)

-- 
2.56.0.385.gd3acb90ef8-goog


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

* [PATCH 00/11] kobject: Require explicit initialization of struct kobj_type::release
@ 2026-10-13 22:39 ` Ian Rogers
  0 siblings, 0 replies; 40+ messages in thread
From: Ian Rogers @ 2026-10-13 22:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, driver-core, llvm, linux-hardening,
	linux-doc, linuxppc-dev, linux-sh, linux-pm, linux-acpi, gfs2,
	xen-devel, linux-s390, 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], this series
introduces __require_explicit_initialization in
include/linux/compiler_attributes.h and applies it to
struct kobj_type::release.

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 30 struct kobj_type
definitions across the tree that omitted .release:
- Patches 2-10 fix 10 struct kobj_type definitions where dynamically
  allocated kobjects, ksets, or enclosing structures were either leaked on
  kobject_put() or freed prematurely before kobject release (risking a
  use-after-free when CONFIG_DEBUG_KOBJECT_RELEASE=y).
- Patch 11 annotates struct kobj_type::release with
  __require_explicit_initialization and explicitly sets .release = NULL
  (with explanatory comments) on the remaining legacy struct kobj_type
  definitions whose kobjects are static, per-CPU, or embedded in devm- or
  parent-managed structures.

[1] https://lpc.events/event/20/contributions/2392/

Ian Rogers (11):
  Compiler Attributes: Add __require_explicit_initialization macro
  powerpc/secvar: Add missing kobject release callback to secvar_ktype
  sh: sq: Add missing kobject release callback to ktype_percpu_entry
  cpufreq: Initialize kobj_type release callback in ondemand and
    conservative governors
  ACPI: CPPC: Free cpc_desc in kobject release callback
  dlm: Free dlm_ls in kobject release callback
  xen/sys-hypervisor: Add release callback to hyp_sysfs_kobj_type
  s390/sclp_mem: Allocate struct sclp_mem dynamically and add kobject
    release
  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                   |  2 +
 arch/powerpc/kernel/secvar-sysfs.c            |  6 ++
 arch/sh/kernel/cpu/sh4/sq.c                   |  6 ++
 drivers/acpi/cppc_acpi.c                      | 39 +++++-----
 drivers/acpi/sysfs.c                          |  2 +
 drivers/cpufreq/cpufreq_conservative.c        |  5 +-
 drivers/cpufreq/cpufreq_governor.c            |  3 +-
 drivers/cpufreq/cpufreq_governor.h            |  1 +
 drivers/cpufreq/cpufreq_ondemand.c            |  5 +-
 drivers/dma/ioat/sysfs.c                      |  2 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c       |  4 +
 drivers/gpu/drm/amd/amdkfd/kfd_process.c      | 10 ++-
 drivers/gpu/drm/amd/amdkfd/kfd_queue.c        |  5 +-
 drivers/infiniband/hw/hfi1/sysfs.c            |  2 +
 drivers/infiniband/hw/usnic/usnic_ib_sysfs.c  |  2 +
 drivers/parisc/pdc_stable.c                   |  2 +
 drivers/power/supply/ab8500_fg.c              |  2 +
 drivers/s390/char/sclp_mem.c                  | 73 +++++++++----------
 drivers/soc/hisilicon/kunpeng_hccs.c          |  6 ++
 .../fbdev/omap2/omapfb/dss/display-sysfs.c    |  2 +
 .../fbdev/omap2/omapfb/dss/manager-sysfs.c    |  2 +
 .../fbdev/omap2/omapfb/dss/overlay-sysfs.c    |  2 +
 drivers/xen/sys-hypervisor.c                  |  6 ++
 fs/dlm/lockspace.c                            | 19 +++--
 fs/erofs/sysfs.c                              |  4 +
 fs/f2fs/sysfs.c                               |  6 ++
 fs/ocfs2/cluster/masklog.c                    |  2 +
 fs/ubifs/sysfs.c                              | 24 ++----
 include/linux/compiler_attributes.h           | 11 +++
 include/linux/kobject.h                       |  2 +-
 scripts/checkpatch.pl                         |  1 +
 tools/lib/python/kdoc/xforms_lists.py         |  1 +
 33 files changed, 170 insertions(+), 90 deletions(-)

-- 
2.56.0.385.gd3acb90ef8-goog


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

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

* [PATCH 01/11] Compiler Attributes: Add __require_explicit_initialization macro
  2026-10-13 22:39 ` Ian Rogers
@ 2026-10-13 22:39   ` Ian Rogers
  -1 siblings, 0 replies; 40+ messages in thread
From: Ian Rogers @ 2026-10-13 22:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, driver-core, llvm, linux-hardening,
	linux-doc, linuxppc-dev, linux-sh, linux-pm, linux-acpi, gfs2,
	xen-devel, linux-s390, linux-mtd, amd-gfx, dri-devel,
	linux-kernel, Ian Rogers

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 __require_explicit_initialization 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.

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/
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
---
 Documentation/conf.py                 |  1 +
 include/linux/compiler_attributes.h   | 11 +++++++++++
 scripts/checkpatch.pl                 |  1 +
 tools/lib/python/kdoc/xforms_lists.py |  1 +
 4 files changed, 14 insertions(+)

diff --git a/Documentation/conf.py b/Documentation/conf.py
index 5ab26ce89daf..3e5cb9ca0970 100644
--- a/Documentation/conf.py
+++ b/Documentation/conf.py
@@ -203,6 +203,7 @@ c_id_attributes = [
     "__noreturn",
     "__packed",
     "__pure",
+    "__require_explicit_initialization",
     "__section",
     "__always_unused",
     "__maybe_unused",
diff --git a/include/linux/compiler_attributes.h b/include/linux/compiler_attributes.h
index 476c4c560d17..60522ab80c5a 100644
--- a/include/linux/compiler_attributes.h
+++ b/include/linux/compiler_attributes.h
@@ -322,6 +322,17 @@
  */
 #define __pure                          __attribute__((__pure__))
 
+/*
+ * Optional: not supported by gcc
+ *
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#require-explicit-initialization
+ */
+#if __has_attribute(__require_explicit_initialization__)
+# define __require_explicit_initialization __attribute__((__require_explicit_initialization__))
+#else
+# define __require_explicit_initialization
+#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 8a7787d228a6..4a3ae6b0100a 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -6871,6 +6871,7 @@ sub process {
 				"noreturn"			=> "__noreturn",
 				"packed"			=> "__packed",
 				"pure"				=> "__pure",
+				"require_explicit_initialization" => "__require_explicit_initialization",
 				"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 e3dda2fe8a53..32066fbbe763 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("__require_explicit_initialization"), ""),
         (CMatch("____cacheline_aligned_in_smp"), ""),
         (CMatch("____cacheline_aligned"), ""),
         (CMatch("__cacheline_group_(?:begin|end)"), ""),
-- 
2.56.0.385.gd3acb90ef8-goog


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

* [PATCH 01/11] Compiler Attributes: Add __require_explicit_initialization macro
@ 2026-10-13 22:39   ` Ian Rogers
  0 siblings, 0 replies; 40+ messages in thread
From: Ian Rogers @ 2026-10-13 22:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, driver-core, llvm, linux-hardening,
	linux-doc, linuxppc-dev, linux-sh, linux-pm, linux-acpi, gfs2,
	xen-devel, linux-s390, linux-mtd, amd-gfx, dri-devel,
	linux-kernel, Ian Rogers

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 __require_explicit_initialization 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.

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/
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
---
 Documentation/conf.py                 |  1 +
 include/linux/compiler_attributes.h   | 11 +++++++++++
 scripts/checkpatch.pl                 |  1 +
 tools/lib/python/kdoc/xforms_lists.py |  1 +
 4 files changed, 14 insertions(+)

diff --git a/Documentation/conf.py b/Documentation/conf.py
index 5ab26ce89daf..3e5cb9ca0970 100644
--- a/Documentation/conf.py
+++ b/Documentation/conf.py
@@ -203,6 +203,7 @@ c_id_attributes = [
     "__noreturn",
     "__packed",
     "__pure",
+    "__require_explicit_initialization",
     "__section",
     "__always_unused",
     "__maybe_unused",
diff --git a/include/linux/compiler_attributes.h b/include/linux/compiler_attributes.h
index 476c4c560d17..60522ab80c5a 100644
--- a/include/linux/compiler_attributes.h
+++ b/include/linux/compiler_attributes.h
@@ -322,6 +322,17 @@
  */
 #define __pure                          __attribute__((__pure__))
 
+/*
+ * Optional: not supported by gcc
+ *
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#require-explicit-initialization
+ */
+#if __has_attribute(__require_explicit_initialization__)
+# define __require_explicit_initialization __attribute__((__require_explicit_initialization__))
+#else
+# define __require_explicit_initialization
+#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 8a7787d228a6..4a3ae6b0100a 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -6871,6 +6871,7 @@ sub process {
 				"noreturn"			=> "__noreturn",
 				"packed"			=> "__packed",
 				"pure"				=> "__pure",
+				"require_explicit_initialization" => "__require_explicit_initialization",
 				"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 e3dda2fe8a53..32066fbbe763 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("__require_explicit_initialization"), ""),
         (CMatch("____cacheline_aligned_in_smp"), ""),
         (CMatch("____cacheline_aligned"), ""),
         (CMatch("__cacheline_group_(?:begin|end)"), ""),
-- 
2.56.0.385.gd3acb90ef8-goog


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

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

* [PATCH 02/11] powerpc/secvar: Add missing kobject release callback to secvar_ktype
  2026-10-13 22:39 ` Ian Rogers
@ 2026-10-13 22:39   ` Ian Rogers
  -1 siblings, 0 replies; 40+ messages in thread
From: Ian Rogers @ 2026-10-13 22:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, driver-core, llvm, linux-hardening,
	linux-doc, linuxppc-dev, linux-sh, linux-pm, linux-acpi, gfs2,
	xen-devel, linux-s390, linux-mtd, amd-gfx, dri-devel,
	linux-kernel, Ian Rogers

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")
Assisted-by: Antigravity:gemini-3.1-pro
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.385.gd3acb90ef8-goog


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

* [PATCH 02/11] powerpc/secvar: Add missing kobject release callback to secvar_ktype
@ 2026-10-13 22:39   ` Ian Rogers
  0 siblings, 0 replies; 40+ messages in thread
From: Ian Rogers @ 2026-10-13 22:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, driver-core, llvm, linux-hardening,
	linux-doc, linuxppc-dev, linux-sh, linux-pm, linux-acpi, gfs2,
	xen-devel, linux-s390, linux-mtd, amd-gfx, dri-devel,
	linux-kernel, Ian Rogers

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")
Assisted-by: Antigravity:gemini-3.1-pro
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.385.gd3acb90ef8-goog


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

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

* [PATCH 03/11] sh: sq: Add missing kobject release callback to ktype_percpu_entry
  2026-10-13 22:39 ` Ian Rogers
@ 2026-10-13 22:39   ` Ian Rogers
  -1 siblings, 0 replies; 40+ messages in thread
From: Ian Rogers @ 2026-10-13 22:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, driver-core, llvm, linux-hardening,
	linux-doc, linuxppc-dev, linux-sh, linux-pm, linux-acpi, gfs2,
	xen-devel, linux-s390, linux-mtd, amd-gfx, dri-devel,
	linux-kernel, Ian Rogers

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.")
Assisted-by: Antigravity:gemini-3.1-pro
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.385.gd3acb90ef8-goog


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

* [PATCH 03/11] sh: sq: Add missing kobject release callback to ktype_percpu_entry
@ 2026-10-13 22:39   ` Ian Rogers
  0 siblings, 0 replies; 40+ messages in thread
From: Ian Rogers @ 2026-10-13 22:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, driver-core, llvm, linux-hardening,
	linux-doc, linuxppc-dev, linux-sh, linux-pm, linux-acpi, gfs2,
	xen-devel, linux-s390, linux-mtd, amd-gfx, dri-devel,
	linux-kernel, Ian Rogers

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.")
Assisted-by: Antigravity:gemini-3.1-pro
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.385.gd3acb90ef8-goog


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

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

* [PATCH 04/11] cpufreq: Initialize kobj_type release callback in ondemand and conservative governors
  2026-10-13 22:39 ` Ian Rogers
@ 2026-10-13 22:39   ` Ian Rogers
  -1 siblings, 0 replies; 40+ messages in thread
From: Ian Rogers @ 2026-10-13 22:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, driver-core, llvm, linux-hardening,
	linux-doc, linuxppc-dev, linux-sh, linux-pm, linux-acpi, gfs2,
	xen-devel, linux-s390, linux-mtd, amd-gfx, dri-devel,
	linux-kernel, Ian Rogers

Export cpufreq_dbs_data_release() and set .kobj_type.release in the
ondemand and conservative governors so their gov_attr_set kobjects have
a valid release callback, matching cpufreq_ governor_dbs.

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

Fixes: c4435630361d ("cpufreq: governor: New sysfs show/store callbacks for governor tunables")
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
---
 drivers/cpufreq/cpufreq_conservative.c | 5 ++++-
 drivers/cpufreq/cpufreq_governor.c     | 3 ++-
 drivers/cpufreq/cpufreq_governor.h     | 1 +
 drivers/cpufreq/cpufreq_ondemand.c     | 5 ++++-
 4 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 0b32ae28ec85..38c3bd5bf75a 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -316,7 +316,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 710d93ec89b5..97b64985927d 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -404,7 +404,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;
@@ -412,6 +412,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)
 {
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h
index 73b8ed7cfaae..c03d067f42eb 100644
--- a/drivers/cpufreq/cpufreq_governor.h
+++ b/drivers/cpufreq/cpufreq_governor.h
@@ -148,6 +148,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.385.gd3acb90ef8-goog


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

* [PATCH 04/11] cpufreq: Initialize kobj_type release callback in ondemand and conservative governors
@ 2026-10-13 22:39   ` Ian Rogers
  0 siblings, 0 replies; 40+ messages in thread
From: Ian Rogers @ 2026-10-13 22:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, driver-core, llvm, linux-hardening,
	linux-doc, linuxppc-dev, linux-sh, linux-pm, linux-acpi, gfs2,
	xen-devel, linux-s390, linux-mtd, amd-gfx, dri-devel,
	linux-kernel, Ian Rogers

Export cpufreq_dbs_data_release() and set .kobj_type.release in the
ondemand and conservative governors so their gov_attr_set kobjects have
a valid release callback, matching cpufreq_ governor_dbs.

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

Fixes: c4435630361d ("cpufreq: governor: New sysfs show/store callbacks for governor tunables")
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
---
 drivers/cpufreq/cpufreq_conservative.c | 5 ++++-
 drivers/cpufreq/cpufreq_governor.c     | 3 ++-
 drivers/cpufreq/cpufreq_governor.h     | 1 +
 drivers/cpufreq/cpufreq_ondemand.c     | 5 ++++-
 4 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 0b32ae28ec85..38c3bd5bf75a 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -316,7 +316,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 710d93ec89b5..97b64985927d 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -404,7 +404,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;
@@ -412,6 +412,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)
 {
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h
index 73b8ed7cfaae..c03d067f42eb 100644
--- a/drivers/cpufreq/cpufreq_governor.h
+++ b/drivers/cpufreq/cpufreq_governor.h
@@ -148,6 +148,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.385.gd3acb90ef8-goog


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

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

* [PATCH 05/11] ACPI: CPPC: Free cpc_desc in kobject release callback
  2026-10-13 22:39 ` Ian Rogers
@ 2026-10-13 22:39   ` Ian Rogers
  -1 siblings, 0 replies; 40+ messages in thread
From: Ian Rogers @ 2026-10-13 22:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, driver-core, llvm, linux-hardening,
	linux-doc, linuxppc-dev, linux-sh, linux-pm, linux-acpi, gfs2,
	xen-devel, linux-s390, linux-mtd, amd-gfx, dri-devel,
	linux-kernel, Ian Rogers

cpc_desc_ptr embeds a struct kobject that is registered in sysfs via
kobject_init_and_add(), but cppc_ktype lacked a .release callback and
acpi_cppc_processor_exit() freed cpc_ptr immediately after kobject_put().
With CONFIG_DEBUG_KOBJECT_RELEASE=y, this causes a use-after-free when
kobject_delayed_cleanup() runs on freed memory.

Move the sys_mem_vaddr unmapping and kfree(cpc_ptr) into a new
cppc_release() callback on cppc_ktype, and initialize the kobject on
allocation so kobject_put() handles cleanup in all paths.

Fixes: 158c998ea44b ("ACPI / CPPC: add sysfs support to compute delivered performance")
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
---
 drivers/acpi/cppc_acpi.c | 39 ++++++++++++++++++---------------------
 1 file changed, 18 insertions(+), 21 deletions(-)

diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
index fef54fcd00b7..2a80404f85d3 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
@@ -297,7 +297,22 @@ static struct attribute *cppc_attrs[] = {
 };
 ATTRIBUTE_GROUPS(cppc);
 
+static void cppc_release(struct kobject *kobj)
+{
+	struct cpc_desc *cpc_ptr = to_cpc_desc(kobj);
+	unsigned int i;
+
+	for (i = 2; i < cpc_ptr->num_entries; i++) {
+		void __iomem *addr = cpc_ptr->cpc_regs[i - 2].sys_mem_vaddr;
+
+		if (addr)
+			iounmap(addr);
+	}
+	kfree(cpc_ptr);
+}
+
 static const struct kobj_type cppc_ktype = {
+	.release = cppc_release,
 	.sysfs_ops = &kobj_sysfs_ops,
 	.default_groups = cppc_groups,
 };
@@ -799,6 +814,7 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
 		ret = -ENOMEM;
 		goto out_buf_free;
 	}
+	kobject_init(&cpc_ptr->kobj, &cppc_ktype);
 
 	/* First entry is NumEntries. */
 	cpc_obj = &out_obj->package.elements[0];
@@ -1001,11 +1017,9 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
 	/* Plug PSD data into this CPU's CPC descriptor. */
 	per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr;
 
-	ret = kobject_init_and_add(&cpc_ptr->kobj, &cppc_ktype, &cpu_dev->kobj,
-			"acpi_cppc");
+	ret = kobject_add(&cpc_ptr->kobj, &cpu_dev->kobj, "acpi_cppc");
 	if (ret) {
 		per_cpu(cpc_desc_ptr, pr->id) = NULL;
-		kobject_put(&cpc_ptr->kobj);
 		goto out_free;
 	}
 
@@ -1013,14 +1027,7 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
 	return 0;
 
 out_free:
-	/* Free all the mapped sys mem areas for this CPU */
-	for (i = 2; i < cpc_ptr->num_entries; i++) {
-		void __iomem *addr = cpc_ptr->cpc_regs[i-2].sys_mem_vaddr;
-
-		if (addr)
-			iounmap(addr);
-	}
-	kfree(cpc_ptr);
+	kobject_put(&cpc_ptr->kobj);
 
 out_buf_free:
 	kfree(output.pointer);
@@ -1037,8 +1044,6 @@ EXPORT_SYMBOL_GPL(acpi_cppc_processor_probe);
 void acpi_cppc_processor_exit(struct acpi_processor *pr)
 {
 	struct cpc_desc *cpc_ptr;
-	unsigned int i;
-	void __iomem *addr;
 	int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, pr->id);
 
 	if (pcc_ss_id >= 0 && pcc_data[pcc_ss_id]) {
@@ -1056,15 +1061,7 @@ void acpi_cppc_processor_exit(struct acpi_processor *pr)
 	if (!cpc_ptr)
 		return;
 
-	/* Free all the mapped sys mem areas for this CPU */
-	for (i = 2; i < cpc_ptr->num_entries; i++) {
-		addr = cpc_ptr->cpc_regs[i-2].sys_mem_vaddr;
-		if (addr)
-			iounmap(addr);
-	}
-
 	kobject_put(&cpc_ptr->kobj);
-	kfree(cpc_ptr);
 }
 EXPORT_SYMBOL_GPL(acpi_cppc_processor_exit);
 
-- 
2.56.0.385.gd3acb90ef8-goog


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

* [PATCH 05/11] ACPI: CPPC: Free cpc_desc in kobject release callback
@ 2026-10-13 22:39   ` Ian Rogers
  0 siblings, 0 replies; 40+ messages in thread
From: Ian Rogers @ 2026-10-13 22:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, driver-core, llvm, linux-hardening,
	linux-doc, linuxppc-dev, linux-sh, linux-pm, linux-acpi, gfs2,
	xen-devel, linux-s390, linux-mtd, amd-gfx, dri-devel,
	linux-kernel, Ian Rogers

cpc_desc_ptr embeds a struct kobject that is registered in sysfs via
kobject_init_and_add(), but cppc_ktype lacked a .release callback and
acpi_cppc_processor_exit() freed cpc_ptr immediately after kobject_put().
With CONFIG_DEBUG_KOBJECT_RELEASE=y, this causes a use-after-free when
kobject_delayed_cleanup() runs on freed memory.

Move the sys_mem_vaddr unmapping and kfree(cpc_ptr) into a new
cppc_release() callback on cppc_ktype, and initialize the kobject on
allocation so kobject_put() handles cleanup in all paths.

Fixes: 158c998ea44b ("ACPI / CPPC: add sysfs support to compute delivered performance")
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
---
 drivers/acpi/cppc_acpi.c | 39 ++++++++++++++++++---------------------
 1 file changed, 18 insertions(+), 21 deletions(-)

diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
index fef54fcd00b7..2a80404f85d3 100644
--- a/drivers/acpi/cppc_acpi.c
+++ b/drivers/acpi/cppc_acpi.c
@@ -297,7 +297,22 @@ static struct attribute *cppc_attrs[] = {
 };
 ATTRIBUTE_GROUPS(cppc);
 
+static void cppc_release(struct kobject *kobj)
+{
+	struct cpc_desc *cpc_ptr = to_cpc_desc(kobj);
+	unsigned int i;
+
+	for (i = 2; i < cpc_ptr->num_entries; i++) {
+		void __iomem *addr = cpc_ptr->cpc_regs[i - 2].sys_mem_vaddr;
+
+		if (addr)
+			iounmap(addr);
+	}
+	kfree(cpc_ptr);
+}
+
 static const struct kobj_type cppc_ktype = {
+	.release = cppc_release,
 	.sysfs_ops = &kobj_sysfs_ops,
 	.default_groups = cppc_groups,
 };
@@ -799,6 +814,7 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
 		ret = -ENOMEM;
 		goto out_buf_free;
 	}
+	kobject_init(&cpc_ptr->kobj, &cppc_ktype);
 
 	/* First entry is NumEntries. */
 	cpc_obj = &out_obj->package.elements[0];
@@ -1001,11 +1017,9 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
 	/* Plug PSD data into this CPU's CPC descriptor. */
 	per_cpu(cpc_desc_ptr, pr->id) = cpc_ptr;
 
-	ret = kobject_init_and_add(&cpc_ptr->kobj, &cppc_ktype, &cpu_dev->kobj,
-			"acpi_cppc");
+	ret = kobject_add(&cpc_ptr->kobj, &cpu_dev->kobj, "acpi_cppc");
 	if (ret) {
 		per_cpu(cpc_desc_ptr, pr->id) = NULL;
-		kobject_put(&cpc_ptr->kobj);
 		goto out_free;
 	}
 
@@ -1013,14 +1027,7 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
 	return 0;
 
 out_free:
-	/* Free all the mapped sys mem areas for this CPU */
-	for (i = 2; i < cpc_ptr->num_entries; i++) {
-		void __iomem *addr = cpc_ptr->cpc_regs[i-2].sys_mem_vaddr;
-
-		if (addr)
-			iounmap(addr);
-	}
-	kfree(cpc_ptr);
+	kobject_put(&cpc_ptr->kobj);
 
 out_buf_free:
 	kfree(output.pointer);
@@ -1037,8 +1044,6 @@ EXPORT_SYMBOL_GPL(acpi_cppc_processor_probe);
 void acpi_cppc_processor_exit(struct acpi_processor *pr)
 {
 	struct cpc_desc *cpc_ptr;
-	unsigned int i;
-	void __iomem *addr;
 	int pcc_ss_id = per_cpu(cpu_pcc_subspace_idx, pr->id);
 
 	if (pcc_ss_id >= 0 && pcc_data[pcc_ss_id]) {
@@ -1056,15 +1061,7 @@ void acpi_cppc_processor_exit(struct acpi_processor *pr)
 	if (!cpc_ptr)
 		return;
 
-	/* Free all the mapped sys mem areas for this CPU */
-	for (i = 2; i < cpc_ptr->num_entries; i++) {
-		addr = cpc_ptr->cpc_regs[i-2].sys_mem_vaddr;
-		if (addr)
-			iounmap(addr);
-	}
-
 	kobject_put(&cpc_ptr->kobj);
-	kfree(cpc_ptr);
 }
 EXPORT_SYMBOL_GPL(acpi_cppc_processor_exit);
 
-- 
2.56.0.385.gd3acb90ef8-goog


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

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

* [PATCH 06/11] dlm: Free dlm_ls in kobject release callback
  2026-10-13 22:39 ` Ian Rogers
@ 2026-10-13 22:39   ` Ian Rogers
  -1 siblings, 0 replies; 40+ messages in thread
From: Ian Rogers @ 2026-10-13 22:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, driver-core, llvm, linux-hardening,
	linux-doc, linuxppc-dev, linux-sh, linux-pm, linux-acpi, gfs2,
	xen-devel, linux-s390, linux-mtd, amd-gfx, dri-devel,
	linux-kernel, Ian Rogers

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
kobject release runs causes a use-after-free.

Add dlm_ls_release() to free struct dlm_ls when the last reference to
ls_kobj is dropped, use kobject_del() in release_lockspace(), and drop
the final kobject reference in free_lockspace().

Fixes: 3514faca19a6 ("kobject: remove struct kobj_type from struct kset")
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
---
 fs/dlm/lockspace.c | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index a9c98b4f378f..1d226b27d8e6 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);
+
+	kfree(ls);
+}
+
 static struct kobj_type dlm_ktype = {
+	.release        = dlm_ls_release,
 	.default_groups = dlm_groups,
 	.sysfs_ops     = &dlm_attr_ops,
 };
@@ -355,7 +363,7 @@ static void free_lockspace(struct work_struct *work)
 	 */
 	rhashtable_free_and_destroy(&ls->ls_rsbtbl, rhash_free_rsb, NULL);
 
-	kfree(ls);
+	kobject_put(&ls->ls_kobj);
 }
 
 static int new_lockspace(const char *name, const char *cluster,
@@ -436,6 +444,8 @@ static int new_lockspace(const char *name, const char *cluster,
 	atomic_set(&ls->ls_count, 0);
 	init_waitqueue_head(&ls->ls_count_wait);
 	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 +577,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);
@@ -615,7 +623,6 @@ static int new_lockspace(const char *name, const char *cluster,
 	rhashtable_destroy(&ls->ls_rsbtbl);
  out_lsfree:
 	kobject_put(&ls->ls_kobj);
-	kfree(ls);
  out:
 	module_put(THIS_MODULE);
 	return error;
@@ -759,7 +766,7 @@ static int release_lockspace(struct dlm_ls *ls, unsigned int release_option)
 
 	dlm_delete_debug_file(ls);
 
-	kobject_put(&ls->ls_kobj);
+	kobject_del(&ls->ls_kobj);
 
 	xa_destroy(&ls->ls_recover_xa);
 	kfree(ls->ls_recover_buf);
-- 
2.56.0.385.gd3acb90ef8-goog


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

* [PATCH 06/11] dlm: Free dlm_ls in kobject release callback
@ 2026-10-13 22:39   ` Ian Rogers
  0 siblings, 0 replies; 40+ messages in thread
From: Ian Rogers @ 2026-10-13 22:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, driver-core, llvm, linux-hardening,
	linux-doc, linuxppc-dev, linux-sh, linux-pm, linux-acpi, gfs2,
	xen-devel, linux-s390, linux-mtd, amd-gfx, dri-devel,
	linux-kernel, Ian Rogers

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
kobject release runs causes a use-after-free.

Add dlm_ls_release() to free struct dlm_ls when the last reference to
ls_kobj is dropped, use kobject_del() in release_lockspace(), and drop
the final kobject reference in free_lockspace().

Fixes: 3514faca19a6 ("kobject: remove struct kobj_type from struct kset")
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
---
 fs/dlm/lockspace.c | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index a9c98b4f378f..1d226b27d8e6 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);
+
+	kfree(ls);
+}
+
 static struct kobj_type dlm_ktype = {
+	.release        = dlm_ls_release,
 	.default_groups = dlm_groups,
 	.sysfs_ops     = &dlm_attr_ops,
 };
@@ -355,7 +363,7 @@ static void free_lockspace(struct work_struct *work)
 	 */
 	rhashtable_free_and_destroy(&ls->ls_rsbtbl, rhash_free_rsb, NULL);
 
-	kfree(ls);
+	kobject_put(&ls->ls_kobj);
 }
 
 static int new_lockspace(const char *name, const char *cluster,
@@ -436,6 +444,8 @@ static int new_lockspace(const char *name, const char *cluster,
 	atomic_set(&ls->ls_count, 0);
 	init_waitqueue_head(&ls->ls_count_wait);
 	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 +577,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);
@@ -615,7 +623,6 @@ static int new_lockspace(const char *name, const char *cluster,
 	rhashtable_destroy(&ls->ls_rsbtbl);
  out_lsfree:
 	kobject_put(&ls->ls_kobj);
-	kfree(ls);
  out:
 	module_put(THIS_MODULE);
 	return error;
@@ -759,7 +766,7 @@ static int release_lockspace(struct dlm_ls *ls, unsigned int release_option)
 
 	dlm_delete_debug_file(ls);
 
-	kobject_put(&ls->ls_kobj);
+	kobject_del(&ls->ls_kobj);
 
 	xa_destroy(&ls->ls_recover_xa);
 	kfree(ls->ls_recover_buf);
-- 
2.56.0.385.gd3acb90ef8-goog


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

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

* [PATCH 07/11] xen/sys-hypervisor: Add release callback to hyp_sysfs_kobj_type
  2026-10-13 22:39 ` Ian Rogers
@ 2026-10-13 22:39   ` Ian Rogers
  -1 siblings, 0 replies; 40+ messages in thread
From: Ian Rogers @ 2026-10-13 22:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, driver-core, llvm, linux-hardening,
	linux-doc, linuxppc-dev, linux-sh, linux-pm, linux-acpi, gfs2,
	xen-devel, linux-s390, linux-mtd, amd-gfx, dri-devel,
	linux-kernel, Ian Rogers

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")
Assisted-by: Antigravity:gemini-3.1-pro
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.385.gd3acb90ef8-goog


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

* [PATCH 07/11] xen/sys-hypervisor: Add release callback to hyp_sysfs_kobj_type
@ 2026-10-13 22:39   ` Ian Rogers
  0 siblings, 0 replies; 40+ messages in thread
From: Ian Rogers @ 2026-10-13 22:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, driver-core, llvm, linux-hardening,
	linux-doc, linuxppc-dev, linux-sh, linux-pm, linux-acpi, gfs2,
	xen-devel, linux-s390, linux-mtd, amd-gfx, dri-devel,
	linux-kernel, Ian Rogers

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")
Assisted-by: Antigravity:gemini-3.1-pro
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.385.gd3acb90ef8-goog


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

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

* [PATCH 08/11] s390/sclp_mem: Allocate struct sclp_mem dynamically and add kobject release
  2026-10-13 22:39 ` Ian Rogers
@ 2026-10-13 22:39   ` Ian Rogers
  -1 siblings, 0 replies; 40+ messages in thread
From: Ian Rogers @ 2026-10-13 22:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, driver-core, llvm, linux-hardening,
	linux-doc, linuxppc-dev, linux-sh, linux-pm, linux-acpi, gfs2,
	xen-devel, linux-s390, linux-mtd, amd-gfx, dri-devel,
	linux-kernel, Ian Rogers

sclp_init_mem() allocated a single array of struct sclp_mem with
kzalloc_objs() and registered each embedded kobject using a kobj_type
without a .release callback. Allocate each struct sclp_mem individually
with kzalloc_obj() instead and add sclp_mem_release() to free it.

Fixes: ff18dcb19aab ("s390/sclp: Add support for dynamic (de)configuration of memory")
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
---
 drivers/s390/char/sclp_mem.c | 73 +++++++++++++++++-------------------
 1 file changed, 34 insertions(+), 39 deletions(-)

diff --git a/drivers/s390/char/sclp_mem.c b/drivers/s390/char/sclp_mem.c
index 6df1926d4c62..f7c161e0d836 100644
--- a/drivers/s390/char/sclp_mem.c
+++ b/drivers/s390/char/sclp_mem.c
@@ -49,11 +49,6 @@ struct sclp_mem {
 #endif
 };
 
-struct sclp_mem_arg {
-	struct sclp_mem *sclp_mems;
-	struct kset *kset;
-};
-
 struct assign_storage_sccb {
 	struct sccb_header header;
 	u16 rn;
@@ -304,7 +299,15 @@ static ssize_t sclp_memmap_on_memory_store(struct kobject *kobj, struct kobj_att
 	return rc ? rc : count;
 }
 
+static void sclp_mem_release(struct kobject *kobj)
+{
+	struct sclp_mem *sclp_mem = container_of(kobj, struct sclp_mem, kobj);
+
+	kfree(sclp_mem);
+}
+
 static const struct kobj_type ktype = {
+	.release = sclp_mem_release,
 	.sysfs_ops = &kobj_sysfs_ops,
 };
 
@@ -321,36 +324,40 @@ static struct attribute_group sclp_mem_attr_group = {
 	.attrs = sclp_mem_attrs,
 };
 
-static int sclp_create_mem(struct sclp_mem *sclp_mem, struct kset *kset,
-			   unsigned int id, bool config, bool memmap_on_memory)
+static int sclp_create_mem(struct kset *kset, unsigned int id, bool config,
+			   bool memmap_on_memory)
 {
+	struct sclp_mem *sclp_mem;
 	int rc;
 
+	sclp_mem = kzalloc_obj(*sclp_mem);
+	if (!sclp_mem)
+		return -ENOMEM;
 	sclp_mem->memmap_on_memory = memmap_on_memory;
 	sclp_mem->config = config;
 #ifdef CONFIG_KASAN
 	sclp_mem->early_shadow_mapped = config;
 #endif
 	sclp_mem->id = id;
-	kobject_init(&sclp_mem->kobj, &ktype);
-	rc = kobject_add(&sclp_mem->kobj, &kset->kobj, "memory%d", id);
-	if (rc)
+	rc = kobject_init_and_add(&sclp_mem->kobj, &ktype, &kset->kobj,
+				  "memory%d", id);
+	if (rc) {
+		kobject_put(&sclp_mem->kobj);
 		return rc;
-	return sysfs_create_group(&sclp_mem->kobj, &sclp_mem_attr_group);
+	}
+	rc = sysfs_create_group(&sclp_mem->kobj, &sclp_mem_attr_group);
+	if (rc) {
+		kobject_put(&sclp_mem->kobj);
+		return rc;
+	}
+	return 0;
 }
 
 static int sclp_create_configured_mem(struct memory_block *mem, void *argument)
 {
-	struct sclp_mem *sclp_mems;
-	struct sclp_mem_arg *arg;
-	struct kset *kset;
-	unsigned int id;
+	struct kset *kset = argument;
 
-	id = mem->dev.id;
-	arg = (struct sclp_mem_arg *)argument;
-	sclp_mems = arg->sclp_mems;
-	kset = arg->kset;
-	return sclp_create_mem(&sclp_mems[id], kset, id, true, false);
+	return sclp_create_mem(kset, mem->dev.id, true, false);
 }
 
 static void __init align_to_block_size(unsigned long *start,
@@ -368,8 +375,7 @@ static void __init align_to_block_size(unsigned long *start,
 	*size = size_align;
 }
 
-static int __init sclp_create_standby_mems_merged(struct sclp_mem *sclp_mems,
-						  struct kset *kset, u16 rn)
+static int __init sclp_create_standby_mems_merged(struct kset *kset, u16 rn)
 {
 	unsigned long start, size, addr, block_size;
 	static u16 first_rn, num;
@@ -394,7 +400,7 @@ static int __init sclp_create_standby_mems_merged(struct sclp_mem *sclp_mems,
 		goto skip_add;
 	for (addr = start; addr < start + size; addr += block_size) {
 		id = addr / block_size;
-		rc = sclp_create_mem(&sclp_mems[id], kset, id, false,
+		rc = sclp_create_mem(kset, id, false,
 				     mhp_supports_memmap_on_memory());
 		if (rc)
 			break;
@@ -405,45 +411,34 @@ static int __init sclp_create_standby_mems_merged(struct sclp_mem *sclp_mems,
 	return rc;
 }
 
-static int __init sclp_create_standby_mems(struct sclp_mem *sclp_mems, struct kset *kset)
+static int __init sclp_create_standby_mems(struct kset *kset)
 {
 	struct memory_increment *incr;
 	int rc = 0;
 
 	list_for_each_entry(incr, &sclp_mem_list, list) {
 		if (incr->standby)
-			rc = sclp_create_standby_mems_merged(sclp_mems, kset, incr->rn);
+			rc = sclp_create_standby_mems_merged(kset, incr->rn);
 		if (rc)
 			return rc;
 	}
-	return sclp_create_standby_mems_merged(sclp_mems, kset, 0);
+	return sclp_create_standby_mems_merged(kset, 0);
 }
 
 static int __init sclp_init_mem(void)
 {
-	const unsigned long block_size = memory_block_size_bytes();
-	unsigned int max_sclp_mems;
-	struct sclp_mem *sclp_mems;
-	struct sclp_mem_arg arg;
 	struct kset *kset;
 	int rc;
 
-	max_sclp_mems = roundup(sclp.rnmax * sclp.rzm, block_size) / block_size;
-	/* Allocate memory for all blocks ahead of time. */
-	sclp_mems = kzalloc_objs(struct sclp_mem, max_sclp_mems);
-	if (!sclp_mems)
-		return -ENOMEM;
 	kset = kset_create_and_add("memory", NULL, firmware_kobj);
 	if (!kset)
 		return -ENOMEM;
 	/* Initial memory is in the "configured" state already. */
-	arg.sclp_mems = sclp_mems;
-	arg.kset = kset;
-	rc = for_each_memory_block(&arg, sclp_create_configured_mem);
+	rc = for_each_memory_block(kset, sclp_create_configured_mem);
 	if (rc)
 		return rc;
 	/* Standby memory is "deconfigured". */
-	return sclp_create_standby_mems(sclp_mems, kset);
+	return sclp_create_standby_mems(kset);
 }
 
 static void __init insert_increment(u16 rn, int standby, int assigned)
-- 
2.56.0.385.gd3acb90ef8-goog



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

* [PATCH 08/11] s390/sclp_mem: Allocate struct sclp_mem dynamically and add kobject release
@ 2026-10-13 22:39   ` Ian Rogers
  0 siblings, 0 replies; 40+ messages in thread
From: Ian Rogers @ 2026-10-13 22:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, driver-core, llvm, linux-hardening,
	linux-doc, linuxppc-dev, linux-sh, linux-pm, linux-acpi, gfs2,
	xen-devel, linux-s390, linux-mtd, amd-gfx, dri-devel,
	linux-kernel, Ian Rogers

sclp_init_mem() allocated a single array of struct sclp_mem with
kzalloc_objs() and registered each embedded kobject using a kobj_type
without a .release callback. Allocate each struct sclp_mem individually
with kzalloc_obj() instead and add sclp_mem_release() to free it.

Fixes: ff18dcb19aab ("s390/sclp: Add support for dynamic (de)configuration of memory")
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
---
 drivers/s390/char/sclp_mem.c | 73 +++++++++++++++++-------------------
 1 file changed, 34 insertions(+), 39 deletions(-)

diff --git a/drivers/s390/char/sclp_mem.c b/drivers/s390/char/sclp_mem.c
index 6df1926d4c62..f7c161e0d836 100644
--- a/drivers/s390/char/sclp_mem.c
+++ b/drivers/s390/char/sclp_mem.c
@@ -49,11 +49,6 @@ struct sclp_mem {
 #endif
 };
 
-struct sclp_mem_arg {
-	struct sclp_mem *sclp_mems;
-	struct kset *kset;
-};
-
 struct assign_storage_sccb {
 	struct sccb_header header;
 	u16 rn;
@@ -304,7 +299,15 @@ static ssize_t sclp_memmap_on_memory_store(struct kobject *kobj, struct kobj_att
 	return rc ? rc : count;
 }
 
+static void sclp_mem_release(struct kobject *kobj)
+{
+	struct sclp_mem *sclp_mem = container_of(kobj, struct sclp_mem, kobj);
+
+	kfree(sclp_mem);
+}
+
 static const struct kobj_type ktype = {
+	.release = sclp_mem_release,
 	.sysfs_ops = &kobj_sysfs_ops,
 };
 
@@ -321,36 +324,40 @@ static struct attribute_group sclp_mem_attr_group = {
 	.attrs = sclp_mem_attrs,
 };
 
-static int sclp_create_mem(struct sclp_mem *sclp_mem, struct kset *kset,
-			   unsigned int id, bool config, bool memmap_on_memory)
+static int sclp_create_mem(struct kset *kset, unsigned int id, bool config,
+			   bool memmap_on_memory)
 {
+	struct sclp_mem *sclp_mem;
 	int rc;
 
+	sclp_mem = kzalloc_obj(*sclp_mem);
+	if (!sclp_mem)
+		return -ENOMEM;
 	sclp_mem->memmap_on_memory = memmap_on_memory;
 	sclp_mem->config = config;
 #ifdef CONFIG_KASAN
 	sclp_mem->early_shadow_mapped = config;
 #endif
 	sclp_mem->id = id;
-	kobject_init(&sclp_mem->kobj, &ktype);
-	rc = kobject_add(&sclp_mem->kobj, &kset->kobj, "memory%d", id);
-	if (rc)
+	rc = kobject_init_and_add(&sclp_mem->kobj, &ktype, &kset->kobj,
+				  "memory%d", id);
+	if (rc) {
+		kobject_put(&sclp_mem->kobj);
 		return rc;
-	return sysfs_create_group(&sclp_mem->kobj, &sclp_mem_attr_group);
+	}
+	rc = sysfs_create_group(&sclp_mem->kobj, &sclp_mem_attr_group);
+	if (rc) {
+		kobject_put(&sclp_mem->kobj);
+		return rc;
+	}
+	return 0;
 }
 
 static int sclp_create_configured_mem(struct memory_block *mem, void *argument)
 {
-	struct sclp_mem *sclp_mems;
-	struct sclp_mem_arg *arg;
-	struct kset *kset;
-	unsigned int id;
+	struct kset *kset = argument;
 
-	id = mem->dev.id;
-	arg = (struct sclp_mem_arg *)argument;
-	sclp_mems = arg->sclp_mems;
-	kset = arg->kset;
-	return sclp_create_mem(&sclp_mems[id], kset, id, true, false);
+	return sclp_create_mem(kset, mem->dev.id, true, false);
 }
 
 static void __init align_to_block_size(unsigned long *start,
@@ -368,8 +375,7 @@ static void __init align_to_block_size(unsigned long *start,
 	*size = size_align;
 }
 
-static int __init sclp_create_standby_mems_merged(struct sclp_mem *sclp_mems,
-						  struct kset *kset, u16 rn)
+static int __init sclp_create_standby_mems_merged(struct kset *kset, u16 rn)
 {
 	unsigned long start, size, addr, block_size;
 	static u16 first_rn, num;
@@ -394,7 +400,7 @@ static int __init sclp_create_standby_mems_merged(struct sclp_mem *sclp_mems,
 		goto skip_add;
 	for (addr = start; addr < start + size; addr += block_size) {
 		id = addr / block_size;
-		rc = sclp_create_mem(&sclp_mems[id], kset, id, false,
+		rc = sclp_create_mem(kset, id, false,
 				     mhp_supports_memmap_on_memory());
 		if (rc)
 			break;
@@ -405,45 +411,34 @@ static int __init sclp_create_standby_mems_merged(struct sclp_mem *sclp_mems,
 	return rc;
 }
 
-static int __init sclp_create_standby_mems(struct sclp_mem *sclp_mems, struct kset *kset)
+static int __init sclp_create_standby_mems(struct kset *kset)
 {
 	struct memory_increment *incr;
 	int rc = 0;
 
 	list_for_each_entry(incr, &sclp_mem_list, list) {
 		if (incr->standby)
-			rc = sclp_create_standby_mems_merged(sclp_mems, kset, incr->rn);
+			rc = sclp_create_standby_mems_merged(kset, incr->rn);
 		if (rc)
 			return rc;
 	}
-	return sclp_create_standby_mems_merged(sclp_mems, kset, 0);
+	return sclp_create_standby_mems_merged(kset, 0);
 }
 
 static int __init sclp_init_mem(void)
 {
-	const unsigned long block_size = memory_block_size_bytes();
-	unsigned int max_sclp_mems;
-	struct sclp_mem *sclp_mems;
-	struct sclp_mem_arg arg;
 	struct kset *kset;
 	int rc;
 
-	max_sclp_mems = roundup(sclp.rnmax * sclp.rzm, block_size) / block_size;
-	/* Allocate memory for all blocks ahead of time. */
-	sclp_mems = kzalloc_objs(struct sclp_mem, max_sclp_mems);
-	if (!sclp_mems)
-		return -ENOMEM;
 	kset = kset_create_and_add("memory", NULL, firmware_kobj);
 	if (!kset)
 		return -ENOMEM;
 	/* Initial memory is in the "configured" state already. */
-	arg.sclp_mems = sclp_mems;
-	arg.kset = kset;
-	rc = for_each_memory_block(&arg, sclp_create_configured_mem);
+	rc = for_each_memory_block(kset, sclp_create_configured_mem);
 	if (rc)
 		return rc;
 	/* Standby memory is "deconfigured". */
-	return sclp_create_standby_mems(sclp_mems, kset);
+	return sclp_create_standby_mems(kset);
 }
 
 static void __init insert_increment(u16 rn, int standby, int assigned)
-- 
2.56.0.385.gd3acb90ef8-goog


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

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

* [PATCH 09/11] ubifs: sysfs: Use kset_create_and_add() for ubifs_kset
  2026-10-13 22:39 ` Ian Rogers
@ 2026-10-13 22:39   ` Ian Rogers
  -1 siblings, 0 replies; 40+ messages in thread
From: Ian Rogers @ 2026-10-13 22:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, driver-core, llvm, linux-hardening,
	linux-doc, linuxppc-dev, linux-sh, linux-pm, linux-acpi, gfs2,
	xen-devel, linux-s390, linux-mtd, amd-gfx, dri-devel,
	linux-kernel, Ian Rogers

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()")
Assisted-by: Antigravity:gemini-3.1-pro
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.385.gd3acb90ef8-goog


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

* [PATCH 09/11] ubifs: sysfs: Use kset_create_and_add() for ubifs_kset
@ 2026-10-13 22:39   ` Ian Rogers
  0 siblings, 0 replies; 40+ messages in thread
From: Ian Rogers @ 2026-10-13 22:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, driver-core, llvm, linux-hardening,
	linux-doc, linuxppc-dev, linux-sh, linux-pm, linux-acpi, gfs2,
	xen-devel, linux-s390, linux-mtd, amd-gfx, dri-devel,
	linux-kernel, Ian Rogers

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()")
Assisted-by: Antigravity:gemini-3.1-pro
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.385.gd3acb90ef8-goog


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

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

* [PATCH 10/11] drm/amdkfd: Free queue in procfs_queue_type kobject release callback
  2026-10-13 22:39 ` Ian Rogers
@ 2026-10-13 22:39   ` Ian Rogers
  -1 siblings, 0 replies; 40+ messages in thread
From: Ian Rogers @ 2026-10-13 22:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, driver-core, llvm, linux-hardening,
	linux-doc, linuxppc-dev, linux-sh, linux-pm, linux-acpi, gfs2,
	xen-devel, linux-s390, linux-mtd, amd-gfx, dri-devel,
	linux-kernel, Ian Rogers

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().

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

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index 0a7c1900da95..6099cb893573 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -510,7 +510,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,
 };
@@ -550,7 +558,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;
 	}
 
@@ -699,7 +706,6 @@ void kfd_procfs_del_queue(struct queue *q)
 		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 15eeaaebbbcd..8d1afc5b47e2 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.385.gd3acb90ef8-goog



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

* [PATCH 10/11] drm/amdkfd: Free queue in procfs_queue_type kobject release callback
@ 2026-10-13 22:39   ` Ian Rogers
  0 siblings, 0 replies; 40+ messages in thread
From: Ian Rogers @ 2026-10-13 22:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, driver-core, llvm, linux-hardening,
	linux-doc, linuxppc-dev, linux-sh, linux-pm, linux-acpi, gfs2,
	xen-devel, linux-s390, linux-mtd, amd-gfx, dri-devel,
	linux-kernel, Ian Rogers

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().

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

diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index 0a7c1900da95..6099cb893573 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -510,7 +510,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,
 };
@@ -550,7 +558,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;
 	}
 
@@ -699,7 +706,6 @@ void kfd_procfs_del_queue(struct queue *q)
 		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 15eeaaebbbcd..8d1afc5b47e2 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.385.gd3acb90ef8-goog


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

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

* [PATCH 11/11] kobject: Require explicit initialization of struct kobj_type::release
  2026-10-13 22:39 ` Ian Rogers
@ 2026-10-13 22:39   ` Ian Rogers
  -1 siblings, 0 replies; 40+ messages in thread
From: Ian Rogers @ 2026-10-13 22:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, driver-core, llvm, linux-hardening,
	linux-doc, linuxppc-dev, linux-sh, linux-pm, linux-acpi, gfs2,
	xen-devel, linux-s390, linux-mtd, amd-gfx, dri-devel,
	linux-kernel, Ian Rogers

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 __require_explicit_initialization
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, 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.

Link: https://lpc.events/event/20/contributions/2392/
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
---
 arch/arm64/kernel/cpuinfo.c                          | 2 ++
 drivers/acpi/sysfs.c                                 | 2 ++
 drivers/dma/ioat/sysfs.c                             | 2 ++
 drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c              | 4 ++++
 drivers/infiniband/hw/hfi1/sysfs.c                   | 2 ++
 drivers/infiniband/hw/usnic/usnic_ib_sysfs.c         | 2 ++
 drivers/parisc/pdc_stable.c                          | 2 ++
 drivers/power/supply/ab8500_fg.c                     | 2 ++
 drivers/soc/hisilicon/kunpeng_hccs.c                 | 6 ++++++
 drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c | 2 ++
 drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c | 2 ++
 drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c | 2 ++
 fs/erofs/sysfs.c                                     | 4 ++++
 fs/f2fs/sysfs.c                                      | 6 ++++++
 fs/ocfs2/cluster/masklog.c                           | 2 ++
 include/linux/kobject.h                              | 2 +-
 16 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 45c63f3d75c5..ab78efdb13f5 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -309,6 +309,8 @@ const struct seq_operations cpuinfo_op = {
 
 
 static const struct kobj_type cpuregs_kobj_type = {
+	/* 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 dd4a99f09efe..7534d3f305ba 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -972,6 +972,8 @@ static struct attribute *hotplug_profile_attrs[] = {
 ATTRIBUTE_GROUPS(hotplug_profile);
 
 static const struct kobj_type acpi_hotplug_profile_ktype = {
+	/* 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..7fdd0ca36b98 100644
--- a/drivers/dma/ioat/sysfs.c
+++ b/drivers/dma/ioat/sysfs.c
@@ -167,6 +167,8 @@ static const struct attribute *const ioat_attrs[] = {
 ATTRIBUTE_GROUPS(ioat);
 
 const struct kobj_type ioat_ktype = {
+	/* ioatdma_chan is allocated via devm_kzalloc() rather than freed by kobject_put(). */
+	.release = NULL,
 	.sysfs_ops = &ioat_sysfs_ops,
 	.default_groups = ioat_groups,
 };
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
index b15af318784b..0477468f12ae 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
@@ -789,6 +789,8 @@ static const struct sysfs_ops xcp_cfg_res_sysfs_ops = {
 };
 
 static const struct kobj_type xcp_cfg_res_sysfs_ktype = {
+	/* 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,
 };
@@ -1053,6 +1055,8 @@ static const struct attribute_group amdgpu_xcp_attrs_group = {
 };
 
 static const struct kobj_type xcp_sysfs_ktype = {
+	/* 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..33b26650069d 100644
--- a/drivers/infiniband/hw/hfi1/sysfs.c
+++ b/drivers/infiniband/hw/hfi1/sysfs.c
@@ -608,6 +608,8 @@ static const struct sysfs_ops sde_sysfs_ops = {
 };
 
 static struct kobj_type sde_ktype = {
+	/* sdma_engine is embedded in the 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..234d8d9532aa 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 = {
+	/* 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 16f4496bca95..6d972c965c1e 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -484,6 +484,8 @@ ATTRIBUTE_GROUPS(paths_subsys);
 
 /* Specific kobject type for our PDC paths */
 static const struct kobj_type ktype_pdcspath = {
+	/* 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..206ee2e392fb 100644
--- a/drivers/power/supply/ab8500_fg.c
+++ b/drivers/power/supply/ab8500_fg.c
@@ -2531,6 +2531,8 @@ static struct attribute *ab8500_fg_attrs[] = {
 ATTRIBUTE_GROUPS(ab8500_fg);
 
 static const struct kobj_type ab8500_fg_ktype = {
+	/* 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/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c
index 0cc2953d59a5..5d083d2b72ca 100644
--- a/drivers/soc/hisilicon/kunpeng_hccs.c
+++ b/drivers/soc/hisilicon/kunpeng_hccs.c
@@ -1038,6 +1038,8 @@ static struct attribute *hccs_port_default_attrs[] = {
 ATTRIBUTE_GROUPS(hccs_port_default);
 
 static const struct kobj_type hccs_port_type = {
+	/* hccs_port_info is allocated via devm_kcalloc() rather than freed by kobject_put(). */
+	.release = NULL,
 	.sysfs_ops = &hccs_comm_ops,
 	.default_groups = hccs_port_default_groups,
 };
@@ -1110,6 +1112,8 @@ static struct attribute *hccs_die_default_attrs[] = {
 ATTRIBUTE_GROUPS(hccs_die_default);
 
 static const struct kobj_type hccs_die_type = {
+	/* hccs_die_info is allocated via devm_kcalloc() rather than freed by kobject_put(). */
+	.release = NULL,
 	.sysfs_ops = &hccs_comm_ops,
 	.default_groups = hccs_die_default_groups,
 };
@@ -1213,6 +1217,8 @@ static struct attribute *hccs_chip_default_attrs[] = {
 ATTRIBUTE_GROUPS(hccs_chip_default);
 
 static const struct kobj_type hccs_chip_type = {
+	/* hccs_chip_info is allocated via devm_kcalloc() rather than freed by kobject_put(). */
+	.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..3d787245f5b5 100644
--- a/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c
+++ b/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c
@@ -304,6 +304,8 @@ static const struct sysfs_ops display_sysfs_ops = {
 };
 
 static struct kobj_type display_ktype = {
+	/* dssdev->kobj is embedded in struct omap_dss_device and zeroed in display_uninit_sysfs(). */
+	.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..cf816e83e903 100644
--- a/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c
+++ b/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c
@@ -496,6 +496,8 @@ static const struct sysfs_ops manager_sysfs_ops = {
 };
 
 static struct kobj_type manager_ktype = {
+	/* 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..9aa16b3dee5e 100644
--- a/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c
+++ b/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c
@@ -429,6 +429,8 @@ static const struct sysfs_ops overlay_sysfs_ops = {
 };
 
 static struct kobj_type overlay_ktype = {
+	/* ovl->kobj is embedded in static overlays[]; dss_overlay_kobj_uninit() only calls kobject_del(). */
+	.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..588d541e1713 100644
--- a/fs/erofs/sysfs.c
+++ b/fs/erofs/sysfs.c
@@ -238,6 +238,8 @@ static const struct kobj_type erofs_sb_ktype = {
 static const struct kobj_type erofs_ktype = {
 	.default_groups = erofs_groups,
 	.sysfs_ops	= &erofs_attr_ops,
+	/* erofs_root is a static struct kset; lifetime is not controlled by kobject_put(). */
+	.release	= NULL,
 };
 
 static struct kset erofs_root = {
@@ -247,6 +249,8 @@ static struct kset erofs_root = {
 static const struct kobj_type erofs_feat_ktype = {
 	.default_groups = erofs_feat_groups,
 	.sysfs_ops	= &erofs_attr_ops,
+	/* 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 811e350a1430..a66cef927c62 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -1653,6 +1653,8 @@ static const struct kobj_type f2fs_sb_ktype = {
 
 static const struct kobj_type f2fs_ktype = {
 	.sysfs_ops	= &f2fs_attr_ops,
+	/* f2fs_kset is a static struct kset; lifetime is not controlled by kobject_put(). */
+	.release	= NULL,
 };
 
 static struct kset f2fs_kset = {
@@ -1667,6 +1669,8 @@ 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,
+	/* f2fs_feat is a static struct kobject; lifetime is not controlled by kobject_put(). */
+	.release	= NULL,
 };
 
 static struct kobject f2fs_feat = {
@@ -1681,6 +1685,8 @@ 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,
+	/* 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..e476fa7ffea6 100644
--- a/fs/ocfs2/cluster/masklog.c
+++ b/fs/ocfs2/cluster/masklog.c
@@ -147,6 +147,8 @@ static const struct sysfs_ops mlog_attr_ops = {
 static struct kobj_type mlog_ktype = {
 	.default_groups = mlog_default_groups,
 	.sysfs_ops      = &mlog_attr_ops,
+	/* 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..e65331717e03 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) __require_explicit_initialization;
 	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.385.gd3acb90ef8-goog



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

* [PATCH 11/11] kobject: Require explicit initialization of struct kobj_type::release
@ 2026-10-13 22:39   ` Ian Rogers
  0 siblings, 0 replies; 40+ messages in thread
From: Ian Rogers @ 2026-10-13 22:39 UTC (permalink / raw)
  To: Greg Kroah-Hartman, Rafael J . Wysocki, Danilo Krummrich,
	Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, driver-core, llvm, linux-hardening,
	linux-doc, linuxppc-dev, linux-sh, linux-pm, linux-acpi, gfs2,
	xen-devel, linux-s390, linux-mtd, amd-gfx, dri-devel,
	linux-kernel, Ian Rogers

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 __require_explicit_initialization
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, 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.

Link: https://lpc.events/event/20/contributions/2392/
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Ian Rogers <irogers@google.com>
---
 arch/arm64/kernel/cpuinfo.c                          | 2 ++
 drivers/acpi/sysfs.c                                 | 2 ++
 drivers/dma/ioat/sysfs.c                             | 2 ++
 drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c              | 4 ++++
 drivers/infiniband/hw/hfi1/sysfs.c                   | 2 ++
 drivers/infiniband/hw/usnic/usnic_ib_sysfs.c         | 2 ++
 drivers/parisc/pdc_stable.c                          | 2 ++
 drivers/power/supply/ab8500_fg.c                     | 2 ++
 drivers/soc/hisilicon/kunpeng_hccs.c                 | 6 ++++++
 drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c | 2 ++
 drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c | 2 ++
 drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c | 2 ++
 fs/erofs/sysfs.c                                     | 4 ++++
 fs/f2fs/sysfs.c                                      | 6 ++++++
 fs/ocfs2/cluster/masklog.c                           | 2 ++
 include/linux/kobject.h                              | 2 +-
 16 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 45c63f3d75c5..ab78efdb13f5 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -309,6 +309,8 @@ const struct seq_operations cpuinfo_op = {
 
 
 static const struct kobj_type cpuregs_kobj_type = {
+	/* 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 dd4a99f09efe..7534d3f305ba 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -972,6 +972,8 @@ static struct attribute *hotplug_profile_attrs[] = {
 ATTRIBUTE_GROUPS(hotplug_profile);
 
 static const struct kobj_type acpi_hotplug_profile_ktype = {
+	/* 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..7fdd0ca36b98 100644
--- a/drivers/dma/ioat/sysfs.c
+++ b/drivers/dma/ioat/sysfs.c
@@ -167,6 +167,8 @@ static const struct attribute *const ioat_attrs[] = {
 ATTRIBUTE_GROUPS(ioat);
 
 const struct kobj_type ioat_ktype = {
+	/* ioatdma_chan is allocated via devm_kzalloc() rather than freed by kobject_put(). */
+	.release = NULL,
 	.sysfs_ops = &ioat_sysfs_ops,
 	.default_groups = ioat_groups,
 };
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
index b15af318784b..0477468f12ae 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
@@ -789,6 +789,8 @@ static const struct sysfs_ops xcp_cfg_res_sysfs_ops = {
 };
 
 static const struct kobj_type xcp_cfg_res_sysfs_ktype = {
+	/* 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,
 };
@@ -1053,6 +1055,8 @@ static const struct attribute_group amdgpu_xcp_attrs_group = {
 };
 
 static const struct kobj_type xcp_sysfs_ktype = {
+	/* 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..33b26650069d 100644
--- a/drivers/infiniband/hw/hfi1/sysfs.c
+++ b/drivers/infiniband/hw/hfi1/sysfs.c
@@ -608,6 +608,8 @@ static const struct sysfs_ops sde_sysfs_ops = {
 };
 
 static struct kobj_type sde_ktype = {
+	/* sdma_engine is embedded in the 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..234d8d9532aa 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 = {
+	/* 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 16f4496bca95..6d972c965c1e 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -484,6 +484,8 @@ ATTRIBUTE_GROUPS(paths_subsys);
 
 /* Specific kobject type for our PDC paths */
 static const struct kobj_type ktype_pdcspath = {
+	/* 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..206ee2e392fb 100644
--- a/drivers/power/supply/ab8500_fg.c
+++ b/drivers/power/supply/ab8500_fg.c
@@ -2531,6 +2531,8 @@ static struct attribute *ab8500_fg_attrs[] = {
 ATTRIBUTE_GROUPS(ab8500_fg);
 
 static const struct kobj_type ab8500_fg_ktype = {
+	/* 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/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c
index 0cc2953d59a5..5d083d2b72ca 100644
--- a/drivers/soc/hisilicon/kunpeng_hccs.c
+++ b/drivers/soc/hisilicon/kunpeng_hccs.c
@@ -1038,6 +1038,8 @@ static struct attribute *hccs_port_default_attrs[] = {
 ATTRIBUTE_GROUPS(hccs_port_default);
 
 static const struct kobj_type hccs_port_type = {
+	/* hccs_port_info is allocated via devm_kcalloc() rather than freed by kobject_put(). */
+	.release = NULL,
 	.sysfs_ops = &hccs_comm_ops,
 	.default_groups = hccs_port_default_groups,
 };
@@ -1110,6 +1112,8 @@ static struct attribute *hccs_die_default_attrs[] = {
 ATTRIBUTE_GROUPS(hccs_die_default);
 
 static const struct kobj_type hccs_die_type = {
+	/* hccs_die_info is allocated via devm_kcalloc() rather than freed by kobject_put(). */
+	.release = NULL,
 	.sysfs_ops = &hccs_comm_ops,
 	.default_groups = hccs_die_default_groups,
 };
@@ -1213,6 +1217,8 @@ static struct attribute *hccs_chip_default_attrs[] = {
 ATTRIBUTE_GROUPS(hccs_chip_default);
 
 static const struct kobj_type hccs_chip_type = {
+	/* hccs_chip_info is allocated via devm_kcalloc() rather than freed by kobject_put(). */
+	.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..3d787245f5b5 100644
--- a/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c
+++ b/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c
@@ -304,6 +304,8 @@ static const struct sysfs_ops display_sysfs_ops = {
 };
 
 static struct kobj_type display_ktype = {
+	/* dssdev->kobj is embedded in struct omap_dss_device and zeroed in display_uninit_sysfs(). */
+	.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..cf816e83e903 100644
--- a/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c
+++ b/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c
@@ -496,6 +496,8 @@ static const struct sysfs_ops manager_sysfs_ops = {
 };
 
 static struct kobj_type manager_ktype = {
+	/* 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..9aa16b3dee5e 100644
--- a/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c
+++ b/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c
@@ -429,6 +429,8 @@ static const struct sysfs_ops overlay_sysfs_ops = {
 };
 
 static struct kobj_type overlay_ktype = {
+	/* ovl->kobj is embedded in static overlays[]; dss_overlay_kobj_uninit() only calls kobject_del(). */
+	.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..588d541e1713 100644
--- a/fs/erofs/sysfs.c
+++ b/fs/erofs/sysfs.c
@@ -238,6 +238,8 @@ static const struct kobj_type erofs_sb_ktype = {
 static const struct kobj_type erofs_ktype = {
 	.default_groups = erofs_groups,
 	.sysfs_ops	= &erofs_attr_ops,
+	/* erofs_root is a static struct kset; lifetime is not controlled by kobject_put(). */
+	.release	= NULL,
 };
 
 static struct kset erofs_root = {
@@ -247,6 +249,8 @@ static struct kset erofs_root = {
 static const struct kobj_type erofs_feat_ktype = {
 	.default_groups = erofs_feat_groups,
 	.sysfs_ops	= &erofs_attr_ops,
+	/* 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 811e350a1430..a66cef927c62 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -1653,6 +1653,8 @@ static const struct kobj_type f2fs_sb_ktype = {
 
 static const struct kobj_type f2fs_ktype = {
 	.sysfs_ops	= &f2fs_attr_ops,
+	/* f2fs_kset is a static struct kset; lifetime is not controlled by kobject_put(). */
+	.release	= NULL,
 };
 
 static struct kset f2fs_kset = {
@@ -1667,6 +1669,8 @@ 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,
+	/* f2fs_feat is a static struct kobject; lifetime is not controlled by kobject_put(). */
+	.release	= NULL,
 };
 
 static struct kobject f2fs_feat = {
@@ -1681,6 +1685,8 @@ 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,
+	/* 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..e476fa7ffea6 100644
--- a/fs/ocfs2/cluster/masklog.c
+++ b/fs/ocfs2/cluster/masklog.c
@@ -147,6 +147,8 @@ static const struct sysfs_ops mlog_attr_ops = {
 static struct kobj_type mlog_ktype = {
 	.default_groups = mlog_default_groups,
 	.sysfs_ops      = &mlog_attr_ops,
+	/* 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..e65331717e03 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) __require_explicit_initialization;
 	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.385.gd3acb90ef8-goog


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

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

* Re: [PATCH 02/11] powerpc/secvar: Add missing kobject release callback to secvar_ktype
  2026-10-13 22:39   ` Ian Rogers
  (?)
@ 2026-10-13 22:47   ` sashiko-bot
  -1 siblings, 0 replies; 40+ messages in thread
From: sashiko-bot @ 2026-10-13 22:47 UTC (permalink / raw)
  To: Ian Rogers
  Cc: linux-s390, Heiko Carstens, Vasily Gorbik, Alexander Gordeev,
	Christian Borntraeger

> 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")
> Assisted-by: Antigravity:gemini-3.1-pro
> Signed-off-by: Ian Rogers <irogers@google.com>

Sashiko has reviewed this patch and found no issues. It looks great!

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


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

* Re: [PATCH 09/11] ubifs: sysfs: Use kset_create_and_add() for ubifs_kset
  2026-10-13 22:39   ` Ian Rogers
  (?)
@ 2026-10-13 22:47   ` sashiko-bot
  -1 siblings, 0 replies; 40+ messages in thread
From: sashiko-bot @ 2026-10-13 22:47 UTC (permalink / raw)
  To: Ian Rogers
  Cc: linux-s390, Heiko Carstens, Vasily Gorbik, Alexander Gordeev,
	Christian Borntraeger

> 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()")
> Assisted-by: Antigravity:gemini-3.1-pro
> Signed-off-by: Ian Rogers <irogers@google.com>

Sashiko has reviewed this patch and found no issues. It looks great!

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


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

* Re: [PATCH 01/11] Compiler Attributes: Add __require_explicit_initialization macro
  2026-10-13 22:39   ` Ian Rogers
  (?)
@ 2026-10-13 22:48   ` sashiko-bot
  -1 siblings, 0 replies; 40+ messages in thread
From: sashiko-bot @ 2026-10-13 22:48 UTC (permalink / raw)
  To: Ian Rogers
  Cc: linux-s390, Heiko Carstens, Vasily Gorbik, Alexander Gordeev,
	Christian Borntraeger

> 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 __require_explicit_initialization 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.
> 
> 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/
> Assisted-by: Antigravity:gemini-3.1-pro
> Signed-off-by: Ian Rogers <irogers@google.com>

Sashiko has reviewed this patch and found no issues. It looks great!

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


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

* Re: [PATCH 08/11] s390/sclp_mem: Allocate struct sclp_mem dynamically and add kobject release
  2026-10-13 22:39   ` Ian Rogers
@ 2026-10-13 22:48     ` sashiko-bot
  -1 siblings, 0 replies; 40+ messages in thread
From: sashiko-bot @ 2026-10-13 22:48 UTC (permalink / raw)
  To: Ian Rogers, Greg Kroah-Hartman, Rafael J . Wysocki,
	Danilo Krummrich, Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, linux-s390, linux-mtd, dri-devel

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] sysfs: kobject memory leak on init error paths and group creation race
- [Medium] sysfs: missing cleanup of previously allocated kobjects in initialization loops
--

commit 191798937bad0f272b0f72f4ae28579cab8672f8
Author: Ian Rogers <irogers@google.com>

s390/sclp_mem: Allocate struct sclp_mem dynamically and add kobject release

sclp_init_mem() allocated a single array of struct sclp_mem with
kzalloc_objs() and registered each embedded kobject using a kobj_type
without a .release callback. Allocate each struct sclp_mem individually
with kzalloc_obj() instead and add sclp_mem_release() to free it.

> diff --git a/drivers/s390/char/sclp_mem.c b/drivers/s390/char/sclp_mem.c
> index 78c054e26d177..40a7f92729751 100644
> --- a/drivers/s390/char/sclp_mem.c
> +++ b/drivers/s390/char/sclp_mem.c
[ ... ]
> @@ -322,36 +325,40 @@ static struct attribute_group sclp_mem_attr_group = {
>  	.attrs = sclp_mem_attrs,
>  };
>  
> -static int sclp_create_mem(struct sclp_mem *sclp_mem, struct kset *kset,
> -			   unsigned int id, bool config, bool memmap_on_memory)
> +static int sclp_create_mem(struct kset *kset, unsigned int id, bool config,
> +			   bool memmap_on_memory)
>  {
> +	struct sclp_mem *sclp_mem;
>  	int rc;
>  
> +	sclp_mem = kzalloc_obj(*sclp_mem);
> +	if (!sclp_mem)
> +		return -ENOMEM;
>  	sclp_mem->memmap_on_memory = memmap_on_memory;
>  	sclp_mem->config = config;
>  #ifdef CONFIG_KASAN
>  	sclp_mem->early_shadow_mapped = config;
>  #endif
>  	sclp_mem->id = id;
> -	kobject_init(&sclp_mem->kobj, &ktype);
> -	rc = kobject_add(&sclp_mem->kobj, &kset->kobj, "memory%d", id);
> -	if (rc)
> +	rc = kobject_init_and_add(&sclp_mem->kobj, &ktype, &kset->kobj,
> +				  "memory%d", id);
> +	if (rc) {
> +		kobject_put(&sclp_mem->kobj);
>  		return rc;
> -	return sysfs_create_group(&sclp_mem->kobj, &sclp_mem_attr_group);
> +	}
> +	rc = sysfs_create_group(&sclp_mem->kobj, &sclp_mem_attr_group);

[Severity: High]
Does calling sysfs_create_group() after kobject_init_and_add() in
sclp_create_mem() expose the sysfs directory to userspace before its
attributes are populated? Would it be safer to avoid this structural sysfs
race condition by assigning the attributes to ktype.default_groups instead?

> +	if (rc) {
> +		kobject_put(&sclp_mem->kobj);
> +		return rc;
> +	}
> +	return 0;
>  }
[ ... ]
> @@ -395,7 +401,7 @@ static int __init sclp_create_standby_mems_merged(struct sclp_mem *sclp_mems,
>  		goto skip_add;
>  	for (addr = start; addr < start + size; addr += block_size) {
>  		id = addr / block_size;
> -		rc = sclp_create_mem(&sclp_mems[id], kset, id, false,
> +		rc = sclp_create_mem(kset, id, false,
>  				     mhp_supports_memmap_on_memory());
>  		if (rc)
>  			break;
>  	}

[Severity: Medium]
If sclp_create_mem() fails and breaks out of this loop in
sclp_create_standby_mems_merged(), are the kobjects created in previous
iterations left registered? Should there be a centralized error cleanup
path to unwind and free these prior allocations?

>  skip_add:
>  	first_rn = rn;
>  	num = 1;
>  	return rc;
>  }
>  
> -static int __init sclp_create_standby_mems(struct sclp_mem *sclp_mems, struct kset *kset)
> +static int __init sclp_create_standby_mems(struct kset *kset)
>  {
>  	struct memory_increment *incr;
>  	int rc = 0;
>  
>  	list_for_each_entry(incr, &sclp_mem_list, list) {
>  		if (incr->standby)
> -			rc = sclp_create_standby_mems_merged(sclp_mems, kset, incr->rn);
> +			rc = sclp_create_standby_mems_merged(kset, incr->rn);
>  		if (rc)
>  			return rc;
>  	}

[Severity: High]
When sclp_create_standby_mems_merged() returns an error, this loop in
sclp_create_standby_mems() returns directly. Could this leak all the
standby kobjects that were successfully created in earlier iterations of
the loop?

> -	return sclp_create_standby_mems_merged(sclp_mems, kset, 0);
> +	return sclp_create_standby_mems_merged(kset, 0);
>  }
>  
>  static int __init sclp_init_mem(void)
>  {
> -	const unsigned long block_size = memory_block_size_bytes();
> -	unsigned int max_sclp_mems;
> -	struct sclp_mem *sclp_mems;
> -	struct sclp_mem_arg arg;
>  	struct kset *kset;
>  	int rc;
>  
> -	max_sclp_mems = roundup(sclp.rnmax * sclp.rzm, block_size) / block_size;
> -	/* Allocate memory for all blocks ahead of time. */
> -	sclp_mems = kzalloc_objs(struct sclp_mem, max_sclp_mems);
> -	if (!sclp_mems)
> -		return -ENOMEM;
>  	kset = kset_create_and_add("memory", NULL, firmware_kobj);
>  	if (!kset)
>  		return -ENOMEM;
>  	/* Initial memory is in the "configured" state already. */
> -	arg.sclp_mems = sclp_mems;
> -	arg.kset = kset;
> -	rc = for_each_memory_block(&arg, sclp_create_configured_mem);
> +	rc = for_each_memory_block(kset, sclp_create_configured_mem);
>  	if (rc)
>  		return rc;

[Severity: High]
If for_each_memory_block() encounters an error during memory block
creation in sclp_init_mem(), returning directly here leaves the previously
created kset and any successfully configured memory kobjects registered.
Does this result in a permanent memory leak of these structures?

>  	/* Standby memory is "deconfigured". */
> -	return sclp_create_standby_mems(sclp_mems, kset);
> +	return sclp_create_standby_mems(kset);
>  }

[Severity: Medium]
Similarly, if sclp_create_standby_mems() fails later in sclp_init_mem(),
returning its error code directly leaves the kset and the initial
configured memory blocks leaked. Is an error handling path missing here to
clean up the kset and all child kobjects on failure?

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

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

* Re: [PATCH 08/11] s390/sclp_mem: Allocate struct sclp_mem dynamically and add kobject release
@ 2026-10-13 22:48     ` sashiko-bot
  0 siblings, 0 replies; 40+ messages in thread
From: sashiko-bot @ 2026-10-13 22:48 UTC (permalink / raw)
  To: Ian Rogers, Greg Kroah-Hartman, Rafael J . Wysocki,
	Danilo Krummrich, Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, linux-s390, linux-mtd, dri-devel

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] sysfs: kobject memory leak on init error paths and group creation race
- [Medium] sysfs: missing cleanup of previously allocated kobjects in initialization loops
--

commit 191798937bad0f272b0f72f4ae28579cab8672f8
Author: Ian Rogers <irogers@google.com>

s390/sclp_mem: Allocate struct sclp_mem dynamically and add kobject release

sclp_init_mem() allocated a single array of struct sclp_mem with
kzalloc_objs() and registered each embedded kobject using a kobj_type
without a .release callback. Allocate each struct sclp_mem individually
with kzalloc_obj() instead and add sclp_mem_release() to free it.

> diff --git a/drivers/s390/char/sclp_mem.c b/drivers/s390/char/sclp_mem.c
> index 78c054e26d177..40a7f92729751 100644
> --- a/drivers/s390/char/sclp_mem.c
> +++ b/drivers/s390/char/sclp_mem.c
[ ... ]
> @@ -322,36 +325,40 @@ static struct attribute_group sclp_mem_attr_group = {
>  	.attrs = sclp_mem_attrs,
>  };
>  
> -static int sclp_create_mem(struct sclp_mem *sclp_mem, struct kset *kset,
> -			   unsigned int id, bool config, bool memmap_on_memory)
> +static int sclp_create_mem(struct kset *kset, unsigned int id, bool config,
> +			   bool memmap_on_memory)
>  {
> +	struct sclp_mem *sclp_mem;
>  	int rc;
>  
> +	sclp_mem = kzalloc_obj(*sclp_mem);
> +	if (!sclp_mem)
> +		return -ENOMEM;
>  	sclp_mem->memmap_on_memory = memmap_on_memory;
>  	sclp_mem->config = config;
>  #ifdef CONFIG_KASAN
>  	sclp_mem->early_shadow_mapped = config;
>  #endif
>  	sclp_mem->id = id;
> -	kobject_init(&sclp_mem->kobj, &ktype);
> -	rc = kobject_add(&sclp_mem->kobj, &kset->kobj, "memory%d", id);
> -	if (rc)
> +	rc = kobject_init_and_add(&sclp_mem->kobj, &ktype, &kset->kobj,
> +				  "memory%d", id);
> +	if (rc) {
> +		kobject_put(&sclp_mem->kobj);
>  		return rc;
> -	return sysfs_create_group(&sclp_mem->kobj, &sclp_mem_attr_group);
> +	}
> +	rc = sysfs_create_group(&sclp_mem->kobj, &sclp_mem_attr_group);

[Severity: High]
Does calling sysfs_create_group() after kobject_init_and_add() in
sclp_create_mem() expose the sysfs directory to userspace before its
attributes are populated? Would it be safer to avoid this structural sysfs
race condition by assigning the attributes to ktype.default_groups instead?

> +	if (rc) {
> +		kobject_put(&sclp_mem->kobj);
> +		return rc;
> +	}
> +	return 0;
>  }
[ ... ]
> @@ -395,7 +401,7 @@ static int __init sclp_create_standby_mems_merged(struct sclp_mem *sclp_mems,
>  		goto skip_add;
>  	for (addr = start; addr < start + size; addr += block_size) {
>  		id = addr / block_size;
> -		rc = sclp_create_mem(&sclp_mems[id], kset, id, false,
> +		rc = sclp_create_mem(kset, id, false,
>  				     mhp_supports_memmap_on_memory());
>  		if (rc)
>  			break;
>  	}

[Severity: Medium]
If sclp_create_mem() fails and breaks out of this loop in
sclp_create_standby_mems_merged(), are the kobjects created in previous
iterations left registered? Should there be a centralized error cleanup
path to unwind and free these prior allocations?

>  skip_add:
>  	first_rn = rn;
>  	num = 1;
>  	return rc;
>  }
>  
> -static int __init sclp_create_standby_mems(struct sclp_mem *sclp_mems, struct kset *kset)
> +static int __init sclp_create_standby_mems(struct kset *kset)
>  {
>  	struct memory_increment *incr;
>  	int rc = 0;
>  
>  	list_for_each_entry(incr, &sclp_mem_list, list) {
>  		if (incr->standby)
> -			rc = sclp_create_standby_mems_merged(sclp_mems, kset, incr->rn);
> +			rc = sclp_create_standby_mems_merged(kset, incr->rn);
>  		if (rc)
>  			return rc;
>  	}

[Severity: High]
When sclp_create_standby_mems_merged() returns an error, this loop in
sclp_create_standby_mems() returns directly. Could this leak all the
standby kobjects that were successfully created in earlier iterations of
the loop?

> -	return sclp_create_standby_mems_merged(sclp_mems, kset, 0);
> +	return sclp_create_standby_mems_merged(kset, 0);
>  }
>  
>  static int __init sclp_init_mem(void)
>  {
> -	const unsigned long block_size = memory_block_size_bytes();
> -	unsigned int max_sclp_mems;
> -	struct sclp_mem *sclp_mems;
> -	struct sclp_mem_arg arg;
>  	struct kset *kset;
>  	int rc;
>  
> -	max_sclp_mems = roundup(sclp.rnmax * sclp.rzm, block_size) / block_size;
> -	/* Allocate memory for all blocks ahead of time. */
> -	sclp_mems = kzalloc_objs(struct sclp_mem, max_sclp_mems);
> -	if (!sclp_mems)
> -		return -ENOMEM;
>  	kset = kset_create_and_add("memory", NULL, firmware_kobj);
>  	if (!kset)
>  		return -ENOMEM;
>  	/* Initial memory is in the "configured" state already. */
> -	arg.sclp_mems = sclp_mems;
> -	arg.kset = kset;
> -	rc = for_each_memory_block(&arg, sclp_create_configured_mem);
> +	rc = for_each_memory_block(kset, sclp_create_configured_mem);
>  	if (rc)
>  		return rc;

[Severity: High]
If for_each_memory_block() encounters an error during memory block
creation in sclp_init_mem(), returning directly here leaves the previously
created kset and any successfully configured memory kobjects registered.
Does this result in a permanent memory leak of these structures?

>  	/* Standby memory is "deconfigured". */
> -	return sclp_create_standby_mems(sclp_mems, kset);
> +	return sclp_create_standby_mems(kset);
>  }

[Severity: Medium]
Similarly, if sclp_create_standby_mems() fails later in sclp_init_mem(),
returning its error code directly leaves the kset and the initial
configured memory blocks leaked. Is an error handling path missing here to
clean up the kset and all child kobjects on failure?

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

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

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

* Re: [PATCH 07/11] xen/sys-hypervisor: Add release callback to hyp_sysfs_kobj_type
  2026-10-13 22:39   ` Ian Rogers
  (?)
@ 2026-10-13 22:52   ` sashiko-bot
  -1 siblings, 0 replies; 40+ messages in thread
From: sashiko-bot @ 2026-10-13 22:52 UTC (permalink / raw)
  To: Ian Rogers
  Cc: linux-s390, Heiko Carstens, Vasily Gorbik, Alexander Gordeev,
	Christian Borntraeger

> 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")
> Assisted-by: Antigravity:gemini-3.1-pro
> Signed-off-by: Ian Rogers <irogers@google.com>

Sashiko has reviewed this patch and found no issues. It looks great!

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


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

* Re: [PATCH 04/11] cpufreq: Initialize kobj_type release callback in ondemand and conservative governors
  2026-10-13 22:39   ` Ian Rogers
  (?)
@ 2026-10-13 22:52   ` sashiko-bot
  -1 siblings, 0 replies; 40+ messages in thread
From: sashiko-bot @ 2026-10-13 22:52 UTC (permalink / raw)
  To: Ian Rogers
  Cc: linux-s390, Heiko Carstens, Vasily Gorbik, Alexander Gordeev,
	Christian Borntraeger

> Export cpufreq_dbs_data_release() and set .kobj_type.release in the
> ondemand and conservative governors so their gov_attr_set kobjects have
> a valid release callback, matching cpufreq_ governor_dbs.
> 
> This prepares for annotating struct kobj_type::release with
> __require_explicit_initialization.
> 
> Fixes: c4435630361d ("cpufreq: governor: New sysfs show/store callbacks for governor tunables")
> Assisted-by: Antigravity:gemini-3.1-pro
> Signed-off-by: Ian Rogers <irogers@google.com>

Sashiko has reviewed this patch and found no issues. It looks great!

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


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

* Re: [PATCH 03/11] sh: sq: Add missing kobject release callback to ktype_percpu_entry
  2026-10-13 22:39   ` Ian Rogers
  (?)
@ 2026-10-13 22:53   ` sashiko-bot
  -1 siblings, 0 replies; 40+ messages in thread
From: sashiko-bot @ 2026-10-13 22:53 UTC (permalink / raw)
  To: Ian Rogers
  Cc: linux-s390, Heiko Carstens, Vasily Gorbik, Alexander Gordeev,
	Christian Borntraeger

> 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.")
> Assisted-by: Antigravity:gemini-3.1-pro
> Signed-off-by: Ian Rogers <irogers@google.com>

Sashiko has reviewed this patch and found no issues. It looks great!

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


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

* Re: [PATCH 05/11] ACPI: CPPC: Free cpc_desc in kobject release callback
  2026-10-13 22:39   ` Ian Rogers
@ 2026-10-13 22:54     ` sashiko-bot
  -1 siblings, 0 replies; 40+ messages in thread
From: sashiko-bot @ 2026-10-13 22:54 UTC (permalink / raw)
  To: Ian Rogers, Greg Kroah-Hartman, Rafael J . Wysocki,
	Danilo Krummrich, Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, linux-s390, linux-mtd, dri-devel

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] acpi: cppc: dangling per-CPU pointer after exit leads to UAF
- [Medium] acpi/cppc: missing kobject_del() causes sysfs -EEXIST on driver re-bind
--

commit 1405c81459a62da53ac116a49a65cbdc3bcdcd68
Author: Ian Rogers <irogers@google.com>

ACPI: CPPC: Free cpc_desc in kobject release callback

cpc_desc_ptr embeds a struct kobject that is registered in sysfs via
kobject_init_and_add(), but cppc_ktype lacked a .release callback and
acpi_cppc_processor_exit() freed cpc_ptr immediately after kobject_put().
This patch moves the sys_mem_vaddr unmapping and kfree(cpc_ptr) into a new
cppc_release() callback.

> diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
> index f370be8715ae2..0fefe1cdb60ce 100644
> --- a/drivers/acpi/cppc_acpi.c
> +++ b/drivers/acpi/cppc_acpi.c
> [ ... ]
> @@ -961,15 +966,7 @@ void acpi_cppc_processor_exit(struct acpi_processor *pr)
>  	if (!cpc_ptr)
>  		return;
>  
> -	/* Free all the mapped sys mem areas for this CPU */
> -	for (i = 2; i < cpc_ptr->num_entries; i++) {
> -		addr = cpc_ptr->cpc_regs[i-2].sys_mem_vaddr;
> -		if (addr)
> -			iounmap(addr);
> -	}
> -
>  	kobject_put(&cpc_ptr->kobj);

[Severity: High]
Does this leave a dangling pointer in the per-CPU variable?

When acpi_cppc_processor_exit() drops the kobject refcount, the underlying
memory is freed. However, it seems per_cpu(cpc_desc_ptr, pr->id) is never
set to NULL.

Could other CPPC functions that rely on this pointer being NULL if
uninitialized, such as cppc_get_perf_caps():

	struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpunum);
	// ...
	if (!cpc_desc) {
		pr_debug("No CPC descriptor for CPU:%d\n", cpunum);
		return -ENODEV;
	}

successfully pass the check on the dangling pointer and trigger a
use-after-free upon driver unbind?

[Severity: Medium]
Could omitting kobject_del() here cause a sysfs -EEXIST error when the
driver is re-bound?

The teardown path drops the reference but appears to omit explicitly
unregistering the sysfs directory. If the kobject's refcount does not
immediately reach 0 (for example, if userspace has a CPPC sysfs file open,
or if CONFIG_DEBUG_KOBJECT_RELEASE=y defers the release), the sysfs
directory is not synchronously removed.

Should kobject_del() be called before kobject_put() to ensure a subsequent
kobject_add() in the probe path does not collide with a lingering sysfs
directory?

> -	kfree(cpc_ptr);
>  }
>  EXPORT_SYMBOL_GPL(acpi_cppc_processor_exit);

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

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

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

* Re: [PATCH 05/11] ACPI: CPPC: Free cpc_desc in kobject release callback
@ 2026-10-13 22:54     ` sashiko-bot
  0 siblings, 0 replies; 40+ messages in thread
From: sashiko-bot @ 2026-10-13 22:54 UTC (permalink / raw)
  To: Ian Rogers, Greg Kroah-Hartman, Rafael J . Wysocki,
	Danilo Krummrich, Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, linux-s390, linux-mtd, dri-devel

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] acpi: cppc: dangling per-CPU pointer after exit leads to UAF
- [Medium] acpi/cppc: missing kobject_del() causes sysfs -EEXIST on driver re-bind
--

commit 1405c81459a62da53ac116a49a65cbdc3bcdcd68
Author: Ian Rogers <irogers@google.com>

ACPI: CPPC: Free cpc_desc in kobject release callback

cpc_desc_ptr embeds a struct kobject that is registered in sysfs via
kobject_init_and_add(), but cppc_ktype lacked a .release callback and
acpi_cppc_processor_exit() freed cpc_ptr immediately after kobject_put().
This patch moves the sys_mem_vaddr unmapping and kfree(cpc_ptr) into a new
cppc_release() callback.

> diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
> index f370be8715ae2..0fefe1cdb60ce 100644
> --- a/drivers/acpi/cppc_acpi.c
> +++ b/drivers/acpi/cppc_acpi.c
> [ ... ]
> @@ -961,15 +966,7 @@ void acpi_cppc_processor_exit(struct acpi_processor *pr)
>  	if (!cpc_ptr)
>  		return;
>  
> -	/* Free all the mapped sys mem areas for this CPU */
> -	for (i = 2; i < cpc_ptr->num_entries; i++) {
> -		addr = cpc_ptr->cpc_regs[i-2].sys_mem_vaddr;
> -		if (addr)
> -			iounmap(addr);
> -	}
> -
>  	kobject_put(&cpc_ptr->kobj);

[Severity: High]
Does this leave a dangling pointer in the per-CPU variable?

When acpi_cppc_processor_exit() drops the kobject refcount, the underlying
memory is freed. However, it seems per_cpu(cpc_desc_ptr, pr->id) is never
set to NULL.

Could other CPPC functions that rely on this pointer being NULL if
uninitialized, such as cppc_get_perf_caps():

	struct cpc_desc *cpc_desc = per_cpu(cpc_desc_ptr, cpunum);
	// ...
	if (!cpc_desc) {
		pr_debug("No CPC descriptor for CPU:%d\n", cpunum);
		return -ENODEV;
	}

successfully pass the check on the dangling pointer and trigger a
use-after-free upon driver unbind?

[Severity: Medium]
Could omitting kobject_del() here cause a sysfs -EEXIST error when the
driver is re-bound?

The teardown path drops the reference but appears to omit explicitly
unregistering the sysfs directory. If the kobject's refcount does not
immediately reach 0 (for example, if userspace has a CPPC sysfs file open,
or if CONFIG_DEBUG_KOBJECT_RELEASE=y defers the release), the sysfs
directory is not synchronously removed.

Should kobject_del() be called before kobject_put() to ensure a subsequent
kobject_add() in the probe path does not collide with a lingering sysfs
directory?

> -	kfree(cpc_ptr);
>  }
>  EXPORT_SYMBOL_GPL(acpi_cppc_processor_exit);

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

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

* Re: [PATCH 06/11] dlm: Free dlm_ls in kobject release callback
  2026-10-13 22:39   ` Ian Rogers
@ 2026-10-13 22:55     ` sashiko-bot
  -1 siblings, 0 replies; 40+ messages in thread
From: sashiko-bot @ 2026-10-13 22:55 UTC (permalink / raw)
  To: Ian Rogers, Greg Kroah-Hartman, Rafael J . Wysocki,
	Danilo Krummrich, Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, linux-s390, linux-mtd, dri-devel

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] dlm: sysfs UAF of ls_recoverd_task during lockspace teardown
- [High] dlm: module unload UAF in dlm_ls_release under DEBUG_KOBJECT_RELEASE
--

commit 5dce188281954f951472555cf7284cda831b20a7
Author: Ian Rogers <irogers@google.com>

dlm: Free dlm_ls in kobject release callback

This commit adds a kobject release callback, dlm_ls_release(), to properly
free the dlm_ls structure when the last kobject reference is dropped. This
fixes a use-after-free issue when CONFIG_DEBUG_KOBJECT_RELEASE is enabled.

> diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
> index a9c98b4f378f3..1d226b27d8e61 100644
> --- a/fs/dlm/lockspace.c
> +++ b/fs/dlm/lockspace.c

[ ... ]

> @@ -179,7 +179,15 @@ static const struct sysfs_ops dlm_attr_ops = {
>  	.show  = dlm_attr_show,
>  	.store = dlm_attr_store,
>  };
>  
> +static void dlm_ls_release(struct kobject *kobj)
> +{
> +	struct dlm_ls *ls = container_of(kobj, struct dlm_ls, ls_kobj);
> +
> +	kfree(ls);
> +}

[Severity: High]
Can this callback trigger an instruction page fault if the module is unloaded?

Under CONFIG_DEBUG_KOBJECT_RELEASE=y, kobject release is delayed by 1-4
seconds. If the dlm module is unloaded during this window, this callback
will point to unmapped memory when the delayed work executes.

[ ... ]

> @@ -615,7 +623,6 @@ static int new_lockspace(const char *name, const char *cluster,
>  	rhashtable_destroy(&ls->ls_rsbtbl);
>   out_lsfree:
>  	kobject_put(&ls->ls_kobj);
> -	kfree(ls);
>   out:
>  	module_put(THIS_MODULE);
>  	return error;

[Severity: High]
In the error path of new_lockspace(), we drop the kobject reference and then
immediately drop the module reference via module_put(). Doesn't this allow
the module to be unloaded while the delayed kobject release is still pending?

Additionally, could this sequence open a use-after-free race window?

Earlier in the error path of new_lockspace(), we call dlm_recoverd_stop():

out_recoverd:
        dlm_recoverd_stop(ls);
out_callback:
        ...
out_lsfree:
        kobject_put(&ls->ls_kobj);

The recovery task is stopped and freed in dlm_recoverd_stop(), but the sysfs
entries aren't removed until kobject_put() is called much later. A concurrent
sysfs write to the control file could invoke dlm_ls_start() in fs/dlm/member.c
and wake up the freed ls->ls_recoverd_task.

[ ... ]

> @@ -759,7 +766,7 @@ static int release_lockspace(struct dlm_ls *ls, unsigned int release_option)
>  
>  	dlm_delete_debug_file(ls);
>  
> -	kobject_put(&ls->ls_kobj);
> +	kobject_del(&ls->ls_kobj);
>  
>  	xa_destroy(&ls->ls_recover_xa);
>  	kfree(ls->ls_recover_buf);

[Severity: High]
Is there a similar use-after-free risk involving the recovery thread here?

Looking at the context in release_lockspace(), we stop the recovery thread
earlier:

release_lockspace() {
    ...
    dlm_recoverd_stop(ls);
    ...
    clear_bit(LSFL_RUNNING, &ls->ls_flags);
    ...
    kobject_del(&ls->ls_kobj);
    ...
    module_put(THIS_MODULE);
}

Since the sysfs kobject isn't deleted until after the recovery thread is
stopped and its task_struct is freed, the sysfs entries remain active in the
interim. A concurrent sysfs write to the control file could invoke
dlm_ls_start() which calls wake_up_process(ls->ls_recoverd_task) on the freed
task_struct.

Also, module_put() is called at the end of release_lockspace() while the
kobject delayed release is pending, repeating the module unload race mentioned
above.

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

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

* Re: [PATCH 06/11] dlm: Free dlm_ls in kobject release callback
@ 2026-10-13 22:55     ` sashiko-bot
  0 siblings, 0 replies; 40+ messages in thread
From: sashiko-bot @ 2026-10-13 22:55 UTC (permalink / raw)
  To: Ian Rogers, Greg Kroah-Hartman, Rafael J . Wysocki,
	Danilo Krummrich, Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, linux-s390, linux-mtd, dri-devel

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] dlm: sysfs UAF of ls_recoverd_task during lockspace teardown
- [High] dlm: module unload UAF in dlm_ls_release under DEBUG_KOBJECT_RELEASE
--

commit 5dce188281954f951472555cf7284cda831b20a7
Author: Ian Rogers <irogers@google.com>

dlm: Free dlm_ls in kobject release callback

This commit adds a kobject release callback, dlm_ls_release(), to properly
free the dlm_ls structure when the last kobject reference is dropped. This
fixes a use-after-free issue when CONFIG_DEBUG_KOBJECT_RELEASE is enabled.

> diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
> index a9c98b4f378f3..1d226b27d8e61 100644
> --- a/fs/dlm/lockspace.c
> +++ b/fs/dlm/lockspace.c

[ ... ]

> @@ -179,7 +179,15 @@ static const struct sysfs_ops dlm_attr_ops = {
>  	.show  = dlm_attr_show,
>  	.store = dlm_attr_store,
>  };
>  
> +static void dlm_ls_release(struct kobject *kobj)
> +{
> +	struct dlm_ls *ls = container_of(kobj, struct dlm_ls, ls_kobj);
> +
> +	kfree(ls);
> +}

[Severity: High]
Can this callback trigger an instruction page fault if the module is unloaded?

Under CONFIG_DEBUG_KOBJECT_RELEASE=y, kobject release is delayed by 1-4
seconds. If the dlm module is unloaded during this window, this callback
will point to unmapped memory when the delayed work executes.

[ ... ]

> @@ -615,7 +623,6 @@ static int new_lockspace(const char *name, const char *cluster,
>  	rhashtable_destroy(&ls->ls_rsbtbl);
>   out_lsfree:
>  	kobject_put(&ls->ls_kobj);
> -	kfree(ls);
>   out:
>  	module_put(THIS_MODULE);
>  	return error;

[Severity: High]
In the error path of new_lockspace(), we drop the kobject reference and then
immediately drop the module reference via module_put(). Doesn't this allow
the module to be unloaded while the delayed kobject release is still pending?

Additionally, could this sequence open a use-after-free race window?

Earlier in the error path of new_lockspace(), we call dlm_recoverd_stop():

out_recoverd:
        dlm_recoverd_stop(ls);
out_callback:
        ...
out_lsfree:
        kobject_put(&ls->ls_kobj);

The recovery task is stopped and freed in dlm_recoverd_stop(), but the sysfs
entries aren't removed until kobject_put() is called much later. A concurrent
sysfs write to the control file could invoke dlm_ls_start() in fs/dlm/member.c
and wake up the freed ls->ls_recoverd_task.

[ ... ]

> @@ -759,7 +766,7 @@ static int release_lockspace(struct dlm_ls *ls, unsigned int release_option)
>  
>  	dlm_delete_debug_file(ls);
>  
> -	kobject_put(&ls->ls_kobj);
> +	kobject_del(&ls->ls_kobj);
>  
>  	xa_destroy(&ls->ls_recover_xa);
>  	kfree(ls->ls_recover_buf);

[Severity: High]
Is there a similar use-after-free risk involving the recovery thread here?

Looking at the context in release_lockspace(), we stop the recovery thread
earlier:

release_lockspace() {
    ...
    dlm_recoverd_stop(ls);
    ...
    clear_bit(LSFL_RUNNING, &ls->ls_flags);
    ...
    kobject_del(&ls->ls_kobj);
    ...
    module_put(THIS_MODULE);
}

Since the sysfs kobject isn't deleted until after the recovery thread is
stopped and its task_struct is freed, the sysfs entries remain active in the
interim. A concurrent sysfs write to the control file could invoke
dlm_ls_start() which calls wake_up_process(ls->ls_recoverd_task) on the freed
task_struct.

Also, module_put() is called at the end of release_lockspace() while the
kobject delayed release is pending, repeating the module unload race mentioned
above.

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

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

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

* Re: [PATCH 11/11] kobject: Require explicit initialization of struct kobj_type::release
  2026-10-13 22:39   ` Ian Rogers
@ 2026-10-13 22:56     ` sashiko-bot
  -1 siblings, 0 replies; 40+ messages in thread
From: sashiko-bot @ 2026-10-13 22:56 UTC (permalink / raw)
  To: Ian Rogers, Greg Kroah-Hartman, Rafael J . Wysocki,
	Danilo Krummrich, Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, linux-s390, linux-mtd, dri-devel

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] sysfs: Use-After-Free in kobject delayed release via devm/memset
- [Low] sysfs: incorrect documentation for dss_overlay_kobj_uninit() cleanup
--

commit 25c0a8c68e5a115989252d41a0d4731867415d79
Author: Ian Rogers <irogers@google.com>
Subject: kobject: Require explicit initialization of struct kobj_type::release

Annotate struct kobj_type::release with __require_explicit_initialization
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, or embedded inside a devm- or parent-managed
structure rather than freed by kobject_put(), explicitly initialize
.release = NULL.

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

> diff --git a/drivers/dma/ioat/sysfs.c b/drivers/dma/ioat/sysfs.c
> index e796ddb5383f8..7fdd0ca36b98a 100644
> --- a/drivers/dma/ioat/sysfs.c
> +++ b/drivers/dma/ioat/sysfs.c
> @@ -167,6 +167,8 @@ static const struct attribute *const ioat_attrs[] = {
>  ATTRIBUTE_GROUPS(ioat);
>  
>  const struct kobj_type ioat_ktype = {
> +	/* ioatdma_chan is allocated via devm_kzalloc() rather than freed by kobject_put(). */
> +	.release = NULL,

[Severity: High]
Does this setup cause a use-after-free when CONFIG_DEBUG_KOBJECT_RELEASE is
enabled?

When kobject_put() is called, it queues a delayed_work to execute
kobject_cleanup() later. Because the struct is managed by devm_kzalloc(),
the memory is freed immediately after unbind, leaving an active delayed_work
pointing to the freed memory.

[ ... ]

> diff --git a/drivers/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c
> index 0cc2953d59a54..5d083d2b72caa 100644
> --- a/drivers/soc/hisilicon/kunpeng_hccs.c
> +++ b/drivers/soc/hisilicon/kunpeng_hccs.c
> @@ -1038,6 +1038,8 @@ static struct attribute *hccs_port_default_attrs[] = {
>  ATTRIBUTE_GROUPS(hccs_port_default);
>  
>  static const struct kobj_type hccs_port_type = {
> +	/* hccs_port_info is allocated via devm_kcalloc() rather than freed by kobject_put(). */
> +	.release = NULL,

[Severity: High]
Can this devm allocation cause a use-after-free for the delayed_work?

Similar to the ioat_ktype case, the devm_kcalloc allocation means the struct
containing the kobject is freed upon driver unbind immediately after
kobject_put() executes, leaving a pending delayed_work on freed memory.

[ ... ]

> diff --git a/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c b/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c
> index ae937854403b1..3d787245f5b51 100644
> --- a/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c
> +++ b/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c
> @@ -304,6 +304,8 @@ static const struct sysfs_ops display_sysfs_ops = {
>  };
>  
>  static struct kobj_type display_ktype = {
> +	/* dssdev->kobj is embedded in struct omap_dss_device and zeroed in display_uninit_sysfs(). */
> +	.release = NULL,

[Severity: High]
Does this zeroing pattern corrupt the active workqueue when
CONFIG_DEBUG_KOBJECT_RELEASE is enabled?

Looking at display_uninit_sysfs(), the code calls kobject_put() followed
immediately by memset:

void display_uninit_sysfs(struct omap_dss_device *dssdev)
{
	...
	kobject_del(&dssdev->kobj);
	kobject_put(&dssdev->kobj);

	memset(&dssdev->kobj, 0, sizeof(dssdev->kobj));
}

Since kobject_put() schedules a delayed_work, wouldn't the memset
synchronously destroy the active work struct before it can run?

[ ... ]

> diff --git a/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c b/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c
> index 1da4fb1c77b4a..9aa16b3dee5ef 100644
> --- a/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c
> +++ b/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c
> @@ -429,6 +429,8 @@ static const struct sysfs_ops overlay_sysfs_ops = {
>  };
>  
>  static struct kobj_type overlay_ktype = {
> +	/* ovl->kobj is embedded in static overlays[]; dss_overlay_kobj_uninit() only calls kobject_del(). */
> +	.release = NULL,

[Severity: Low]
Is this comment accurate?

Looking at dss_overlay_kobj_uninit() in the same file:

void dss_overlay_kobj_uninit(struct omap_overlay *ovl)
{
	kobject_del(&ovl->kobj);
	kobject_put(&ovl->kobj);
}

The implementation contradicts the comment by explicitly calling
kobject_put().

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

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

* Re: [PATCH 11/11] kobject: Require explicit initialization of struct kobj_type::release
@ 2026-10-13 22:56     ` sashiko-bot
  0 siblings, 0 replies; 40+ messages in thread
From: sashiko-bot @ 2026-10-13 22:56 UTC (permalink / raw)
  To: Ian Rogers, Greg Kroah-Hartman, Rafael J . Wysocki,
	Danilo Krummrich, Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, linux-s390, linux-mtd, dri-devel

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] sysfs: Use-After-Free in kobject delayed release via devm/memset
- [Low] sysfs: incorrect documentation for dss_overlay_kobj_uninit() cleanup
--

commit 25c0a8c68e5a115989252d41a0d4731867415d79
Author: Ian Rogers <irogers@google.com>
Subject: kobject: Require explicit initialization of struct kobj_type::release

Annotate struct kobj_type::release with __require_explicit_initialization
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, or embedded inside a devm- or parent-managed
structure rather than freed by kobject_put(), explicitly initialize
.release = NULL.

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

> diff --git a/drivers/dma/ioat/sysfs.c b/drivers/dma/ioat/sysfs.c
> index e796ddb5383f8..7fdd0ca36b98a 100644
> --- a/drivers/dma/ioat/sysfs.c
> +++ b/drivers/dma/ioat/sysfs.c
> @@ -167,6 +167,8 @@ static const struct attribute *const ioat_attrs[] = {
>  ATTRIBUTE_GROUPS(ioat);
>  
>  const struct kobj_type ioat_ktype = {
> +	/* ioatdma_chan is allocated via devm_kzalloc() rather than freed by kobject_put(). */
> +	.release = NULL,

[Severity: High]
Does this setup cause a use-after-free when CONFIG_DEBUG_KOBJECT_RELEASE is
enabled?

When kobject_put() is called, it queues a delayed_work to execute
kobject_cleanup() later. Because the struct is managed by devm_kzalloc(),
the memory is freed immediately after unbind, leaving an active delayed_work
pointing to the freed memory.

[ ... ]

> diff --git a/drivers/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c
> index 0cc2953d59a54..5d083d2b72caa 100644
> --- a/drivers/soc/hisilicon/kunpeng_hccs.c
> +++ b/drivers/soc/hisilicon/kunpeng_hccs.c
> @@ -1038,6 +1038,8 @@ static struct attribute *hccs_port_default_attrs[] = {
>  ATTRIBUTE_GROUPS(hccs_port_default);
>  
>  static const struct kobj_type hccs_port_type = {
> +	/* hccs_port_info is allocated via devm_kcalloc() rather than freed by kobject_put(). */
> +	.release = NULL,

[Severity: High]
Can this devm allocation cause a use-after-free for the delayed_work?

Similar to the ioat_ktype case, the devm_kcalloc allocation means the struct
containing the kobject is freed upon driver unbind immediately after
kobject_put() executes, leaving a pending delayed_work on freed memory.

[ ... ]

> diff --git a/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c b/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c
> index ae937854403b1..3d787245f5b51 100644
> --- a/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c
> +++ b/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c
> @@ -304,6 +304,8 @@ static const struct sysfs_ops display_sysfs_ops = {
>  };
>  
>  static struct kobj_type display_ktype = {
> +	/* dssdev->kobj is embedded in struct omap_dss_device and zeroed in display_uninit_sysfs(). */
> +	.release = NULL,

[Severity: High]
Does this zeroing pattern corrupt the active workqueue when
CONFIG_DEBUG_KOBJECT_RELEASE is enabled?

Looking at display_uninit_sysfs(), the code calls kobject_put() followed
immediately by memset:

void display_uninit_sysfs(struct omap_dss_device *dssdev)
{
	...
	kobject_del(&dssdev->kobj);
	kobject_put(&dssdev->kobj);

	memset(&dssdev->kobj, 0, sizeof(dssdev->kobj));
}

Since kobject_put() schedules a delayed_work, wouldn't the memset
synchronously destroy the active work struct before it can run?

[ ... ]

> diff --git a/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c b/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c
> index 1da4fb1c77b4a..9aa16b3dee5ef 100644
> --- a/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c
> +++ b/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c
> @@ -429,6 +429,8 @@ static const struct sysfs_ops overlay_sysfs_ops = {
>  };
>  
>  static struct kobj_type overlay_ktype = {
> +	/* ovl->kobj is embedded in static overlays[]; dss_overlay_kobj_uninit() only calls kobject_del(). */
> +	.release = NULL,

[Severity: Low]
Is this comment accurate?

Looking at dss_overlay_kobj_uninit() in the same file:

void dss_overlay_kobj_uninit(struct omap_overlay *ovl)
{
	kobject_del(&ovl->kobj);
	kobject_put(&ovl->kobj);
}

The implementation contradicts the comment by explicitly calling
kobject_put().

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

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

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

* Re: [PATCH 10/11] drm/amdkfd: Free queue in procfs_queue_type kobject release callback
  2026-10-13 22:39   ` Ian Rogers
@ 2026-10-13 22:57     ` sashiko-bot
  -1 siblings, 0 replies; 40+ messages in thread
From: sashiko-bot @ 2026-10-13 22:57 UTC (permalink / raw)
  To: Ian Rogers, Greg Kroah-Hartman, Rafael J . Wysocki,
	Danilo Krummrich, Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, linux-s390, linux-mtd, dri-devel

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] sysfs: WARNING in kernfs_remove_by_name_ns due to unconditionally deleting uninitialized kobject
--

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

drm/amdkfd: Free queue in procfs_queue_type kobject release callback

This commit adds a release callback to free the struct queue from the kobject
release function to prevent a use-after-free, and adjusts the kobject_put()
locations accordingly.

> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
[ ... ]
> @@ -701,7 +708,6 @@ void kfd_procfs_del_queue(struct queue *q)
>  		return;
>  
>  	kobject_del(&q->kobj);

[Severity: Medium]
Can this trigger a kernel warning if sysfs creation fails?

If kfd_procfs_add_queue() fails (for example, due to a memory allocation failure
in sysfs), q->kobj.state_in_sysfs remains 0 and q->kobj.sd is null. However,
pqm_create_queue() may ignore this sysfs failure and keep the queue operational.

Later, when pqm_destroy_queue() calls kfd_procfs_del_queue(), kobject_del() is
called unconditionally.

This results in a call chain to __kobject_del() which invokes
sysfs_remove_groups() with a null kobj->sd. This eventually propagates to
kernfs_remove_by_name_ns(), where a warning is triggered explicitly when
its parent argument is null:

fs/kernfs/dir.c:kernfs_remove_by_name_ns() {
    ...
    if (!parent) {
        WARN(1, KERN_WARNING "kernfs: can not remove '%s', no directory\n", name);
        return -ENOENT;
    }
    ...
}

Should we check if the kobject was successfully added to sysfs (such as checking
q->kobj.state_in_sysfs) before calling kobject_del()?

> -	kobject_put(&q->kobj);
>  }

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

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

* Re: [PATCH 10/11] drm/amdkfd: Free queue in procfs_queue_type kobject release callback
@ 2026-10-13 22:57     ` sashiko-bot
  0 siblings, 0 replies; 40+ messages in thread
From: sashiko-bot @ 2026-10-13 22:57 UTC (permalink / raw)
  To: Ian Rogers, Greg Kroah-Hartman, Rafael J . Wysocki,
	Danilo Krummrich, Miguel Ojeda, Kees Cook, Nathan Chancellor
  Cc: Nick Desaulniers, Bill Wendling, Justin Stitt, Jonathan Corbet,
	Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
	Christophe Leroy, Nayna Jain, Yoshinori Sato, Rich Felker,
	John Paul Adrian Glaubitz, Viresh Kumar, David Teigland,
	Alexander Aring, Juergen Gross, Stefano Stabellini,
	Oleksandr Tyshchenko, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Christian Borntraeger, Sven Schnelle,
	Richard Weinberger, Zhihao Cheng, Felix Kuehling, Alex Deucher,
	Christian König, linux-s390, linux-mtd, dri-devel

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] sysfs: WARNING in kernfs_remove_by_name_ns due to unconditionally deleting uninitialized kobject
--

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

drm/amdkfd: Free queue in procfs_queue_type kobject release callback

This commit adds a release callback to free the struct queue from the kobject
release function to prevent a use-after-free, and adjusts the kobject_put()
locations accordingly.

> diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
> --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
> +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
[ ... ]
> @@ -701,7 +708,6 @@ void kfd_procfs_del_queue(struct queue *q)
>  		return;
>  
>  	kobject_del(&q->kobj);

[Severity: Medium]
Can this trigger a kernel warning if sysfs creation fails?

If kfd_procfs_add_queue() fails (for example, due to a memory allocation failure
in sysfs), q->kobj.state_in_sysfs remains 0 and q->kobj.sd is null. However,
pqm_create_queue() may ignore this sysfs failure and keep the queue operational.

Later, when pqm_destroy_queue() calls kfd_procfs_del_queue(), kobject_del() is
called unconditionally.

This results in a call chain to __kobject_del() which invokes
sysfs_remove_groups() with a null kobj->sd. This eventually propagates to
kernfs_remove_by_name_ns(), where a warning is triggered explicitly when
its parent argument is null:

fs/kernfs/dir.c:kernfs_remove_by_name_ns() {
    ...
    if (!parent) {
        WARN(1, KERN_WARNING "kernfs: can not remove '%s', no directory\n", name);
        return -ENOENT;
    }
    ...
}

Should we check if the kobject was successfully added to sysfs (such as checking
q->kobj.state_in_sysfs) before calling kobject_del()?

> -	kobject_put(&q->kobj);
>  }

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

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

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

end of thread, other threads:[~2026-10-13 22:57 UTC | newest]

Thread overview: 40+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-13 22:39 [PATCH 00/11] kobject: Require explicit initialization of struct kobj_type::release Ian Rogers
2026-10-13 22:39 ` Ian Rogers
2026-10-13 22:39 ` [PATCH 01/11] Compiler Attributes: Add __require_explicit_initialization macro Ian Rogers
2026-10-13 22:39   ` Ian Rogers
2026-10-13 22:48   ` sashiko-bot
2026-10-13 22:39 ` [PATCH 02/11] powerpc/secvar: Add missing kobject release callback to secvar_ktype Ian Rogers
2026-10-13 22:39   ` Ian Rogers
2026-10-13 22:47   ` sashiko-bot
2026-10-13 22:39 ` [PATCH 03/11] sh: sq: Add missing kobject release callback to ktype_percpu_entry Ian Rogers
2026-10-13 22:39   ` Ian Rogers
2026-10-13 22:53   ` sashiko-bot
2026-10-13 22:39 ` [PATCH 04/11] cpufreq: Initialize kobj_type release callback in ondemand and conservative governors Ian Rogers
2026-10-13 22:39   ` Ian Rogers
2026-10-13 22:52   ` sashiko-bot
2026-10-13 22:39 ` [PATCH 05/11] ACPI: CPPC: Free cpc_desc in kobject release callback Ian Rogers
2026-10-13 22:39   ` Ian Rogers
2026-10-13 22:54   ` sashiko-bot
2026-10-13 22:54     ` sashiko-bot
2026-10-13 22:39 ` [PATCH 06/11] dlm: Free dlm_ls " Ian Rogers
2026-10-13 22:39   ` Ian Rogers
2026-10-13 22:55   ` sashiko-bot
2026-10-13 22:55     ` sashiko-bot
2026-10-13 22:39 ` [PATCH 07/11] xen/sys-hypervisor: Add release callback to hyp_sysfs_kobj_type Ian Rogers
2026-10-13 22:39   ` Ian Rogers
2026-10-13 22:52   ` sashiko-bot
2026-10-13 22:39 ` [PATCH 08/11] s390/sclp_mem: Allocate struct sclp_mem dynamically and add kobject release Ian Rogers
2026-10-13 22:39   ` Ian Rogers
2026-10-13 22:48   ` sashiko-bot
2026-10-13 22:48     ` sashiko-bot
2026-10-13 22:39 ` [PATCH 09/11] ubifs: sysfs: Use kset_create_and_add() for ubifs_kset Ian Rogers
2026-10-13 22:39   ` Ian Rogers
2026-10-13 22:47   ` sashiko-bot
2026-10-13 22:39 ` [PATCH 10/11] drm/amdkfd: Free queue in procfs_queue_type kobject release callback Ian Rogers
2026-10-13 22:39   ` Ian Rogers
2026-10-13 22:57   ` sashiko-bot
2026-10-13 22:57     ` sashiko-bot
2026-10-13 22:39 ` [PATCH 11/11] kobject: Require explicit initialization of struct kobj_type::release Ian Rogers
2026-10-13 22:39   ` Ian Rogers
2026-10-13 22:56   ` sashiko-bot
2026-10-13 22:56     ` sashiko-bot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.