| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/10/28 06:19 | flow | patch-triage |
4mArgs:null Results: {
"EnableConfigs": [
"DLM",
"CONFIGFS_FS",
"SYSFS",
"INET",
"UBIFS_FS",
"MTD_UBI",
"CPU_FREQ",
"CPU_FREQ_GOV_ONDEMAND",
"CPU_FREQ_GOV_CONSERVATIVE"
],
"FocusSymbols": [
"dlm_ls_release",
"free_lockspace",
"new_lockspace",
"release_lockspace",
"dlm_new_lockspace",
"dlm_release_lockspace",
"dlm_new_user_lockspace",
"ubifs_sysfs_register",
"ubifs_sysfs_unregister",
"cpufreq_dbs_data_release"
],
"KMSANReasoning": "The patch series introduces a new compile-time attribute `__must_init` (using Clang's `__require_explicit_initialization__` attribute) on `struct kobj_type.release` to require explicit initialization of the kobject release callback. In order to comply with this requirement and address kobject lifecycle issues, the patch adds explicit `.release` entries (either `NULL` for embedded/static kobjects or proper cleanup callbacks) and refactors kobject lifecycle handling in several subsystems (e.g., amdkfd queue release, DLM lockspace completion on release, and dynamic allocation of ubifs_kset).\n\nThese changes purely involve compile-time attribute validation and runtime kobject reference counting and object lifecycle management. Potential bugs arising from these changes (such as use-after-free, double free, or invalid refcounting) are within the domain of KASAN, refcount tracking, and CONFIG_DEBUG_KOBJECT_RELEASE. The patch does not introduce or modify any uninitialized memory reads, uninitialized struct fields, bounds/length calculations on raw memory buffers, or kernel-to-user information copies. Therefore, a dedicated KMSAN fuzzing session is not warranted.",
"NeedsKMSAN": false,
"Reasoning": "The patch introduces '__must_init' on 'struct kobj_type.release' and addresses missing or improper kobject release callbacks across various drivers and subsystems. In reachable core subsystems on amd64, notable functional and synchronization refactorings were introduced:\n1. In fs/dlm/lockspace.c, the lifecycle of struct dlm_ls kobjects was overhauled by introducing a new completion (ls_kobj_done), a release callback (dlm_ls_release), reordered kobject initialization/teardown in new_lockspace(), moving kobject_put() into free_lockspace(), and waiting on the completion before freeing the lockspace. This changes destruction and synchronization behavior on code accessible via /dev/dlm-control and filesystem mounts.\n2. In fs/ubifs/sysfs.c, ubifs_kset was transitioned from a static struct kset to a dynamically allocated kset created via kset_create_and_add().\n3. In drivers/cpufreq/, dbs_governor kobj_type release callback handling was refactored with exported cpufreq_dbs_data_release.\n\nThese alterations in reachable filesystem and core subsystem lifecycle code warrant fuzzing to identify potential regressions, use-after-free, or hang/deadlock conditions (particularly around the new completion wait during dlm lockspace teardown).",
"WorthFuzzing": true
} |
| 1/1 | 2026/10/28 06:19 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit aeb7a14c32eb7ebc6a77c24bd1d1349164380cbb\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Wed Oct 28 06:19:50 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/Documentation/conf.py b/Documentation/conf.py\nindex 5ab26ce89dafe6..baaa4035258c86 100644\n--- a/Documentation/conf.py\n+++ b/Documentation/conf.py\n@@ -203,6 +203,7 @@ c_id_attributes = [\n \"__noreturn\",\n \"__packed\",\n \"__pure\",\n+ \"__must_init\",\n \"__section\",\n \"__always_unused\",\n \"__maybe_unused\",\ndiff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c\nindex 94e6cd211d70e6..7a4ac8dd0b86a6 100644\n--- a/arch/arm64/kernel/cpuinfo.c\n+++ b/arch/arm64/kernel/cpuinfo.c\n@@ -295,6 +295,11 @@ const struct seq_operations cpuinfo_op = {\n \n \n static const struct kobj_type cpuregs_kobj_type = {\n+\t/*\n+\t * Pre-existing: info-\u003ekobj is embedded in per-CPU cpu_data;\n+\t * cpuid_cpu_offline() only calls kobject_del().\n+\t */\n+\t.release = NULL,\n \t.sysfs_ops = \u0026kobj_sysfs_ops,\n };\n \ndiff --git a/arch/powerpc/kernel/secvar-sysfs.c b/arch/powerpc/kernel/secvar-sysfs.c\nindex 395399bbab2c69..f3f6ac25ea788f 100644\n--- a/arch/powerpc/kernel/secvar-sysfs.c\n+++ b/arch/powerpc/kernel/secvar-sysfs.c\n@@ -126,7 +126,13 @@ static const struct attribute_group secvar_attr_group = {\n };\n __ATTRIBUTE_GROUPS(secvar_attr);\n \n+static void secvar_release(struct kobject *kobj)\n+{\n+\tkfree(kobj);\n+}\n+\n static const struct kobj_type secvar_ktype = {\n+\t.release\t= secvar_release,\n \t.sysfs_ops\t= \u0026kobj_sysfs_ops,\n \t.default_groups = secvar_attr_groups,\n };\ndiff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c\nindex 908a8e09113b7d..f33864958487ba 100644\n--- a/arch/sh/kernel/cpu/sh4/sq.c\n+++ b/arch/sh/kernel/cpu/sh4/sq.c\n@@ -331,7 +331,13 @@ static const struct sysfs_ops sq_sysfs_ops = {\n \t.store\t= sq_sysfs_store,\n };\n \n+static void sq_kobj_release(struct kobject *kobj)\n+{\n+\tkfree(kobj);\n+}\n+\n static struct kobj_type ktype_percpu_entry = {\n+\t.release\t= sq_kobj_release,\n \t.sysfs_ops\t= \u0026sq_sysfs_ops,\n \t.default_groups\t= sq_sysfs_groups,\n };\ndiff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c\nindex a993735471261c..1948b80e8a4a0e 100644\n--- a/drivers/acpi/sysfs.c\n+++ b/drivers/acpi/sysfs.c\n@@ -973,6 +973,8 @@ static struct attribute *hotplug_profile_attrs[] = {\n ATTRIBUTE_GROUPS(hotplug_profile);\n \n static const struct kobj_type acpi_hotplug_profile_ktype = {\n+\t/* Pre-existing: hotplug-\u003ekobj is embedded in static struct acpi_scan_hotplug objects. */\n+\t.release = NULL,\n \t.sysfs_ops = \u0026kobj_sysfs_ops,\n \t.default_groups = hotplug_profile_groups,\n };\ndiff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c\nindex 02bfd46543e99c..146a2353b1a204 100644\n--- a/drivers/cpufreq/cpufreq_conservative.c\n+++ b/drivers/cpufreq/cpufreq_conservative.c\n@@ -318,7 +318,10 @@ static void cs_limits(struct cpufreq_policy *policy)\n \n static struct dbs_governor cs_governor = {\n \t.gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER(\"conservative\"),\n-\t.kobj_type = { .default_groups = cs_groups },\n+\t.kobj_type = {\n+\t\t.release = cpufreq_dbs_data_release,\n+\t\t.default_groups = cs_groups,\n+\t},\n \t.gov_dbs_update = cs_dbs_update,\n \t.alloc = cs_alloc,\n \t.free = cs_free,\ndiff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c\nindex f3bd3dbe7c419c..f8b5aca09b6b69 100644\n--- a/drivers/cpufreq/cpufreq_governor.c\n+++ b/drivers/cpufreq/cpufreq_governor.c\n@@ -419,7 +419,7 @@ static void free_policy_dbs_info(struct policy_dbs_info *policy_dbs,\n \tgov-\u003efree(policy_dbs);\n }\n \n-static void cpufreq_dbs_data_release(struct kobject *kobj)\n+void cpufreq_dbs_data_release(struct kobject *kobj)\n {\n \tstruct dbs_data *dbs_data = to_dbs_data(to_gov_attr_set(kobj));\n \tstruct dbs_governor *gov = dbs_data-\u003egov;\n@@ -427,6 +427,7 @@ static void cpufreq_dbs_data_release(struct kobject *kobj)\n \tgov-\u003eexit(dbs_data);\n \tkfree(dbs_data);\n }\n+EXPORT_SYMBOL_GPL(cpufreq_dbs_data_release);\n \n int cpufreq_dbs_governor_init(struct cpufreq_policy *policy)\n {\n@@ -488,7 +489,6 @@ int cpufreq_dbs_governor_init(struct cpufreq_policy *policy)\n \tpolicy-\u003egovernor_data = policy_dbs;\n \n \tgov-\u003ekobj_type.sysfs_ops = \u0026governor_sysfs_ops;\n-\tgov-\u003ekobj_type.release = cpufreq_dbs_data_release;\n \tret = kobject_init_and_add(\u0026dbs_data-\u003eattr_set.kobj, \u0026gov-\u003ekobj_type,\n \t\t\t\t get_governor_parent_kobj(policy),\n \t\t\t\t \"%s\", gov-\u003egov.name);\ndiff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h\nindex 806d8fb4dff1d9..1026712bb79b87 100644\n--- a/drivers/cpufreq/cpufreq_governor.h\n+++ b/drivers/cpufreq/cpufreq_governor.h\n@@ -150,6 +150,7 @@ static inline struct dbs_governor *dbs_governor_of(struct cpufreq_policy *policy\n }\n \n /* Governor callback routines */\n+void cpufreq_dbs_data_release(struct kobject *kobj);\n int cpufreq_dbs_governor_init(struct cpufreq_policy *policy);\n void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy);\n int cpufreq_dbs_governor_start(struct cpufreq_policy *policy);\ndiff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c\nindex 9942dbb38dae41..7386d043c66541 100644\n--- a/drivers/cpufreq/cpufreq_ondemand.c\n+++ b/drivers/cpufreq/cpufreq_ondemand.c\n@@ -374,7 +374,10 @@ static struct od_ops od_ops = {\n \n static struct dbs_governor od_dbs_gov = {\n \t.gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER(\"ondemand\"),\n-\t.kobj_type = { .default_groups = od_groups },\n+\t.kobj_type = {\n+\t\t.release = cpufreq_dbs_data_release,\n+\t\t.default_groups = od_groups,\n+\t},\n \t.gov_dbs_update = od_dbs_update,\n \t.alloc = od_alloc,\n \t.free = od_free,\ndiff --git a/drivers/dma/ioat/sysfs.c b/drivers/dma/ioat/sysfs.c\nindex e796ddb5383f8f..5ba44876eb96e3 100644\n--- a/drivers/dma/ioat/sysfs.c\n+++ b/drivers/dma/ioat/sysfs.c\n@@ -167,6 +167,13 @@ static const struct attribute *const ioat_attrs[] = {\n ATTRIBUTE_GROUPS(ioat);\n \n const struct kobj_type ioat_ktype = {\n+\t/*\n+\t * Pre-existing: ioatdma_chan is freed by release_ioatdma(), not\n+\t * by kobject_put(). With CONFIG_DEBUG_KOBJECT_RELEASE the delayed\n+\t * kobject cleanup queued by ioat_kobject_del() may run after\n+\t * that kfree(), a use-after-free.\n+\t */\n+\t.release = NULL,\n \t.sysfs_ops = \u0026ioat_sysfs_ops,\n \t.default_groups = ioat_groups,\n };\ndiff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c\nindex 17888cf544472c..c2cccd924b03c4 100644\n--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c\n+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c\n@@ -885,6 +885,11 @@ static const struct attribute_group ualink_xcp_info_group = {\n };\n \n static const struct kobj_type ualink_xcp_info_ktype = {\n+\t/*\n+\t * Pre-existing: xcp-\u003eualink.kobj is embedded in struct amdgpu_xcp_mgr\n+\t * rather than freed individually by kobject_put().\n+\t */\n+\t.release = NULL,\n \t.sysfs_ops = \u0026kobj_sysfs_ops\n };\n \ndiff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c\nindex ab14079d1c4222..0847134a139171 100644\n--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c\n+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c\n@@ -797,6 +797,11 @@ static const struct sysfs_ops xcp_cfg_res_sysfs_ops = {\n };\n \n static const struct kobj_type xcp_cfg_res_sysfs_ktype = {\n+\t/*\n+\t * Pre-existing: xcp_res is embedded in struct amdgpu_xcp_cfg\n+\t * rather than freed individually by kobject_put().\n+\t */\n+\t.release = NULL,\n \t.sysfs_ops = \u0026xcp_cfg_res_sysfs_ops,\n \t.default_groups = xcp_cfg_res_sysfs_groups,\n };\n@@ -1061,6 +1066,11 @@ static const struct attribute_group amdgpu_xcp_attrs_group = {\n };\n \n static const struct kobj_type xcp_sysfs_ktype = {\n+\t/*\n+\t * Pre-existing: xcp is embedded in struct amdgpu_xcp_mgr\n+\t * rather than freed individually by kobject_put().\n+\t */\n+\t.release = NULL,\n \t.sysfs_ops = \u0026kobj_sysfs_ops,\n };\n \ndiff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c\nindex 226f52626e849d..8e6136d52a50d0 100644\n--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c\n+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c\n@@ -512,7 +512,15 @@ static const struct sysfs_ops procfs_queue_ops = {\n \t.show = kfd_procfs_queue_show,\n };\n \n+static void kfd_procfs_queue_release(struct kobject *kobj)\n+{\n+\tstruct queue *q = container_of(kobj, struct queue, kobj);\n+\n+\tkfree(q);\n+}\n+\n static const struct kobj_type procfs_queue_type = {\n+\t.release = kfd_procfs_queue_release,\n \t.sysfs_ops = \u0026procfs_queue_ops,\n \t.default_groups = procfs_queue_groups,\n };\n@@ -552,7 +560,6 @@ int kfd_procfs_add_queue(struct queue *q)\n \tif (ret \u003c 0) {\n \t\tpr_warn(\"Creating proc/\u003cpid\u003e/queues/%u failed\",\n \t\t\tq-\u003eproperties.queue_id);\n-\t\tkobject_put(\u0026q-\u003ekobj);\n \t\treturn ret;\n \t}\n \n@@ -697,11 +704,10 @@ static void kfd_procfs_add_sysfs_files(struct kfd_process *p)\n \n void kfd_procfs_del_queue(struct queue *q)\n {\n-\tif (!q || !q-\u003eprocess-\u003ekobj)\n+\tif (!q || !q-\u003eprocess || !q-\u003eprocess-\u003ekobj || !q-\u003ekobj.state_in_sysfs)\n \t\treturn;\n \n \tkobject_del(\u0026q-\u003ekobj);\n-\tkobject_put(\u0026q-\u003ekobj);\n }\n \n int kfd_process_create_wq(void)\ndiff --git a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c\nindex ae3e7c54014a86..4666110aebe07c 100644\n--- a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c\n+++ b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c\n@@ -83,7 +83,10 @@ int init_queue(struct queue **q, const struct queue_properties *properties)\n \n void uninit_queue(struct queue *q)\n {\n-\tkfree(q);\n+\tif (q \u0026\u0026 q-\u003ekobj.state_initialized)\n+\t\tkobject_put(\u0026q-\u003ekobj);\n+\telse\n+\t\tkfree(q);\n }\n \n #if IS_ENABLED(CONFIG_HSA_AMD_SVM)\ndiff --git a/drivers/infiniband/hw/hfi1/sysfs.c b/drivers/infiniband/hw/hfi1/sysfs.c\nindex 372cfd13dc6160..5a1aca06b542b2 100644\n--- a/drivers/infiniband/hw/hfi1/sysfs.c\n+++ b/drivers/infiniband/hw/hfi1/sysfs.c\n@@ -608,6 +608,11 @@ static const struct sysfs_ops sde_sysfs_ops = {\n };\n \n static struct kobj_type sde_ktype = {\n+\t/*\n+\t * Pre-existing: sdma_engine is embedded in dd-\u003eper_sdma array\n+\t * rather than freed by kobject_put().\n+\t */\n+\t.release = NULL,\n \t.sysfs_ops = \u0026sde_sysfs_ops,\n };\n \ndiff --git a/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c b/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c\nindex fdb63a8fb9974b..df0e48070c2ee9 100644\n--- a/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c\n+++ b/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c\n@@ -245,6 +245,8 @@ static struct attribute *usnic_ib_qpn_default_attrs[] = {\n ATTRIBUTE_GROUPS(usnic_ib_qpn_default);\n \n static struct kobj_type usnic_ib_qpn_type = {\n+\t/* Pre-existing: usnic_ib_qp_grp is embedded in RDMA core-managed struct usnic_ib_qp_grp. */\n+\t.release = NULL,\n \t.sysfs_ops = \u0026usnic_ib_qpn_sysfs_ops,\n \t.default_groups = usnic_ib_qpn_default_groups,\n };\ndiff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c\nindex 6b567a74fc2cb2..2f530e8c675793 100644\n--- a/drivers/parisc/pdc_stable.c\n+++ b/drivers/parisc/pdc_stable.c\n@@ -484,6 +484,11 @@ ATTRIBUTE_GROUPS(paths_subsys);\n \n /* Specific kobject type for our PDC paths */\n static const struct kobj_type ktype_pdcspath = {\n+\t/*\n+\t * Pre-existing: pdcspath_entry instances are static; lifetime\n+\t * is not controlled by kobject_put().\n+\t */\n+\t.release = NULL,\n \t.sysfs_ops = \u0026pdcspath_attr_ops,\n \t.default_groups = paths_subsys_groups,\n };\ndiff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c\nindex e6b5efdf5dc9bc..d62411e4f5355d 100644\n--- a/drivers/power/supply/ab8500_fg.c\n+++ b/drivers/power/supply/ab8500_fg.c\n@@ -2531,6 +2531,11 @@ static struct attribute *ab8500_fg_attrs[] = {\n ATTRIBUTE_GROUPS(ab8500_fg);\n \n static const struct kobj_type ab8500_fg_ktype = {\n+\t/*\n+\t * Pre-existing: fg_kobject is embedded in devm-allocated struct\n+\t * ab8500_fg; ab8500_fg_sysfs_exit() only calls kobject_del().\n+\t */\n+\t.release = NULL,\n \t.sysfs_ops = \u0026ab8500_fg_sysfs_ops,\n \t.default_groups = ab8500_fg_groups,\n };\ndiff --git a/drivers/s390/char/sclp_mem.c b/drivers/s390/char/sclp_mem.c\nindex 6df1926d4c62a1..2fb7271dce362f 100644\n--- a/drivers/s390/char/sclp_mem.c\n+++ b/drivers/s390/char/sclp_mem.c\n@@ -305,6 +305,8 @@ static ssize_t sclp_memmap_on_memory_store(struct kobject *kobj, struct kobj_att\n }\n \n static const struct kobj_type ktype = {\n+\t/* Pre-existing: permanent firmware kobjects, never freed */\n+\t.release = NULL,\n \t.sysfs_ops = \u0026kobj_sysfs_ops,\n };\n \ndiff --git a/drivers/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c\nindex 0cc2953d59a54b..da7a64c9505878 100644\n--- a/drivers/soc/hisilicon/kunpeng_hccs.c\n+++ b/drivers/soc/hisilicon/kunpeng_hccs.c\n@@ -1038,6 +1038,13 @@ static struct attribute *hccs_port_default_attrs[] = {\n ATTRIBUTE_GROUPS(hccs_port_default);\n \n static const struct kobj_type hccs_port_type = {\n+\t/*\n+\t * Pre-existing: hccs_port_info is allocated via devm_kzalloc()\n+\t * rather than freed by kobject_put(). With\n+\t * CONFIG_DEBUG_KOBJECT_RELEASE the delayed kobject cleanup may run\n+\t * after devm frees it on unbind, a use-after-free.\n+\t */\n+\t.release = NULL,\n \t.sysfs_ops = \u0026hccs_comm_ops,\n \t.default_groups = hccs_port_default_groups,\n };\n@@ -1110,6 +1117,13 @@ static struct attribute *hccs_die_default_attrs[] = {\n ATTRIBUTE_GROUPS(hccs_die_default);\n \n static const struct kobj_type hccs_die_type = {\n+\t/*\n+\t * Pre-existing: hccs_die_info is allocated via devm_kzalloc()\n+\t * rather than freed by kobject_put(). With\n+\t * CONFIG_DEBUG_KOBJECT_RELEASE the delayed kobject cleanup may run\n+\t * after devm frees it on unbind, a use-after-free.\n+\t */\n+\t.release = NULL,\n \t.sysfs_ops = \u0026hccs_comm_ops,\n \t.default_groups = hccs_die_default_groups,\n };\n@@ -1213,6 +1227,13 @@ static struct attribute *hccs_chip_default_attrs[] = {\n ATTRIBUTE_GROUPS(hccs_chip_default);\n \n static const struct kobj_type hccs_chip_type = {\n+\t/*\n+\t * Pre-existing: hccs_chip_info is allocated via devm_kzalloc()\n+\t * rather than freed by kobject_put(). With\n+\t * CONFIG_DEBUG_KOBJECT_RELEASE the delayed kobject cleanup may run\n+\t * after devm frees it on unbind, a use-after-free.\n+\t */\n+\t.release = NULL,\n \t.sysfs_ops = \u0026hccs_comm_ops,\n \t.default_groups = hccs_chip_default_groups,\n };\ndiff --git a/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c b/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c\nindex ae937854403b12..452920a4e2a9a9 100644\n--- a/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c\n+++ b/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c\n@@ -304,6 +304,13 @@ static const struct sysfs_ops display_sysfs_ops = {\n };\n \n static struct kobj_type display_ktype = {\n+\t/*\n+\t * Pre-existing: dssdev-\u003ekobj is embedded in struct omap_dss_device\n+\t * and zeroed in display_uninit_sysfs() right after kobject_put().\n+\t * With CONFIG_DEBUG_KOBJECT_RELEASE that memset() clobbers the\n+\t * pending delayed kobject cleanup.\n+\t */\n+\t.release = NULL,\n \t.sysfs_ops = \u0026display_sysfs_ops,\n \t.default_groups = display_sysfs_groups,\n };\ndiff --git a/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c b/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c\nindex 1b644be5fe2ed0..40ec750f431559 100644\n--- a/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c\n+++ b/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c\n@@ -496,6 +496,11 @@ static const struct sysfs_ops manager_sysfs_ops = {\n };\n \n static struct kobj_type manager_ktype = {\n+\t/*\n+\t * Pre-existing: mgr-\u003ekobj is embedded in static managers[] and\n+\t * zeroed in dss_manager_kobj_uninit().\n+\t */\n+\t.release = NULL,\n \t.sysfs_ops = \u0026manager_sysfs_ops,\n \t.default_groups = manager_sysfs_groups,\n };\ndiff --git a/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c b/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c\nindex 1da4fb1c77b4a6..4d333031b18d6d 100644\n--- a/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c\n+++ b/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c\n@@ -429,6 +429,11 @@ static const struct sysfs_ops overlay_sysfs_ops = {\n };\n \n static struct kobj_type overlay_ktype = {\n+\t/*\n+\t * Pre-existing: ovl-\u003ekobj is embedded in static overlays[];\n+\t * dss_overlay_kobj_uninit() drops the kobject ref.\n+\t */\n+\t.release = NULL,\n \t.sysfs_ops = \u0026overlay_sysfs_ops,\n \t.default_groups = overlay_sysfs_groups,\n };\ndiff --git a/drivers/xen/sys-hypervisor.c b/drivers/xen/sys-hypervisor.c\nindex 91923242a5ae71..0e8a2cd69fd69a 100644\n--- a/drivers/xen/sys-hypervisor.c\n+++ b/drivers/xen/sys-hypervisor.c\n@@ -659,7 +659,13 @@ static const struct sysfs_ops hyp_sysfs_ops = {\n \t.store = hyp_sysfs_store,\n };\n \n+static void hyp_sysfs_release(struct kobject *kobj)\n+{\n+\tkfree(kobj);\n+}\n+\n static const struct kobj_type hyp_sysfs_kobj_type = {\n+\t.release = hyp_sysfs_release,\n \t.sysfs_ops = \u0026hyp_sysfs_ops,\n };\n \ndiff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h\nindex 74c2e77d1b553e..95b3bff0cb57aa 100644\n--- a/fs/dlm/dlm_internal.h\n+++ b/fs/dlm/dlm_internal.h\n@@ -576,6 +576,7 @@ struct dlm_ls {\n \tint\t\t\tls_create_count; /* create/release refcount */\n \tunsigned long\t\tls_flags;\t/* LSFL_ */\n \tstruct kobject\t\tls_kobj;\n+\tstruct completion\tls_kobj_done;\n \n \tstruct xarray\t\tls_lkbxa;\n \trwlock_t\t\tls_lkbxa_lock;\ndiff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c\nindex a9c98b4f378f3a..2dccd080a10f64 100644\n--- a/fs/dlm/lockspace.c\n+++ b/fs/dlm/lockspace.c\n@@ -179,7 +179,15 @@ static const struct sysfs_ops dlm_attr_ops = {\n \t.store = dlm_attr_store,\n };\n \n+static void dlm_ls_release(struct kobject *kobj)\n+{\n+\tstruct dlm_ls *ls = container_of(kobj, struct dlm_ls, ls_kobj);\n+\n+\tcomplete(\u0026ls-\u003els_kobj_done);\n+}\n+\n static struct kobj_type dlm_ktype = {\n+\t.release = dlm_ls_release,\n \t.default_groups = dlm_groups,\n \t.sysfs_ops = \u0026dlm_attr_ops,\n };\n@@ -355,6 +363,8 @@ static void free_lockspace(struct work_struct *work)\n \t */\n \trhashtable_free_and_destroy(\u0026ls-\u003els_rsbtbl, rhash_free_rsb, NULL);\n \n+\tkobject_put(\u0026ls-\u003els_kobj);\n+\twait_for_completion(\u0026ls-\u003els_kobj_done);\n \tkfree(ls);\n }\n \n@@ -435,7 +445,10 @@ static int new_lockspace(const char *name, const char *cluster,\n \tls-\u003els_lvblen = lvblen;\n \tatomic_set(\u0026ls-\u003els_count, 0);\n \tinit_waitqueue_head(\u0026ls-\u003els_count_wait);\n+\tinit_completion(\u0026ls-\u003els_kobj_done);\n \tls-\u003els_flags = 0;\n+\tls-\u003els_kobj.kset = dlm_kset;\n+\tkobject_init(\u0026ls-\u003els_kobj, \u0026dlm_ktype);\n \n \tif (ops \u0026\u0026 dlm_config.ci_recover_callbacks) {\n \t\tls-\u003els_ops = ops;\n@@ -567,9 +580,7 @@ static int new_lockspace(const char *name, const char *cluster,\n \twait_event(ls-\u003els_recover_lock_wait,\n \t\t test_bit(LSFL_RECOVER_LOCK, \u0026ls-\u003els_flags));\n \n-\tls-\u003els_kobj.kset = dlm_kset;\n-\terror = kobject_init_and_add(\u0026ls-\u003els_kobj, \u0026dlm_ktype, NULL,\n-\t\t\t\t \"%s\", ls-\u003els_name);\n+\terror = kobject_add(\u0026ls-\u003els_kobj, NULL, \"%s\", ls-\u003els_name);\n \tif (error)\n \t\tgoto out_recoverd;\n \tkobject_uevent(\u0026ls-\u003els_kobj, KOBJ_ADD);\n@@ -582,7 +593,7 @@ static int new_lockspace(const char *name, const char *cluster,\n \n \terror = do_uevent(ls, 1, 0);\n \tif (error \u003c 0)\n-\t\tgoto out_recoverd;\n+\t\tgoto out_kobj;\n \n \t/* wait until recovery is successful or failed */\n \twait_for_completion(\u0026ls-\u003els_recovery_done);\n@@ -600,6 +611,8 @@ static int new_lockspace(const char *name, const char *cluster,\n \tdo_uevent(ls, 0, 0);\n \tdlm_clear_members(ls);\n \tkfree(ls-\u003els_node_array);\n+ out_kobj:\n+\tkobject_del(\u0026ls-\u003els_kobj);\n out_recoverd:\n \tdlm_recoverd_stop(ls);\n out_callback:\n@@ -615,6 +628,7 @@ static int new_lockspace(const char *name, const char *cluster,\n \trhashtable_destroy(\u0026ls-\u003els_rsbtbl);\n out_lsfree:\n \tkobject_put(\u0026ls-\u003els_kobj);\n+\twait_for_completion(\u0026ls-\u003els_kobj_done);\n \tkfree(ls);\n out:\n \tmodule_put(THIS_MODULE);\n@@ -740,6 +754,8 @@ static int release_lockspace(struct dlm_ls *ls, unsigned int release_option)\n \t dlm_user_daemon_available())\n \t\tdo_uevent(ls, 0, (release_option == DLM_RELEASE_RECOVER));\n \n+\tkobject_del(\u0026ls-\u003els_kobj);\n+\n \tdlm_recoverd_stop(ls);\n \n \t/* clear the LSFL_RUNNING flag to fast up\n@@ -759,8 +775,6 @@ static int release_lockspace(struct dlm_ls *ls, unsigned int release_option)\n \n \tdlm_delete_debug_file(ls);\n \n-\tkobject_put(\u0026ls-\u003els_kobj);\n-\n \txa_destroy(\u0026ls-\u003els_recover_xa);\n \tkfree(ls-\u003els_recover_buf);\n \ndiff --git a/fs/erofs/sysfs.c b/fs/erofs/sysfs.c\nindex dfcec9376cd54d..2ea6773cd98fdd 100644\n--- a/fs/erofs/sysfs.c\n+++ b/fs/erofs/sysfs.c\n@@ -238,6 +238,11 @@ static const struct kobj_type erofs_sb_ktype = {\n static const struct kobj_type erofs_ktype = {\n \t.default_groups = erofs_groups,\n \t.sysfs_ops\t= \u0026erofs_attr_ops,\n+\t/*\n+\t * Pre-existing: erofs_root is a static struct kset; lifetime\n+\t * is not controlled by kobject_put().\n+\t */\n+\t.release\t= NULL,\n };\n \n static struct kset erofs_root = {\n@@ -247,6 +252,11 @@ static struct kset erofs_root = {\n static const struct kobj_type erofs_feat_ktype = {\n \t.default_groups = erofs_feat_groups,\n \t.sysfs_ops\t= \u0026erofs_attr_ops,\n+\t/*\n+\t * Pre-existing: erofs_feat is a static struct kobject; lifetime\n+\t * is not controlled by kobject_put().\n+\t */\n+\t.release\t= NULL,\n };\n \n static struct kobject erofs_feat = {\ndiff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c\nindex 430356e500afd6..6e15695cb75f1c 100644\n--- a/fs/f2fs/sysfs.c\n+++ b/fs/f2fs/sysfs.c\n@@ -1683,6 +1683,11 @@ static const struct kobj_type f2fs_sb_ktype = {\n \n static const struct kobj_type f2fs_ktype = {\n \t.sysfs_ops\t= \u0026f2fs_attr_ops,\n+\t/*\n+\t * Pre-existing: f2fs_kset is a static struct kset; lifetime\n+\t * is not controlled by kobject_put().\n+\t */\n+\t.release\t= NULL,\n };\n \n static struct kset f2fs_kset = {\n@@ -1697,6 +1702,11 @@ static const struct sysfs_ops f2fs_feat_attr_ops = {\n static const struct kobj_type f2fs_feat_ktype = {\n \t.default_groups = f2fs_feat_groups,\n \t.sysfs_ops\t= \u0026f2fs_feat_attr_ops,\n+\t/*\n+\t * Pre-existing: f2fs_feat is a static struct kobject; lifetime\n+\t * is not controlled by kobject_put().\n+\t */\n+\t.release\t= NULL,\n };\n \n static struct kobject f2fs_feat = {\n@@ -1711,6 +1721,11 @@ static const struct sysfs_ops f2fs_tune_attr_ops = {\n static const struct kobj_type f2fs_tune_ktype = {\n \t.default_groups = f2fs_tune_groups,\n \t.sysfs_ops\t= \u0026f2fs_tune_attr_ops,\n+\t/*\n+\t * Pre-existing: f2fs_tune is a static struct kobject; lifetime\n+\t * is not controlled by kobject_put().\n+\t */\n+\t.release\t= NULL,\n };\n \n static struct kobject f2fs_tune = {\ndiff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c\nindex 563881ddbf00c8..ff8a1cf51e72f7 100644\n--- a/fs/ocfs2/cluster/masklog.c\n+++ b/fs/ocfs2/cluster/masklog.c\n@@ -147,6 +147,11 @@ static const struct sysfs_ops mlog_attr_ops = {\n static struct kobj_type mlog_ktype = {\n \t.default_groups = mlog_default_groups,\n \t.sysfs_ops = \u0026mlog_attr_ops,\n+\t/*\n+\t * Pre-existing: mlog_kset is a static struct kset; lifetime\n+\t * is not controlled by kobject_put().\n+\t */\n+\t.release = NULL,\n };\n \n static struct kset mlog_kset = {\ndiff --git a/fs/ubifs/sysfs.c b/fs/ubifs/sysfs.c\nindex dbf967dcf26e66..e20931e3a62f96 100644\n--- a/fs/ubifs/sysfs.c\n+++ b/fs/ubifs/sysfs.c\n@@ -80,13 +80,7 @@ static const struct kobj_type ubifs_sb_ktype = {\n \t.release\t= ubifs_sb_release,\n };\n \n-static const struct kobj_type ubifs_ktype = {\n-\t.sysfs_ops\t= \u0026ubifs_attr_ops,\n-};\n-\n-static struct kset ubifs_kset = {\n-\t.kobj\t= {.ktype = \u0026ubifs_ktype},\n-};\n+static struct kset *ubifs_kset;\n \n int ubifs_sysfs_register(struct ubifs_info *c)\n {\n@@ -107,7 +101,7 @@ int ubifs_sysfs_register(struct ubifs_info *c)\n \t\tgoto out_free;\n \t}\n \n-\tc-\u003ekobj.kset = \u0026ubifs_kset;\n+\tc-\u003ekobj.kset = ubifs_kset;\n \tinit_completion(\u0026c-\u003ekobj_unregister);\n \n \tret = kobject_init_and_add(\u0026c-\u003ekobj, \u0026ubifs_sb_ktype, NULL,\n@@ -139,18 +133,14 @@ void ubifs_sysfs_unregister(struct ubifs_info *c)\n \n int __init ubifs_sysfs_init(void)\n {\n-\tint ret;\n+\tubifs_kset = kset_create_and_add(\"ubifs\", NULL, fs_kobj);\n+\tif (!ubifs_kset)\n+\t\treturn -ENOMEM;\n \n-\tkobject_set_name(\u0026ubifs_kset.kobj, \"ubifs\");\n-\tubifs_kset.kobj.parent = fs_kobj;\n-\tret = kset_register(\u0026ubifs_kset);\n-\tif (ret)\n-\t\tkset_put(\u0026ubifs_kset);\n-\n-\treturn ret;\n+\treturn 0;\n }\n \n void ubifs_sysfs_exit(void)\n {\n-\tkset_unregister(\u0026ubifs_kset);\n+\tkset_unregister(ubifs_kset);\n }\ndiff --git a/include/linux/compiler_attributes.h b/include/linux/compiler_attributes.h\nindex 476c4c560d1743..b9c0b56dd22e79 100644\n--- a/include/linux/compiler_attributes.h\n+++ b/include/linux/compiler_attributes.h\n@@ -322,6 +322,18 @@\n */\n #define __pure __attribute__((__pure__))\n \n+/*\n+ * Optional: not supported by gcc\n+ * Optional: only supported since clang \u003e= 20.0\n+ *\n+ * clang: https://clang.llvm.org/docs/AttributeReference.html#require-explicit-initialization\n+ */\n+#if __has_attribute(__require_explicit_initialization__)\n+# define __must_init __attribute__((__require_explicit_initialization__))\n+#else\n+# define __must_init\n+#endif\n+\n /*\n * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-section-function-attribute\n * gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-section-variable-attribute\ndiff --git a/include/linux/kobject.h b/include/linux/kobject.h\nindex 55e37a5d405ef7..8a133203088477 100644\n--- a/include/linux/kobject.h\n+++ b/include/linux/kobject.h\n@@ -114,7 +114,7 @@ void kobject_get_ownership(const struct kobject *kobj, kuid_t *uid, kgid_t *gid)\n char *kobject_get_path(const struct kobject *kobj, gfp_t flag);\n \n struct kobj_type {\n-\tvoid (*release)(struct kobject *kobj);\n+\tvoid (*release)(struct kobject *kobj) __must_init;\n \tconst struct sysfs_ops *sysfs_ops;\n \tconst struct attribute_group **default_groups;\n \tconst struct kobj_ns_type_operations *(*child_ns_type)(const struct kobject *kobj);\ndiff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl\nindex c9840f5219c2a9..5232f66d2b80f1 100755\n--- a/scripts/checkpatch.pl\n+++ b/scripts/checkpatch.pl\n@@ -6860,6 +6860,7 @@ sub process {\n \t\t\t\t\"noreturn\"\t\t\t=\u003e \"__noreturn\",\n \t\t\t\t\"packed\"\t\t\t=\u003e \"__packed\",\n \t\t\t\t\"pure\"\t\t\t\t=\u003e \"__pure\",\n+\t\t\t\t\"require_explicit_initialization\" =\u003e \"__must_init\",\n \t\t\t\t\"section\"\t\t\t=\u003e \"__section\",\n \t\t\t\t\"used\"\t\t\t\t=\u003e \"__used\",\n \t\t\t\t\"weak\"\t\t\t\t=\u003e \"__weak\"\ndiff --git a/tools/lib/python/kdoc/xforms_lists.py b/tools/lib/python/kdoc/xforms_lists.py\nindex 320f977c5bac2c..3c744cbd2f34f7 100644\n--- a/tools/lib/python/kdoc/xforms_lists.py\n+++ b/tools/lib/python/kdoc/xforms_lists.py\n@@ -36,6 +36,7 @@ class CTransforms:\n (CMatch(\"CRYPTO_MINALIGN_ATTR\"), \"\"),\n (CMatch(\"__private\"), \"\"),\n (CMatch(\"__rcu\"), \"\"),\n+ (CMatch(\"__must_init\"), \"\"),\n (CMatch(\"____cacheline_aligned_in_smp\"), \"\"),\n (CMatch(\"____cacheline_aligned\"), \"\"),\n (CMatch(\"__cacheline_group_(?:begin|end)\"), \"\"),\n"
} |
| 2/1 | 2026/10/28 06:19 | agent | patch-evaluator |
4mModel:core Args: null Results: {
"EnableConfigs": [
"DLM",
"CONFIGFS_FS",
"SYSFS",
"INET",
"UBIFS_FS",
"MTD_UBI",
"CPU_FREQ",
"CPU_FREQ_GOV_ONDEMAND",
"CPU_FREQ_GOV_CONSERVATIVE"
],
"FocusSymbols": [
"dlm_ls_release",
"free_lockspace",
"new_lockspace",
"release_lockspace",
"dlm_new_lockspace",
"dlm_release_lockspace",
"dlm_new_user_lockspace",
"ubifs_sysfs_register",
"ubifs_sysfs_unregister",
"cpufreq_dbs_data_release"
],
"Reasoning": "The patch introduces '__must_init' on 'struct kobj_type.release' and addresses missing or improper kobject release callbacks across various drivers and subsystems. In reachable core subsystems on amd64, notable functional and synchronization refactorings were introduced:\n1. In fs/dlm/lockspace.c, the lifecycle of struct dlm_ls kobjects was overhauled by introducing a new completion (ls_kobj_done), a release callback (dlm_ls_release), reordered kobject initialization/teardown in new_lockspace(), moving kobject_put() into free_lockspace(), and waiting on the completion before freeing the lockspace. This changes destruction and synchronization behavior on code accessible via /dev/dlm-control and filesystem mounts.\n2. In fs/ubifs/sysfs.c, ubifs_kset was transitioned from a static struct kset to a dynamically allocated kset created via kset_create_and_add().\n3. In drivers/cpufreq/, dbs_governor kobj_type release callback handling was refactored with exported cpufreq_dbs_data_release.\n\nThese alterations in reachable filesystem and core subsystem lifecycle code warrant fuzzing to identify potential regressions, use-after-free, or hang/deadlock conditions (particularly around the new completion wait during dlm lockspace teardown).",
"WorthFuzzing": true
}Instruction: You are an expert Linux kernel maintainer and security engineer.
Your job is to review a provided patch series and evaluate whether it warrants fuzzing with syzkaller.
IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on internal assumptions. You must actively use your code access
tools to inspect the actual source code, callers, and surrounding context.
================================================================================
1. CORE TRIAGE PHILOSOPHY
================================================================================
The goal of patch fuzzing is to discover crashes, regressions, exposed latent bugs,
and newly triggered assertions introduced by the patch series.
- REACHABILITY IS THE PRIMARY GATE:
Fuzzing can only discover bugs in code that can actually execute in standard virtualized
environments (GCE or QEMU, utilizing software-emulated devices like USB gadgets, netdev, tun/tap).
If the modified code is structurally unreachable (see Section 2), it MUST NOT be fuzzed,
regardless of whether it adds assertions or complex logic.
- DO NOT BLINDLY TRUST "NO FUNCTIONAL CHANGE" (NFCI) OR "REFACTORING" CLAIMS:
Patch authors routinely label changes as "cleanups", "refactorings", or state
"No functional change intended". Do NOT take these claims at face value.
Code refactorings that rearrange logic, introduce helper functions, or alter state management
in core subsystems frequently introduce subtle semantic shifts or uncover latent kernel bugs.
If reachable executable code is modified or refactored, it MUST be fuzzed.
- NEW OR MODIFIED ASSERTIONS IN REACHABLE CODE MUST BE FUZZED:
When a patch introduces or modifies runtime checks or assertions (e.g., WARN_ON*, VM_WARN_ON*,
BUG_ON*, lockdep_assert*) in reachable code paths, it enforces new or stricter invariants.
Even if the author believes the invariant always holds, fuzzing is essential to verify whether
an unusual sequence of operations can violate it.
================================================================================
2. WHEN TO RETURN WorthFuzzing=false (NEGATIVE CRITERIA)
================================================================================
Return WorthFuzzing=false ONLY IF all modified code falls strictly into one or more of these categories:
- Non-kernel and non-executable changes:
* Modifications to Documentation/, comments, or spelling fixes.
* User-space directories, self-tests, samples, or scripts (e.g., tools/, samples/, scripts/, usr/)
that do not affect the compiled kernel image (vmlinux) or kernel modules.
* Purely decorative logging (e.g., message strings in pr_err, printk, dev_info) or tracepoints
that do not alter control flow or data structures.
* Build system or Kconfig changes that do not alter compiled C logic.
- Structurally unreachable hardware:
* Vendor-specific PCIe switches, SmartNICs, or GPU drivers (e.g., mlxsw, pds_core, qed,
ionic, amdgpu) requiring physical ASIC/PCIe cards not emulated in standard QEMU.
- Unreachable execution paths:
* Driver teardown callbacks (.remove, .shutdown, pci_unregister_driver) executed only during
physical PCI hot-unplug or manual sysfs driver unbinding.
* Code paths exclusive to architectures other than the target architecture.
================================================================================
3. WHEN TO RETURN WorthFuzzing=true (POSITIVE CRITERIA)
================================================================================
Return WorthFuzzing=true whenever the patch touches reachable executable code, including:
- Core Subsystems:
* Any logic modifications in memory management (mm/), synchronization/locking (kernel/locking/),
BPF, scheduler, core networking, VFS, or syscall handling.
- Refactorings and Code Cleanups:
* Any restructuring of reachable data structures, helper abstractions, or algorithm flows.
- Runtime Assertions and Defensive Checks:
* Any introduction or alteration of assertions (WARN_ON*, VM_WARN_ON*, BUG_ON*, etc.) in reachable paths.
- Reachable Drivers and Protocols:
* Drivers accessible via virtual buses (virtio, USB gadget, loopback, netlink, binder, sockets, etc.).
================================================================================
4. EXTRACTING FocusSymbols (PREVENTING DILUTION)
================================================================================
When WorthFuzzing=true, you must extract specific kernel functions into FocusSymbols to guide the fuzzer:
- AVOID UBIQUITOUS LIFECYCLE HOT-PATHS:
Do NOT list generic, ubiquitous functions called by almost every program in the corpus
(including, but not limited to: general memory allocators and deallocators, page fault
and trap handlers, or core synchronization primitives; this is not an exhaustive list).
Listing ubiquitous functions causes the fuzzer to classify thousands of unrelated tests as "focused",
which severely dilutes fuzzing effort away from the actual changes.
- TARGET SPECIFIC FEATURE LOGIC AND ENTRYPOINTS:
List functions that specifically implement the logic being added or altered, or direct API entrypoints
for the subsystem feature under review.
- HANDLING STATIC INLINE FUNCTIONS IN HEADERS (.h):
Compiler-inlined static functions (such as static inlines in mm/*.h or include/linux/*.h) lack
distinct symbol addresses in vmlinux and cannot be targeted directly by symbol coverage filters.
If the changes are primarily in static inline helpers, identify non-static, feature-specific caller
functions in .c files that exercise them (avoiding ubiquitous lifecycle wrappers).
================================================================================
5. IDENTIFYING EnableConfigs
================================================================================
Identify any specific CONFIG_ options required to properly compile and reach the modified code:
- Inspect Kconfig files and #ifdef guards; do not make assumptions.
- Check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed.
- Strip any 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.
Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.
Prompt: Target architecture: amd64
For your convenience, here is the diff of the changes:
commit aeb7a14c32eb7ebc6a77c24bd1d1349164380cbb
Author: syz-cluster <triage@syzkaller.com>
Date: Wed Oct 28 06:19:50 2026 +0000
syz-cluster: applied patch under review
diff --git a/Documentation/conf.py b/Documentation/conf.py
index 5ab26ce89dafe6..baaa4035258c86 100644
--- a/Documentation/conf.py
+++ b/Documentation/conf.py
@@ -203,6 +203,7 @@ c_id_attributes = [
"__noreturn",
"__packed",
"__pure",
+ "__must_init",
"__section",
"__always_unused",
"__maybe_unused",
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 94e6cd211d70e6..7a4ac8dd0b86a6 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -295,6 +295,11 @@ const struct seq_operations cpuinfo_op = {
static const struct kobj_type cpuregs_kobj_type = {
+ /*
+ * Pre-existing: info->kobj is embedded in per-CPU cpu_data;
+ * cpuid_cpu_offline() only calls kobject_del().
+ */
+ .release = NULL,
.sysfs_ops = &kobj_sysfs_ops,
};
diff --git a/arch/powerpc/kernel/secvar-sysfs.c b/arch/powerpc/kernel/secvar-sysfs.c
index 395399bbab2c69..f3f6ac25ea788f 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,
};
diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c
index 908a8e09113b7d..f33864958487ba 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,
};
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index a993735471261c..1948b80e8a4a0e 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -973,6 +973,8 @@ static struct attribute *hotplug_profile_attrs[] = {
ATTRIBUTE_GROUPS(hotplug_profile);
static const struct kobj_type acpi_hotplug_profile_ktype = {
+ /* Pre-existing: hotplug->kobj is embedded in static struct acpi_scan_hotplug objects. */
+ .release = NULL,
.sysfs_ops = &kobj_sysfs_ops,
.default_groups = hotplug_profile_groups,
};
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 02bfd46543e99c..146a2353b1a204 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -318,7 +318,10 @@ static void cs_limits(struct cpufreq_policy *policy)
static struct dbs_governor cs_governor = {
.gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("conservative"),
- .kobj_type = { .default_groups = cs_groups },
+ .kobj_type = {
+ .release = cpufreq_dbs_data_release,
+ .default_groups = cs_groups,
+ },
.gov_dbs_update = cs_dbs_update,
.alloc = cs_alloc,
.free = cs_free,
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
index f3bd3dbe7c419c..f8b5aca09b6b69 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -419,7 +419,7 @@ static void free_policy_dbs_info(struct policy_dbs_info *policy_dbs,
gov->free(policy_dbs);
}
-static void cpufreq_dbs_data_release(struct kobject *kobj)
+void cpufreq_dbs_data_release(struct kobject *kobj)
{
struct dbs_data *dbs_data = to_dbs_data(to_gov_attr_set(kobj));
struct dbs_governor *gov = dbs_data->gov;
@@ -427,6 +427,7 @@ static void cpufreq_dbs_data_release(struct kobject *kobj)
gov->exit(dbs_data);
kfree(dbs_data);
}
+EXPORT_SYMBOL_GPL(cpufreq_dbs_data_release);
int cpufreq_dbs_governor_init(struct cpufreq_policy *policy)
{
@@ -488,7 +489,6 @@ int cpufreq_dbs_governor_init(struct cpufreq_policy *policy)
policy->governor_data = policy_dbs;
gov->kobj_type.sysfs_ops = &governor_sysfs_ops;
- gov->kobj_type.release = cpufreq_dbs_data_release;
ret = kobject_init_and_add(&dbs_data->attr_set.kobj, &gov->kobj_type,
get_governor_parent_kobj(policy),
"%s", gov->gov.name);
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h
index 806d8fb4dff1d9..1026712bb79b87 100644
--- a/drivers/cpufreq/cpufreq_governor.h
+++ b/drivers/cpufreq/cpufreq_governor.h
@@ -150,6 +150,7 @@ static inline struct dbs_governor *dbs_governor_of(struct cpufreq_policy *policy
}
/* Governor callback routines */
+void cpufreq_dbs_data_release(struct kobject *kobj);
int cpufreq_dbs_governor_init(struct cpufreq_policy *policy);
void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy);
int cpufreq_dbs_governor_start(struct cpufreq_policy *policy);
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 9942dbb38dae41..7386d043c66541 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,
diff --git a/drivers/dma/ioat/sysfs.c b/drivers/dma/ioat/sysfs.c
index e796ddb5383f8f..5ba44876eb96e3 100644
--- a/drivers/dma/ioat/sysfs.c
+++ b/drivers/dma/ioat/sysfs.c
@@ -167,6 +167,13 @@ static const struct attribute *const ioat_attrs[] = {
ATTRIBUTE_GROUPS(ioat);
const struct kobj_type ioat_ktype = {
+ /*
+ * Pre-existing: ioatdma_chan is freed by release_ioatdma(), not
+ * by kobject_put(). With CONFIG_DEBUG_KOBJECT_RELEASE the delayed
+ * kobject cleanup queued by ioat_kobject_del() may run after
+ * that kfree(), a use-after-free.
+ */
+ .release = NULL,
.sysfs_ops = &ioat_sysfs_ops,
.default_groups = ioat_groups,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
index 17888cf544472c..c2cccd924b03c4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
@@ -885,6 +885,11 @@ static const struct attribute_group ualink_xcp_info_group = {
};
static const struct kobj_type ualink_xcp_info_ktype = {
+ /*
+ * Pre-existing: xcp->ualink.kobj is embedded in struct amdgpu_xcp_mgr
+ * rather than freed individually by kobject_put().
+ */
+ .release = NULL,
.sysfs_ops = &kobj_sysfs_ops
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
index ab14079d1c4222..0847134a139171 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
@@ -797,6 +797,11 @@ static const struct sysfs_ops xcp_cfg_res_sysfs_ops = {
};
static const struct kobj_type xcp_cfg_res_sysfs_ktype = {
+ /*
+ * Pre-existing: xcp_res is embedded in struct amdgpu_xcp_cfg
+ * rather than freed individually by kobject_put().
+ */
+ .release = NULL,
.sysfs_ops = &xcp_cfg_res_sysfs_ops,
.default_groups = xcp_cfg_res_sysfs_groups,
};
@@ -1061,6 +1066,11 @@ static const struct attribute_group amdgpu_xcp_attrs_group = {
};
static const struct kobj_type xcp_sysfs_ktype = {
+ /*
+ * Pre-existing: xcp is embedded in struct amdgpu_xcp_mgr
+ * rather than freed individually by kobject_put().
+ */
+ .release = NULL,
.sysfs_ops = &kobj_sysfs_ops,
};
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index 226f52626e849d..8e6136d52a50d0 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -512,7 +512,15 @@ static const struct sysfs_ops procfs_queue_ops = {
.show = kfd_procfs_queue_show,
};
+static void kfd_procfs_queue_release(struct kobject *kobj)
+{
+ struct queue *q = container_of(kobj, struct queue, kobj);
+
+ kfree(q);
+}
+
static const struct kobj_type procfs_queue_type = {
+ .release = kfd_procfs_queue_release,
.sysfs_ops = &procfs_queue_ops,
.default_groups = procfs_queue_groups,
};
@@ -552,7 +560,6 @@ int kfd_procfs_add_queue(struct queue *q)
if (ret < 0) {
pr_warn("Creating proc/<pid>/queues/%u failed",
q->properties.queue_id);
- kobject_put(&q->kobj);
return ret;
}
@@ -697,11 +704,10 @@ static void kfd_procfs_add_sysfs_files(struct kfd_process *p)
void kfd_procfs_del_queue(struct queue *q)
{
- if (!q || !q->process->kobj)
+ if (!q || !q->process || !q->process->kobj || !q->kobj.state_in_sysfs)
return;
kobject_del(&q->kobj);
- kobject_put(&q->kobj);
}
int kfd_process_create_wq(void)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
index ae3e7c54014a86..4666110aebe07c 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)
diff --git a/drivers/infiniband/hw/hfi1/sysfs.c b/drivers/infiniband/hw/hfi1/sysfs.c
index 372cfd13dc6160..5a1aca06b542b2 100644
--- a/drivers/infiniband/hw/hfi1/sysfs.c
+++ b/drivers/infiniband/hw/hfi1/sysfs.c
@@ -608,6 +608,11 @@ static const struct sysfs_ops sde_sysfs_ops = {
};
static struct kobj_type sde_ktype = {
+ /*
+ * Pre-existing: sdma_engine is embedded in dd->per_sdma array
+ * rather than freed by kobject_put().
+ */
+ .release = NULL,
.sysfs_ops = &sde_sysfs_ops,
};
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c b/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
index fdb63a8fb9974b..df0e48070c2ee9 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
@@ -245,6 +245,8 @@ static struct attribute *usnic_ib_qpn_default_attrs[] = {
ATTRIBUTE_GROUPS(usnic_ib_qpn_default);
static struct kobj_type usnic_ib_qpn_type = {
+ /* Pre-existing: usnic_ib_qp_grp is embedded in RDMA core-managed struct usnic_ib_qp_grp. */
+ .release = NULL,
.sysfs_ops = &usnic_ib_qpn_sysfs_ops,
.default_groups = usnic_ib_qpn_default_groups,
};
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index 6b567a74fc2cb2..2f530e8c675793 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -484,6 +484,11 @@ ATTRIBUTE_GROUPS(paths_subsys);
/* Specific kobject type for our PDC paths */
static const struct kobj_type ktype_pdcspath = {
+ /*
+ * Pre-existing: pdcspath_entry instances are static; lifetime
+ * is not controlled by kobject_put().
+ */
+ .release = NULL,
.sysfs_ops = &pdcspath_attr_ops,
.default_groups = paths_subsys_groups,
};
diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c
index e6b5efdf5dc9bc..d62411e4f5355d 100644
--- a/drivers/power/supply/ab8500_fg.c
+++ b/drivers/power/supply/ab8500_fg.c
@@ -2531,6 +2531,11 @@ static struct attribute *ab8500_fg_attrs[] = {
ATTRIBUTE_GROUPS(ab8500_fg);
static const struct kobj_type ab8500_fg_ktype = {
+ /*
+ * Pre-existing: fg_kobject is embedded in devm-allocated struct
+ * ab8500_fg; ab8500_fg_sysfs_exit() only calls kobject_del().
+ */
+ .release = NULL,
.sysfs_ops = &ab8500_fg_sysfs_ops,
.default_groups = ab8500_fg_groups,
};
diff --git a/drivers/s390/char/sclp_mem.c b/drivers/s390/char/sclp_mem.c
index 6df1926d4c62a1..2fb7271dce362f 100644
--- a/drivers/s390/char/sclp_mem.c
+++ b/drivers/s390/char/sclp_mem.c
@@ -305,6 +305,8 @@ static ssize_t sclp_memmap_on_memory_store(struct kobject *kobj, struct kobj_att
}
static const struct kobj_type ktype = {
+ /* Pre-existing: permanent firmware kobjects, never freed */
+ .release = NULL,
.sysfs_ops = &kobj_sysfs_ops,
};
diff --git a/drivers/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c
index 0cc2953d59a54b..da7a64c9505878 100644
--- a/drivers/soc/hisilicon/kunpeng_hccs.c
+++ b/drivers/soc/hisilicon/kunpeng_hccs.c
@@ -1038,6 +1038,13 @@ static struct attribute *hccs_port_default_attrs[] = {
ATTRIBUTE_GROUPS(hccs_port_default);
static const struct kobj_type hccs_port_type = {
+ /*
+ * Pre-existing: hccs_port_info is allocated via devm_kzalloc()
+ * rather than freed by kobject_put(). With
+ * CONFIG_DEBUG_KOBJECT_RELEASE the delayed kobject cleanup may run
+ * after devm frees it on unbind, a use-after-free.
+ */
+ .release = NULL,
.sysfs_ops = &hccs_comm_ops,
.default_groups = hccs_port_default_groups,
};
@@ -1110,6 +1117,13 @@ static struct attribute *hccs_die_default_attrs[] = {
ATTRIBUTE_GROUPS(hccs_die_default);
static const struct kobj_type hccs_die_type = {
+ /*
+ * Pre-existing: hccs_die_info is allocated via devm_kzalloc()
+ * rather than freed by kobject_put(). With
+ * CONFIG_DEBUG_KOBJECT_RELEASE the delayed kobject cleanup may run
+ * after devm frees it on unbind, a use-after-free.
+ */
+ .release = NULL,
.sysfs_ops = &hccs_comm_ops,
.default_groups = hccs_die_default_groups,
};
@@ -1213,6 +1227,13 @@ static struct attribute *hccs_chip_default_attrs[] = {
ATTRIBUTE_GROUPS(hccs_chip_default);
static const struct kobj_type hccs_chip_type = {
+ /*
+ * Pre-existing: hccs_chip_info is allocated via devm_kzalloc()
+ * rather than freed by kobject_put(). With
+ * CONFIG_DEBUG_KOBJECT_RELEASE the delayed kobject cleanup may run
+ * after devm frees it on unbind, a use-after-free.
+ */
+ .release = NULL,
.sysfs_ops = &hccs_comm_ops,
.default_groups = hccs_chip_default_groups,
};
diff --git a/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c b/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c
index ae937854403b12..452920a4e2a9a9 100644
--- a/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c
+++ b/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c
@@ -304,6 +304,13 @@ static const struct sysfs_ops display_sysfs_ops = {
};
static struct kobj_type display_ktype = {
+ /*
+ * Pre-existing: dssdev->kobj is embedded in struct omap_dss_device
+ * and zeroed in display_uninit_sysfs() right after kobject_put().
+ * With CONFIG_DEBUG_KOBJECT_RELEASE that memset() clobbers the
+ * pending delayed kobject cleanup.
+ */
+ .release = NULL,
.sysfs_ops = &display_sysfs_ops,
.default_groups = display_sysfs_groups,
};
diff --git a/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c b/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c
index 1b644be5fe2ed0..40ec750f431559 100644
--- a/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c
+++ b/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c
@@ -496,6 +496,11 @@ static const struct sysfs_ops manager_sysfs_ops = {
};
static struct kobj_type manager_ktype = {
+ /*
+ * Pre-existing: mgr->kobj is embedded in static managers[] and
+ * zeroed in dss_manager_kobj_uninit().
+ */
+ .release = NULL,
.sysfs_ops = &manager_sysfs_ops,
.default_groups = manager_sysfs_groups,
};
diff --git a/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c b/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c
index 1da4fb1c77b4a6..4d333031b18d6d 100644
--- a/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c
+++ b/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c
@@ -429,6 +429,11 @@ static const struct sysfs_ops overlay_sysfs_ops = {
};
static struct kobj_type overlay_ktype = {
+ /*
+ * Pre-existing: ovl->kobj is embedded in static overlays[];
+ * dss_overlay_kobj_uninit() drops the kobject ref.
+ */
+ .release = NULL,
.sysfs_ops = &overlay_sysfs_ops,
.default_groups = overlay_sysfs_groups,
};
diff --git a/drivers/xen/sys-hypervisor.c b/drivers/xen/sys-hypervisor.c
index 91923242a5ae71..0e8a2cd69fd69a 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,
};
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
index 74c2e77d1b553e..95b3bff0cb57aa 100644
--- a/fs/dlm/dlm_internal.h
+++ b/fs/dlm/dlm_internal.h
@@ -576,6 +576,7 @@ struct dlm_ls {
int ls_create_count; /* create/release refcount */
unsigned long ls_flags; /* LSFL_ */
struct kobject ls_kobj;
+ struct completion ls_kobj_done;
struct xarray ls_lkbxa;
rwlock_t ls_lkbxa_lock;
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index a9c98b4f378f3a..2dccd080a10f64 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -179,7 +179,15 @@ static const struct sysfs_ops dlm_attr_ops = {
.store = dlm_attr_store,
};
+static void dlm_ls_release(struct kobject *kobj)
+{
+ struct dlm_ls *ls = container_of(kobj, struct dlm_ls, ls_kobj);
+
+ complete(&ls->ls_kobj_done);
+}
+
static struct kobj_type dlm_ktype = {
+ .release = dlm_ls_release,
.default_groups = dlm_groups,
.sysfs_ops = &dlm_attr_ops,
};
@@ -355,6 +363,8 @@ static void free_lockspace(struct work_struct *work)
*/
rhashtable_free_and_destroy(&ls->ls_rsbtbl, rhash_free_rsb, NULL);
+ kobject_put(&ls->ls_kobj);
+ wait_for_completion(&ls->ls_kobj_done);
kfree(ls);
}
@@ -435,7 +445,10 @@ static int new_lockspace(const char *name, const char *cluster,
ls->ls_lvblen = lvblen;
atomic_set(&ls->ls_count, 0);
init_waitqueue_head(&ls->ls_count_wait);
+ init_completion(&ls->ls_kobj_done);
ls->ls_flags = 0;
+ ls->ls_kobj.kset = dlm_kset;
+ kobject_init(&ls->ls_kobj, &dlm_ktype);
if (ops && dlm_config.ci_recover_callbacks) {
ls->ls_ops = ops;
@@ -567,9 +580,7 @@ static int new_lockspace(const char *name, const char *cluster,
wait_event(ls->ls_recover_lock_wait,
test_bit(LSFL_RECOVER_LOCK, &ls->ls_flags));
- ls->ls_kobj.kset = dlm_kset;
- error = kobject_init_and_add(&ls->ls_kobj, &dlm_ktype, NULL,
- "%s", ls->ls_name);
+ error = kobject_add(&ls->ls_kobj, NULL, "%s", ls->ls_name);
if (error)
goto out_recoverd;
kobject_uevent(&ls->ls_kobj, KOBJ_ADD);
@@ -582,7 +593,7 @@ static int new_lockspace(const char *name, const char *cluster,
error = do_uevent(ls, 1, 0);
if (error < 0)
- goto out_recoverd;
+ goto out_kobj;
/* wait until recovery is successful or failed */
wait_for_completion(&ls->ls_recovery_done);
@@ -600,6 +611,8 @@ static int new_lockspace(const char *name, const char *cluster,
do_uevent(ls, 0, 0);
dlm_clear_members(ls);
kfree(ls->ls_node_array);
+ out_kobj:
+ kobject_del(&ls->ls_kobj);
out_recoverd:
dlm_recoverd_stop(ls);
out_callback:
@@ -615,6 +628,7 @@ static int new_lockspace(const char *name, const char *cluster,
rhashtable_destroy(&ls->ls_rsbtbl);
out_lsfree:
kobject_put(&ls->ls_kobj);
+ wait_for_completion(&ls->ls_kobj_done);
kfree(ls);
out:
module_put(THIS_MODULE);
@@ -740,6 +754,8 @@ static int release_lockspace(struct dlm_ls *ls, unsigned int release_option)
dlm_user_daemon_available())
do_uevent(ls, 0, (release_option == DLM_RELEASE_RECOVER));
+ kobject_del(&ls->ls_kobj);
+
dlm_recoverd_stop(ls);
/* clear the LSFL_RUNNING flag to fast up
@@ -759,8 +775,6 @@ static int release_lockspace(struct dlm_ls *ls, unsigned int release_option)
dlm_delete_debug_file(ls);
- kobject_put(&ls->ls_kobj);
-
xa_destroy(&ls->ls_recover_xa);
kfree(ls->ls_recover_buf);
diff --git a/fs/erofs/sysfs.c b/fs/erofs/sysfs.c
index dfcec9376cd54d..2ea6773cd98fdd 100644
--- a/fs/erofs/sysfs.c
+++ b/fs/erofs/sysfs.c
@@ -238,6 +238,11 @@ static const struct kobj_type erofs_sb_ktype = {
static const struct kobj_type erofs_ktype = {
.default_groups = erofs_groups,
.sysfs_ops = &erofs_attr_ops,
+ /*
+ * Pre-existing: erofs_root is a static struct kset; lifetime
+ * is not controlled by kobject_put().
+ */
+ .release = NULL,
};
static struct kset erofs_root = {
@@ -247,6 +252,11 @@ static struct kset erofs_root = {
static const struct kobj_type erofs_feat_ktype = {
.default_groups = erofs_feat_groups,
.sysfs_ops = &erofs_attr_ops,
+ /*
+ * Pre-existing: erofs_feat is a static struct kobject; lifetime
+ * is not controlled by kobject_put().
+ */
+ .release = NULL,
};
static struct kobject erofs_feat = {
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index 430356e500afd6..6e15695cb75f1c 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -1683,6 +1683,11 @@ static const struct kobj_type f2fs_sb_ktype = {
static const struct kobj_type f2fs_ktype = {
.sysfs_ops = &f2fs_attr_ops,
+ /*
+ * Pre-existing: f2fs_kset is a static struct kset; lifetime
+ * is not controlled by kobject_put().
+ */
+ .release = NULL,
};
static struct kset f2fs_kset = {
@@ -1697,6 +1702,11 @@ static const struct sysfs_ops f2fs_feat_attr_ops = {
static const struct kobj_type f2fs_feat_ktype = {
.default_groups = f2fs_feat_groups,
.sysfs_ops = &f2fs_feat_attr_ops,
+ /*
+ * Pre-existing: f2fs_feat is a static struct kobject; lifetime
+ * is not controlled by kobject_put().
+ */
+ .release = NULL,
};
static struct kobject f2fs_feat = {
@@ -1711,6 +1721,11 @@ static const struct sysfs_ops f2fs_tune_attr_ops = {
static const struct kobj_type f2fs_tune_ktype = {
.default_groups = f2fs_tune_groups,
.sysfs_ops = &f2fs_tune_attr_ops,
+ /*
+ * Pre-existing: f2fs_tune is a static struct kobject; lifetime
+ * is not controlled by kobject_put().
+ */
+ .release = NULL,
};
static struct kobject f2fs_tune = {
diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c
index 563881ddbf00c8..ff8a1cf51e72f7 100644
--- a/fs/ocfs2/cluster/masklog.c
+++ b/fs/ocfs2/cluster/masklog.c
@@ -147,6 +147,11 @@ static const struct sysfs_ops mlog_attr_ops = {
static struct kobj_type mlog_ktype = {
.default_groups = mlog_default_groups,
.sysfs_ops = &mlog_attr_ops,
+ /*
+ * Pre-existing: mlog_kset is a static struct kset; lifetime
+ * is not controlled by kobject_put().
+ */
+ .release = NULL,
};
static struct kset mlog_kset = {
diff --git a/fs/ubifs/sysfs.c b/fs/ubifs/sysfs.c
index dbf967dcf26e66..e20931e3a62f96 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);
}
diff --git a/include/linux/compiler_attributes.h b/include/linux/compiler_attributes.h
index 476c4c560d1743..b9c0b56dd22e79 100644
--- a/include/linux/compiler_attributes.h
+++ b/include/linux/compiler_attributes.h
@@ -322,6 +322,18 @@
*/
#define __pure __attribute__((__pure__))
+/*
+ * Optional: not supported by gcc
+ * Optional: only supported since clang >= 20.0
+ *
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#require-explicit-initialization
+ */
+#if __has_attribute(__require_explicit_initialization__)
+# define __must_init __attribute__((__require_explicit_initialization__))
+#else
+# define __must_init
+#endif
+
/*
* gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-section-function-attribute
* gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-section-variable-attribute
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 55e37a5d405ef7..8a133203088477 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -114,7 +114,7 @@ void kobject_get_ownership(const struct kobject *kobj, kuid_t *uid, kgid_t *gid)
char *kobject_get_path(const struct kobject *kobj, gfp_t flag);
struct kobj_type {
- void (*release)(struct kobject *kobj);
+ void (*release)(struct kobject *kobj) __must_init;
const struct sysfs_ops *sysfs_ops;
const struct attribute_group **default_groups;
const struct kobj_ns_type_operations *(*child_ns_type)(const struct kobject *kobj);
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index c9840f5219c2a9..5232f66d2b80f1 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -6860,6 +6860,7 @@ sub process {
"noreturn" => "__noreturn",
"packed" => "__packed",
"pure" => "__pure",
+ "require_explicit_initialization" => "__must_init",
"section" => "__section",
"used" => "__used",
"weak" => "__weak"
diff --git a/tools/lib/python/kdoc/xforms_lists.py b/tools/lib/python/kdoc/xforms_lists.py
index 320f977c5bac2c..3c744cbd2f34f7 100644
--- a/tools/lib/python/kdoc/xforms_lists.py
+++ b/tools/lib/python/kdoc/xforms_lists.py
@@ -36,6 +36,7 @@ class CTransforms:
(CMatch("CRYPTO_MINALIGN_ATTR"), ""),
(CMatch("__private"), ""),
(CMatch("__rcu"), ""),
+ (CMatch("__must_init"), ""),
(CMatch("____cacheline_aligned_in_smp"), ""),
(CMatch("____cacheline_aligned"), ""),
(CMatch("__cacheline_group_(?:begin|end)"), ""),
|
| 3/2 | 2026/10/28 06:19 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 14367 output: 29 thoughts: 2089 Thoughts: **Analysis of the `__must_init` Patch Series** Okay, let's break this down. We're looking at a patch series that's introducing `__must_init` to the `.release` member of `struct kobj_type`. This seems straightforward: the compiler now *requires* explicit initialization of `.release`, and the patch series is making sure that happens. The primary driver is likely clang >= 20. So, it's making existing code, which implicitly initialized this field, more explicit. Now, let's go file by file. Most of the changes are simply initializing `.release` to `NULL`. Nothing groundbreaking there, just making the code compliant. But some of these are interesting. * `arch/powerpc/kernel/secvar-sysfs.c`, `arch/sh/kernel/cpu/sh4/sq.c` and `drivers/xen/sys-hypervisor.c` are straightforward, explicitly assigning a release function. * `drivers/cpufreq/cpufreq_governor.c` is interesting, and the `.release = cpufreq_dbs_data_release` assignment across multiple files is showing that the code is more explicit now. * `drivers/gpu/drm/amd/amdkfd/kfd_process.c` and `kfd_queue.c` seem to have more substantive changes. The code has added and removed `kobject_put` calls, which suggests potential refactoring around the lifetime management of the `struct queue` and its associated `kobject`. Are there potential memory safety issues, or just cleanup? The changes in `fs/dlm/lockspace.c` are a bit more involved. The addition of `dlm_ls_release` and the use of `init_completion` and `wait_for_completion` suggest that releasing a lockspace might involve asynchronous operations. This needs further investigation. `fs/ubifs/sysfs.c` is another noteworthy change. It looks like the patch is converting from a static `kset` to a dynamically created one using `kset_create_and_add`. This could be important for resource management. And finally, `fs/erofs/sysfs.c`, `fs/f2fs/sysfs.c` and `fs/ocfs2/cluster/masklog.c` simply setting `.release = NULL`. Now, let's think about exploitability. Let's see: `fs/dlm` and `fs/ubifs` look like the most promising. DLM is a distributed lock manager. It has a `/dev/dlm-control` character device, meaning it can be interacted with from userspace. It's a clustering subsystem, so it could be complex. I should investigate how lockspaces are created and managed, and if errors in those methods can be exploited. UBIFS is a file system, which syzkaller supports for fuzzing. If UBIFS kobjects are mismanaged, that might be exploitable. `cpufreq` is also a possibility - mismanaging that could lead to vulnerabilities. Let's use our tools (`grepper`, `codesearch-dir-index`, `read-file`, `set-results`) and continue to explore those avenues. |
| 4/2 | 2026/10/28 06:20 | tool | grepper |
0mArgs:{
"Expression": "new_lockspace",
"PathPrefixes": [
"fs/dlm"
]
}Results: {
"Output": "fs/dlm/lockspace.c=347=static void free_lockspace(struct work_struct *work)\n--\nfs/dlm/lockspace.c-370-\nfs/dlm/lockspace.c:371:static int new_lockspace(const char *name, const char *cluster,\nfs/dlm/lockspace.c-372-\t\t\t uint32_t flags, int lvblen,\n--\nfs/dlm/lockspace.c-637-\nfs/dlm/lockspace.c:638:static int __dlm_new_lockspace(const char *name, const char *cluster,\nfs/dlm/lockspace.c-639-\t\t\t uint32_t flags, int lvblen,\n--\nfs/dlm/lockspace.c-651-\nfs/dlm/lockspace.c:652:\terror = new_lockspace(name, cluster, flags, lvblen, ops, ops_arg,\nfs/dlm/lockspace.c-653-\t\t\t ops_result, lockspace);\n--\nfs/dlm/lockspace.c-666-\nfs/dlm/lockspace.c:667:int dlm_new_lockspace(const char *name, const char *cluster, uint32_t flags,\nfs/dlm/lockspace.c-668-\t\t int lvblen, const struct dlm_lockspace_ops *ops,\n--\nfs/dlm/lockspace.c-671-{\nfs/dlm/lockspace.c:672:\treturn __dlm_new_lockspace(name, cluster, flags | DLM_LSFL_FS, lvblen,\nfs/dlm/lockspace.c-673-\t\t\t\t ops, ops_arg, ops_result, lockspace);\n--\nfs/dlm/lockspace.c=676=int dlm_new_user_lockspace(const char *name, const char *cluster,\n--\nfs/dlm/lockspace.c-684-\nfs/dlm/lockspace.c:685:\treturn __dlm_new_lockspace(name, cluster, flags, lvblen, ops,\nfs/dlm/lockspace.c-686-\t\t\t\t ops_arg, ops_result, lockspace);\n--\nfs/dlm/main.c=99=MODULE_LICENSE(\"GPL\");\nfs/dlm/main.c-100-\nfs/dlm/main.c:101:EXPORT_SYMBOL_GPL(dlm_new_lockspace);\nfs/dlm/main.c-102-EXPORT_SYMBOL_GPL(dlm_release_lockspace);\n--\nfs/dlm/recoverd.c=347=static void do_ls_recovery(struct dlm_ls *ls)\n--\nfs/dlm/recoverd.c-378-\nfs/dlm/recoverd.c:379:\t\t\t/* let new_lockspace() get aware of critical error */\nfs/dlm/recoverd.c-380-\t\t\tls-\u003els_recovery_result = error;\n--\nfs/dlm/user.c=469=static int check_version(struct dlm_write_request *req)\n--\nfs/dlm/user.c-501- * device_create_lockspace\nfs/dlm/user.c:502: * dlm_new_lockspace\nfs/dlm/user.c-503- *\n"
} |
| 5/2 | 2026/10/28 06:20 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 18069 output: 31 thoughts: 29 Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience, and written as a first-person summary: **Digging into the Distributed Lock Manager (DLM)** Alright, so I see a reference to the DLM and its user interface code at `fs/dlm/user.c`. My first instinct is, "Yes, let's dive into that!" I know this area inside and out. `fs/dlm/user.c` is the key for how userspace interacts with the DLM core, and any issues or potential optimizations there are going to be critical to overall performance and stability. I'll be looking for several key things immediately. I'll be checking: * **System Call Handlers:** The core of the user-space interface. I need to refresh myself on how the `dlm_*` system calls are structured, how they're validated, and how they dispatch to the DLM kernel code. Any inefficiencies in argument parsing, unnecessary copying, or incorrect error handling will jump out immediately. I want to see how these calls handle all the lock operations: locking, unlocking, status queries, etc. Are they efficient? Are any operations blocking unnecessarily? * **Security Context and Permissions:** This is a crucial area. How are permissions checked? Does the user-space code validate the caller's credentials properly before granting access to resources? Any holes here could lead to privilege escalation or, at a minimum, resource exhaustion vulnerabilities. I need to understand how the code protects against users circumventing locks they shouldn't have access to. * **Error Handling and Robustness:** I'll scrutinize the error handling. Does it gracefully handle error conditions, such as network failures, resource exhaustion, or invalid arguments from the user? Does it provide informative error messages to the user space? Proper error handling is paramount for debugging and for preventing userspace from getting wedged. Is there a back-off mechanism for error retries? Does it provide clear, actionable error codes? * **Memory Management:** User-space interaction frequently involves shared memory. I'll check how it manages shared memory regions. Are there potential race conditions in access to those shared regions? How does the code handle allocations and deallocations in the shared memory context? * **Concurrency:** User-space lock operations have to be thread-safe. I need to understand how concurrency is managed within the `user.c` file. Are mutexes used correctly? Are there any potential deadlocks or race conditions in the interaction with the underlying kernel lock structures? * **I/O Completion Handling:** How does the user-space code handle asynchronous lock requests? Does it use polling, signals, or some other mechanism to notify user-space of lock completion? Is this efficient, or is it a bottleneck? * **Resource Limits:** Are there resource limits or quotas imposed on user-space DLM operations (e.g., maximum number of locks a user can hold, maximum size of a lock request)? How are these limits enforced and what happens when they are exceeded? In short, I'm expecting this file to be the bridge between user expectations and kernel realities. Understanding the efficiency, security, and robustness of this bridge is paramount to understanding the DLM as a whole. Let's see what's there! |
| 6/2 | 2026/10/28 06:20 | tool | grepper |
0mArgs:{
"Expression": "device_create_lockspace",
"PathPrefixes": [
"fs/dlm"
]
}Results: {
"Output": "fs/dlm/user.c=377=int dlm_device_deregister(struct dlm_ls *ls)\n--\nfs/dlm/user.c-379-\t/* The device is not registered. This happens when the lockspace\nfs/dlm/user.c:380:\t was never used from userspace, or when device_create_lockspace()\nfs/dlm/user.c-381-\t calls dlm_release_lockspace() after the register fails. */\n--\nfs/dlm/user.c=390=static int device_user_purge(struct dlm_user_proc *proc,\n--\nfs/dlm/user.c-405-\nfs/dlm/user.c:406:static int device_create_lockspace(struct dlm_lspace_params *params)\nfs/dlm/user.c-407-{\n--\nfs/dlm/user.c=469=static int check_version(struct dlm_write_request *req)\n--\nfs/dlm/user.c-500- *\nfs/dlm/user.c:501: * device_create_lockspace\nfs/dlm/user.c-502- * dlm_new_lockspace\n--\nfs/dlm/user.c=511=static ssize_t device_write(struct file *file, const char __user *buf,\n--\nfs/dlm/user.c-623-\t\t}\nfs/dlm/user.c:624:\t\terror = device_create_lockspace(\u0026kbuf-\u003ei.lspace);\nfs/dlm/user.c-625-\t\tbreak;\n"
} |
| 7/2 | 2026/10/28 06:20 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 19259 output: 35 thoughts: 73 Thoughts: Here's my summary, as I see it: **Digging into the DLM User Interface** Okay, so I see `fs/dlm/user.c` has a `device_write` function. That's interesting, because it means userspace applications can directly interact with the Distributed Lock Manager. Specifically, they can open the DLM control device, which I'm guessing is `/dev/dlm-control`, and then use a `write` command to perform lockspace operations. This is key: creation and release are handled via a simple `write` call. I need to understand this better. My next step is to trace the initialization path. I'm going to look at either `dlm_user_init`, or search to see exactly what kind of device (misc or character) the DLM is registering to see what the driver is. Let's see how they actually set up this interface. This is going to be important to map out. |
| 8/2 | 2026/10/28 06:20 | tool | grepper |
0mArgs:{
"Expression": "misc_register|dlm_user_init",
"PathPrefixes": [
"fs/dlm"
]
}Results: {
"Output": "fs/dlm/main.c=27=static int __init init_dlm(void)\n--\nfs/dlm/main.c-46-\nfs/dlm/main.c:47:\terror = dlm_user_init();\nfs/dlm/main.c-48-\tif (error)\n--\nfs/dlm/plock.c=626=int dlm_plock_init(void)\n--\nfs/dlm/plock.c-629-\nfs/dlm/plock.c:630:\trv = misc_register(\u0026plock_dev_misc);\nfs/dlm/plock.c-631-\tif (rv)\nfs/dlm/plock.c:632:\t\tlog_print(\"dlm_plock_init: misc_register failed %d\", rv);\nfs/dlm/plock.c-633-\treturn rv;\n--\nfs/dlm/user.c=345=static int dlm_device_register(struct dlm_ls *ls, char *name)\n--\nfs/dlm/user.c-364-\nfs/dlm/user.c:365:\terror = misc_register(\u0026ls-\u003els_device);\nfs/dlm/user.c-366-\tif (error) {\n--\nfs/dlm/user.c=979=static struct miscdevice monitor_device = {\n--\nfs/dlm/user.c-985-\nfs/dlm/user.c:986:int __init dlm_user_init(void)\nfs/dlm/user.c-987-{\n--\nfs/dlm/user.c-991-\nfs/dlm/user.c:992:\terror = misc_register(\u0026ctl_device);\nfs/dlm/user.c-993-\tif (error) {\nfs/dlm/user.c:994:\t\tlog_print(\"misc_register failed for control device\");\nfs/dlm/user.c-995-\t\tgoto out;\n--\nfs/dlm/user.c-997-\nfs/dlm/user.c:998:\terror = misc_register(\u0026monitor_device);\nfs/dlm/user.c-999-\tif (error) {\nfs/dlm/user.c:1000:\t\tlog_print(\"misc_register failed for monitor device\");\nfs/dlm/user.c-1001-\t\tmisc_deregister(\u0026ctl_device);\n--\nfs/dlm/user.h=10=void dlm_user_add_ast(struct dlm_lkb *lkb, uint32_t flags, int mode,\nfs/dlm/user.h-11-\t\t int status, uint32_t sbflags);\nfs/dlm/user.h:12:int dlm_user_init(void);\nfs/dlm/user.h-13-void dlm_user_exit(void);\n"
} |
| 9/2 | 2026/10/28 06:20 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 20332 output: 37 thoughts: 87 Thoughts: Here's my understanding of the situation, presented from my perspective as an expert: **Investigating the DLM's Control Device Handling** Okay, so the DLM registers `ctl_device`, which, if I recall correctly, is implemented as a miscdevice. My immediate goal is to understand the lifecycle and interaction with this control device. To do that, I'll need to dig into the lockspace management code. I'll need to know what happens when a new lockspace is created (`new_lockspace`), when it's freed (`free_lockspace`), and specifically what occurs during a lockspace release (`release_lockspace`). Understanding this will give me a good handle on how the control device is used. I think a good starting point is `fs/dlm/lockspace.c`. I'm going to focus my initial investigation on specific sections of that file: lines 350-370 to get the basic flow, lines 560-635 to look at the resource allocation, and lines 740-780, to see how things are cleaned up during release. This should provide a solid overview of how the control device is used within this part of the system. |
| 10/2 | 2026/10/28 06:20 | tool | read-file |
0mArgs:{
"File": "fs/dlm/lockspace.c",
"FirstLine": 350,
"LineCount": 50
}Results: {
"Contents": " 350:\t\tstruct dlm_lkb *lkb;\n 351:\t\tunsigned long id;\n 352:\t\n 353:\t\t/*\n 354:\t\t * Free all lkb's in xa\n 355:\t\t */\n 356:\t\txa_for_each(\u0026ls-\u003els_lkbxa, id, lkb) {\n 357:\t\t\tlkb_idr_free(lkb);\n 358:\t\t}\n 359:\t\txa_destroy(\u0026ls-\u003els_lkbxa);\n 360:\t\n 361:\t\t/*\n 362:\t\t * Free all rsb's on rsbtbl\n 363:\t\t */\n 364:\t\trhashtable_free_and_destroy(\u0026ls-\u003els_rsbtbl, rhash_free_rsb, NULL);\n 365:\t\n 366:\t\tkobject_put(\u0026ls-\u003els_kobj);\n 367:\t\twait_for_completion(\u0026ls-\u003els_kobj_done);\n 368:\t\tkfree(ls);\n 369:\t}\n 370:\t\n 371:\tstatic int new_lockspace(const char *name, const char *cluster,\n 372:\t\t\t\t uint32_t flags, int lvblen,\n 373:\t\t\t\t const struct dlm_lockspace_ops *ops, void *ops_arg,\n 374:\t\t\t\t int *ops_result, dlm_lockspace_t **lockspace)\n 375:\t{\n 376:\t\tstruct dlm_ls *ls;\n 377:\t\tint namelen = strlen(name);\n 378:\t\tint error;\n 379:\t\n 380:\t\tif (namelen \u003e DLM_LOCKSPACE_LEN || namelen == 0)\n 381:\t\t\treturn -EINVAL;\n 382:\t\n 383:\t\tif (lvblen % 8)\n 384:\t\t\treturn -EINVAL;\n 385:\t\n 386:\t\tif (!try_module_get(THIS_MODULE))\n 387:\t\t\treturn -EINVAL;\n 388:\t\n 389:\t\tif (!dlm_user_daemon_available()) {\n 390:\t\t\tlog_print(\"dlm user daemon not available\");\n 391:\t\t\terror = -EUNATCH;\n 392:\t\t\tgoto out;\n 393:\t\t}\n 394:\t\n 395:\t\tif (ops \u0026\u0026 ops_result) {\n 396:\t\t \tif (!dlm_config.ci_recover_callbacks)\n 397:\t\t\t\t*ops_result = -EOPNOTSUPP;\n 398:\t\t\telse\n 399:\t\t\t\t*ops_result = 0;\n"
} |
| 11/2 | 2026/10/28 06:20 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 21440 output: 38 thoughts: 1091 Thoughts: **Analyzing the DLM Lockspace Kobject Lifetime Management** Okay, let's break down these DLM changes. The initial code was problematic. It appears the `dlm_ktype` didn't have a `.release` callback, meaning `kobject_put(&ls->ls_kobj)` did nothing to free the associated `struct dlm_ls` which, in turn, led to a `kfree(ls)` being called without proper cleanup. A clear violation of kobject lifetime rules, particularly considering that sysfs files could be opened, creating a reference to `ls->ls_kobj`. This would trigger clang warnings with `__must_init` and kobject. The patch introduced `dlm_ls_release` function, which utilizes the `container_of` macro to retrieve the `struct dlm_ls` from the `kobject` and completes `ls->ls_kobj_done`. The `dlm_ktype` struct was updated to include this new `dlm_ls_release` function as its `.release` callback. This is the first crucial fix. Now, `kobject_put` has a mechanism to free the memory. In `new_lockspace`, the code now initializes a completion (`ls->ls_kobj_done`) and the kobject using `kobject_init` followed by `kobject_add`. Crucially, error handling was added. If `kobject_add` fails, the code jumps to `out_kobj` where `kobject_del` is called to unregister the kobject and cleanup any remaining references. The code now ensures `kobject_put` is called *after* `kobject_add` (and only if it succeeds) and, critically, `wait_for_completion(&ls->ls_kobj_done)` is called before the `kfree(ls)`. This is key. In `release_lockspace`, `kobject_del` is called before the `kobject_put` to decrement the reference count of the kobject and initiate the release process. In `free_lockspace` is where it all comes together! The new patch changes this to `kobject_put(&ls->ls_kobj); wait_for_completion(&ls->ls_kobj_done); kfree(ls);`. This is *much* better. The critical point here is that `kobject_put` decrements the reference count and calls `dlm_ls_release` *eventually*, which completes `ls->ls_kobj_done`. Then, `wait_for_completion` blocks until all references to the kobject are gone and the `dlm_ls_release` function finishes. THEN, and only then, the memory is freed by `kfree(ls)`. This is a robust solution to a very tricky problem. By ensuring the `dlm_ls_release` callback is invoked and completion waited for, the code guarantees that the `struct dlm_ls` isn't freed prematurely, even if someone is holding a sysfs file open. The kobject's lifetime is now managed correctly, addressing the potential race conditions and memory leaks. The error handling in `new_lockspace` ensures that even if `kobject_add` fails, the system can gracefully recover and release resources. A solid and much needed improvement! |
| 12/2 | 2026/10/28 06:20 | tool | read-file |
0mArgs:{
"File": "fs/dlm/lockspace.c",
"FirstLine": 440,
"LineCount": 100
}Results: {
"Contents": " 440:\t\tls = kzalloc_obj(*ls, GFP_NOFS);\n 441:\t\tif (!ls)\n 442:\t\t\tgoto out;\n 443:\t\tmemcpy(ls-\u003els_name, name, namelen);\n 444:\t\tls-\u003els_namelen = namelen;\n 445:\t\tls-\u003els_lvblen = lvblen;\n 446:\t\tatomic_set(\u0026ls-\u003els_count, 0);\n 447:\t\tinit_waitqueue_head(\u0026ls-\u003els_count_wait);\n 448:\t\tinit_completion(\u0026ls-\u003els_kobj_done);\n 449:\t\tls-\u003els_flags = 0;\n 450:\t\tls-\u003els_kobj.kset = dlm_kset;\n 451:\t\tkobject_init(\u0026ls-\u003els_kobj, \u0026dlm_ktype);\n 452:\t\n 453:\t\tif (ops \u0026\u0026 dlm_config.ci_recover_callbacks) {\n 454:\t\t\tls-\u003els_ops = ops;\n 455:\t\t\tls-\u003els_ops_arg = ops_arg;\n 456:\t\t}\n 457:\t\n 458:\t\tif (flags \u0026 DLM_LSFL_SOFTIRQ)\n 459:\t\t\tset_bit(LSFL_SOFTIRQ, \u0026ls-\u003els_flags);\n 460:\t\n 461:\t\t/* ls_exflags are forced to match among nodes, and we don't\n 462:\t\t * need to require all nodes to have some flags set\n 463:\t\t */\n 464:\t\tls-\u003els_exflags = (flags \u0026 ~(DLM_LSFL_FS | DLM_LSFL_NEWEXCL |\n 465:\t\t\t\t\t DLM_LSFL_SOFTIRQ));\n 466:\t\n 467:\t\tINIT_LIST_HEAD(\u0026ls-\u003els_slow_inactive);\n 468:\t\tINIT_LIST_HEAD(\u0026ls-\u003els_slow_active);\n 469:\t\trwlock_init(\u0026ls-\u003els_rsbtbl_lock);\n 470:\t\n 471:\t\terror = rhashtable_init(\u0026ls-\u003els_rsbtbl, \u0026dlm_rhash_rsb_params);\n 472:\t\tif (error)\n 473:\t\t\tgoto out_lsfree;\n 474:\t\n 475:\t\txa_init_flags(\u0026ls-\u003els_lkbxa, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_BH);\n 476:\t\trwlock_init(\u0026ls-\u003els_lkbxa_lock);\n 477:\t\n 478:\t\tINIT_LIST_HEAD(\u0026ls-\u003els_waiters);\n 479:\t\tspin_lock_init(\u0026ls-\u003els_waiters_lock);\n 480:\t\tINIT_LIST_HEAD(\u0026ls-\u003els_orphans);\n 481:\t\tspin_lock_init(\u0026ls-\u003els_orphans_lock);\n 482:\t\n 483:\t\tINIT_LIST_HEAD(\u0026ls-\u003els_nodes);\n 484:\t\tINIT_LIST_HEAD(\u0026ls-\u003els_nodes_gone);\n 485:\t\tls-\u003els_num_nodes = 0;\n 486:\t\tls-\u003els_low_nodeid = 0;\n 487:\t\tls-\u003els_total_weight = 0;\n 488:\t\tls-\u003els_node_array = NULL;\n 489:\t\n 490:\t\tmemset(\u0026ls-\u003els_local_rsb, 0, sizeof(struct dlm_rsb));\n 491:\t\tls-\u003els_local_rsb.res_ls = ls;\n 492:\t\n 493:\t\tls-\u003els_debug_rsb_dentry = NULL;\n 494:\t\tls-\u003els_debug_waiters_dentry = NULL;\n 495:\t\n 496:\t\tinit_waitqueue_head(\u0026ls-\u003els_uevent_wait);\n 497:\t\tls-\u003els_uevent_result = 0;\n 498:\t\tinit_completion(\u0026ls-\u003els_recovery_done);\n 499:\t\tls-\u003els_recovery_result = -1;\n 500:\t\n 501:\t\tspin_lock_init(\u0026ls-\u003els_cb_lock);\n 502:\t\tINIT_LIST_HEAD(\u0026ls-\u003els_cb_delay);\n 503:\t\n 504:\t\tINIT_WORK(\u0026ls-\u003els_free_work, free_lockspace);\n 505:\t\n 506:\t\tls-\u003els_recoverd_task = NULL;\n 507:\t\tmutex_init(\u0026ls-\u003els_recoverd_active);\n 508:\t\tspin_lock_init(\u0026ls-\u003els_recover_lock);\n 509:\t\tspin_lock_init(\u0026ls-\u003els_rcom_spin);\n 510:\t\tget_random_bytes(\u0026ls-\u003els_rcom_seq, sizeof(uint64_t));\n 511:\t\tls-\u003els_recover_status = 0;\n 512:\t\tls-\u003els_recover_seq = get_random_u64();\n 513:\t\tls-\u003els_recover_args = NULL;\n 514:\t\tinit_rwsem(\u0026ls-\u003els_in_recovery);\n 515:\t\trwlock_init(\u0026ls-\u003els_recv_active);\n 516:\t\tINIT_LIST_HEAD(\u0026ls-\u003els_requestqueue);\n 517:\t\trwlock_init(\u0026ls-\u003els_requestqueue_lock);\n 518:\t\tspin_lock_init(\u0026ls-\u003els_clear_proc_locks);\n 519:\t\n 520:\t\t/* Due backwards compatibility with 3.1 we need to use maximum\n 521:\t\t * possible dlm message size to be sure the message will fit and\n 522:\t\t * not having out of bounds issues. However on sending side 3.2\n 523:\t\t * might send less.\n 524:\t\t */\n 525:\t\tls-\u003els_recover_buf = kmalloc(DLM_MAX_SOCKET_BUFSIZE, GFP_NOFS);\n 526:\t\tif (!ls-\u003els_recover_buf) {\n 527:\t\t\terror = -ENOMEM;\n 528:\t\t\tgoto out_lkbxa;\n 529:\t\t}\n 530:\t\n 531:\t\tls-\u003els_slot = 0;\n 532:\t\tls-\u003els_num_slots = 0;\n 533:\t\tls-\u003els_slots_size = 0;\n 534:\t\tls-\u003els_slots = NULL;\n 535:\t\n 536:\t\tINIT_LIST_HEAD(\u0026ls-\u003els_recover_list);\n 537:\t\tspin_lock_init(\u0026ls-\u003els_recover_list_lock);\n 538:\t\txa_init_flags(\u0026ls-\u003els_recover_xa, XA_FLAGS_ALLOC | XA_FLAGS_LOCK_BH);\n 539:\t\tspin_lock_init(\u0026ls-\u003els_recover_xa_lock);\n"
} |
| 13/2 | 2026/10/28 06:20 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 25091 output: 37 thoughts: 27 Thoughts: Okay, here's my attempt at summarizing the thought process, as requested, geared toward an expert audience, and written in the first person: **Diving into `fs/dlm/lockspace.c` - Lines 540-640** Right, let's get down to brass tacks. I need to zero in on a specific chunk of code within the DLM, and that means jumping straight to the heart of the matter. I'm focusing my attention on `fs/dlm/lockspace.c`, and more precisely, lines 540 through 640. That range likely encapsulates a specific function or logic block that's relevant to the issue I'm currently wrestling with – it could be related to lockspace creation, deletion, or perhaps something more granular like managing the state transitions of a lock request within the space. I'm expecting to see operations related to either the allocation or deallocation of resources; it's also highly probable that synchronization primitives such as mutexes or spinlocks will be in play there, given the nature of the DLM's work. It could even be some form of an optimization like an attempt to collapse multiple operations into one atomic operation, or it could be a simple check and log of the state of the DLM lockspace. I'm anticipating some critical logic is contained within that code block. I'll need to carefully dissect each statement to understand the flow control and data dependencies, and to look for potential concurrency issues or race conditions. Let's see what we've got. |
| 14/2 | 2026/10/28 06:21 | tool | read-file |
0mArgs:{
"File": "fs/dlm/lockspace.c",
"FirstLine": 540,
"LineCount": 90
}Results: {
"Contents": " 540:\t\tls-\u003els_recover_list_count = 0;\n 541:\t\tinit_waitqueue_head(\u0026ls-\u003els_wait_general);\n 542:\t\tINIT_LIST_HEAD(\u0026ls-\u003els_masters_list);\n 543:\t\trwlock_init(\u0026ls-\u003els_masters_lock);\n 544:\t\tINIT_LIST_HEAD(\u0026ls-\u003els_dir_dump_list);\n 545:\t\trwlock_init(\u0026ls-\u003els_dir_dump_lock);\n 546:\t\n 547:\t\tINIT_LIST_HEAD(\u0026ls-\u003els_scan_list);\n 548:\t\tspin_lock_init(\u0026ls-\u003els_scan_lock);\n 549:\t\ttimer_setup(\u0026ls-\u003els_scan_timer, dlm_rsb_scan, TIMER_DEFERRABLE);\n 550:\t\n 551:\t\tspin_lock_bh(\u0026lslist_lock);\n 552:\t\tls-\u003els_create_count = 1;\n 553:\t\tlist_add(\u0026ls-\u003els_list, \u0026lslist);\n 554:\t\tspin_unlock_bh(\u0026lslist_lock);\n 555:\t\n 556:\t\tif (flags \u0026 DLM_LSFL_FS)\n 557:\t\t\tset_bit(LSFL_FS, \u0026ls-\u003els_flags);\n 558:\t\n 559:\t\terror = dlm_callback_start(ls);\n 560:\t\tif (error) {\n 561:\t\t\tlog_error(ls, \"can't start dlm_callback %d\", error);\n 562:\t\t\tgoto out_delist;\n 563:\t\t}\n 564:\t\n 565:\t\tinit_waitqueue_head(\u0026ls-\u003els_recover_lock_wait);\n 566:\t\n 567:\t\t/*\n 568:\t\t * Once started, dlm_recoverd first looks for ls in lslist, then\n 569:\t\t * initializes ls_in_recovery as locked in \"down\" mode. We need\n 570:\t\t * to wait for the wakeup from dlm_recoverd because in_recovery\n 571:\t\t * has to start out in down mode.\n 572:\t\t */\n 573:\t\n 574:\t\terror = dlm_recoverd_start(ls);\n 575:\t\tif (error) {\n 576:\t\t\tlog_error(ls, \"can't start dlm_recoverd %d\", error);\n 577:\t\t\tgoto out_callback;\n 578:\t\t}\n 579:\t\n 580:\t\twait_event(ls-\u003els_recover_lock_wait,\n 581:\t\t\t test_bit(LSFL_RECOVER_LOCK, \u0026ls-\u003els_flags));\n 582:\t\n 583:\t\terror = kobject_add(\u0026ls-\u003els_kobj, NULL, \"%s\", ls-\u003els_name);\n 584:\t\tif (error)\n 585:\t\t\tgoto out_recoverd;\n 586:\t\tkobject_uevent(\u0026ls-\u003els_kobj, KOBJ_ADD);\n 587:\t\n 588:\t\t/* This uevent triggers dlm_controld in userspace to add us to the\n 589:\t\t group of nodes that are members of this lockspace (managed by the\n 590:\t\t cluster infrastructure.) Once it's done that, it tells us who the\n 591:\t\t current lockspace members are (via configfs) and then tells the\n 592:\t\t lockspace to start running (via sysfs) in dlm_ls_start(). */\n 593:\t\n 594:\t\terror = do_uevent(ls, 1, 0);\n 595:\t\tif (error \u003c 0)\n 596:\t\t\tgoto out_kobj;\n 597:\t\n 598:\t\t/* wait until recovery is successful or failed */\n 599:\t\twait_for_completion(\u0026ls-\u003els_recovery_done);\n 600:\t\terror = ls-\u003els_recovery_result;\n 601:\t\tif (error)\n 602:\t\t\tgoto out_members;\n 603:\t\n 604:\t\tdlm_create_debug_file(ls);\n 605:\t\n 606:\t\tlog_rinfo(ls, \"join complete\");\n 607:\t\t*lockspace = ls;\n 608:\t\treturn 0;\n 609:\t\n 610:\t out_members:\n 611:\t\tdo_uevent(ls, 0, 0);\n 612:\t\tdlm_clear_members(ls);\n 613:\t\tkfree(ls-\u003els_node_array);\n 614:\t out_kobj:\n 615:\t\tkobject_del(\u0026ls-\u003els_kobj);\n 616:\t out_recoverd:\n 617:\t\tdlm_recoverd_stop(ls);\n 618:\t out_callback:\n 619:\t\tdlm_callback_stop(ls);\n 620:\t out_delist:\n 621:\t\tspin_lock_bh(\u0026lslist_lock);\n 622:\t\tlist_del(\u0026ls-\u003els_list);\n 623:\t\tspin_unlock_bh(\u0026lslist_lock);\n 624:\t\txa_destroy(\u0026ls-\u003els_recover_xa);\n 625:\t\tkfree(ls-\u003els_recover_buf);\n 626:\t out_lkbxa:\n 627:\t\txa_destroy(\u0026ls-\u003els_lkbxa);\n 628:\t\trhashtable_destroy(\u0026ls-\u003els_rsbtbl);\n 629:\t out_lsfree:\n"
} |
| 15/2 | 2026/10/28 06:21 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 26962 output: 30 thoughts: 6457 Thoughts: **Analysis of Kernel Patch Series: WorthFuzzing Evaluation** Alright, let's break this down. My initial scan flagged a few areas for closer inspection within this patch series, focusing on determining whether the changes warrant fuzzing efforts. My primary concern is reachability, as per the established guidelines: modifications to code that is accessible in standard virtualized environments are key. First, I examined `fs/dlm/lockspace.c` and `fs/dlm/dlm_internal.h`. The changes here are significant. It looks like the patch introduces a new completion (`ls_kobj_done`), a `release` function (`dlm_ls_release`) for the kobject type, and fundamentally alters the lifecycle management of the `struct dlm_ls` kobject. The sequence of `kobject_init`, `kobject_add`, `kobject_del`, and `kobject_put` calls, along with the added `wait_for_completion`, raises red flags. The potential for synchronization issues, deadlocks, or reference counting errors within the context of sysfs interactions and workqueue execution in `free_lockspace` is concerning. Since DLM is a core part of the kernel and is reachable via the `/dev/dlm-control` device and DLM APIs, this is a definite "worth fuzzing" candidate. Next up is `fs/ubifs/sysfs.c`. Here, the patch transforms the static `ubifs_kset` into a dynamically allocated structure. While this seems like a refactoring, UBIFS is directly reachable through mounting UBI volumes. The change could have a ripple effect on the way kobjects are managed within UBIFS. The dynamic allocation and registration/deregistration also necessitates checking that this does not introduce new issues with the kobject lifecycle. This is also a "worth fuzzing" candidate. The third area involves `drivers/cpufreq/cpufreq_governor.c`, `cpufreq_ondemand.c`, and `cpufreq_conservative.c`. These patches refactor the assignment of the `.release` function within the kobj_type for CPUFreq governors. Because CPUFreq governors are directly accessible via sysfs interface at `/sys/devices/system/cpu/cpu*/cpufreq/scaling_governor`, even a seemingly minor modification that might impact how the kernel handles resource management is something I must consider as a "worth fuzzing". In short, there have been a few areas changed that impact code that is reachable, therefore `WorthFuzzing` is definitively `true`. I now need to dive into the Kconfig options for DLM, UBIFS, and CPUFreq to define the best configurations for testing. I also need to make a list of symbols for `FocusSymbols` and define the best configs for `EnableConfigs`. |
| 16/2 | 2026/10/28 06:21 | tool | grepper |
0mArgs:{
"Expression": "config DLM\\b",
"PathPrefixes": [
"fs/dlm"
]
}Results: {
"Output": "fs/dlm/Kconfig-1-# SPDX-License-Identifier: GPL-2.0-only\nfs/dlm/Kconfig:2:menuconfig DLM\nfs/dlm/Kconfig-3-\ttristate \"Distributed Lock Manager (DLM)\"\n"
} |
| 17/2 | 2026/10/28 06:21 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 34121 output: 33 thoughts: 13 Thoughts: Okay, let's dive into `fs/dlm/Kconfig`. I need to get a clear picture of how this Distributed Lock Manager (DLM) is configured within the file system. **Diving into the DLM Configuration: Kconfig** Right, so, I'm going through the Kconfig file for the DLM. My primary focus is understanding the configurable options and dependencies. I'm looking for the core elements: what features can be enabled or disabled, and what other kernel components are required for the DLM to function correctly. I expect to see things like: * **Core DLM Functionality:** Options related to enabling/disabling the DLM itself, perhaps different implementations or variations. * **Protocol Configuration:** Settings related to the underlying communication protocols that the DLM uses. Likely something about the transport layer. * **Resource Management:** Settings dealing with resource limits, lock tables, memory allocation related to the locking subsystem. * **Clustering Support:** Any options that relate to integrating the DLM with a broader clustering environment. * **Debug Options:** Maybe some compile-time flags for enabling verbose logging or specialized debugging features. * **Dependencies:** I'm keen to see which kernel subsystems are *required* and which are *optional* for the DLM to function. Things like network support, certain file systems, or other infrastructure bits. I'll need to figure out what the minimal requirements are and how much flexibility we have. Basically, I want to form a complete mental model of all the things a system administrator would need to consider when enabling, configuring, and deploying this DLM, and how it interplays with the rest of the file system. I anticipate that this Kconfig file will be the key to it all. Let's see what's in there. |
| 18/2 | 2026/10/28 06:22 | tool | read-file |
0mArgs:{
"File": "fs/dlm/Kconfig",
"FirstLine": 1,
"LineCount": 40
}Results: {
"Contents": " 1:\t# SPDX-License-Identifier: GPL-2.0-only\n 2:\tmenuconfig DLM\n 3:\t\ttristate \"Distributed Lock Manager (DLM)\"\n 4:\t\tdepends on INET\n 5:\t\tdepends on SYSFS \u0026\u0026 CONFIGFS_FS\n 6:\t\thelp\n 7:\t\tA general purpose distributed lock manager for kernel or userspace\n 8:\t\tapplications.\n 9:\t\n 10:\tconfig DLM_DEBUG\n 11:\t\tbool \"DLM debugging\"\n 12:\t\tdepends on DLM\n 13:\t\thelp\n 14:\t\tUnder the debugfs mount point, the name of each lockspace will\n 15:\t\tappear as a file in the \"dlm\" directory. The output is the\n 16:\t\tlist of resource and locks the local node knows about.\n"
} |
| 19/2 | 2026/10/28 06:22 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 34764 output: 32 thoughts: 13 Thoughts: Here's a summary of my thought process, as requested: **Diving into the UBIFS Configuration** Okay, time to get started. My immediate instinct is to look at the UBIFS configuration file. Specifically, I'm thinking, "Let's check `fs/ubifs/Kconfig`." That's the logical starting point. The Kconfig file is where I'll find all the configuration options related to UBIFS. It's the central hub for understanding what features are available, how they're enabled, what dependencies exist, and what the default settings are. This is where I'll begin to get a clear picture. |
| 20/2 | 2026/10/28 06:22 | tool | grepper |
0mArgs:{
"Expression": "config UBIFS_FS\\b",
"PathPrefixes": [
"fs/ubifs"
]
}Results: {
"Output": "fs/ubifs/Kconfig-1-# SPDX-License-Identifier: GPL-2.0-only\nfs/ubifs/Kconfig:2:config UBIFS_FS\nfs/ubifs/Kconfig-3-\ttristate \"UBIFS file system support\"\n"
} |
| 21/2 | 2026/10/28 06:22 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 35020 output: 33 thoughts: 13 Thoughts: Okay, here's my interpretation of that thought process, tailored for an expert audience, and written in the first person: **Delving into UBIFS Configuration** Alright, time to dive into the heart of the matter. My thought process here is pretty straightforward: I need to understand the configuration options for UBIFS. Specifically, I'm heading straight for the `fs/ubifs/Kconfig` file. This is the central repository for the compile-time settings related to the UBIFS filesystem within the kernel. I'm expecting to find the standard `config` directives, probably grouped logically, defining all the tunable features, feature flags, and defaults. I'll be looking for things like the block size options, compression algorithms (LZO, ZLIB, LZ4, etc.), wear-leveling strategies, journaling parameters, any debugging features exposed, and perhaps options for handling different NAND flash configurations. I also anticipate finding dependencies between these configurations, such as how compression choices relate to memory usage or performance tradeoffs. I'm especially interested in whether or not there are any new and interesting features or new configuration options. I'll mentally map the available choices to the potential performance implications. I might also be looking at how UBIFS is integrated in other kernel configurations, for instance, related to its use with UBIO. Ultimately, the goal is to get a solid grasp of what's configurable, how those settings impact the filesystem's behavior, and how best to optimize a UBIFS deployment for a given use case. Let's get to it. |
| 22/2 | 2026/10/28 06:22 | tool | read-file |
0mArgs:{
"File": "fs/ubifs/Kconfig",
"FirstLine": 1,
"LineCount": 25
}Results: {
"Contents": " 1:\t# SPDX-License-Identifier: GPL-2.0-only\n 2:\tconfig UBIFS_FS\n 3:\t\ttristate \"UBIFS file system support\"\n 4:\t\tselect CRC16\n 5:\t\tselect CRC32\n 6:\t\tselect CRYPTO if UBIFS_FS_ADVANCED_COMPR\n 7:\t\tselect CRYPTO if UBIFS_FS_LZO\n 8:\t\tselect CRYPTO if UBIFS_FS_ZLIB\n 9:\t\tselect CRYPTO if UBIFS_FS_ZSTD\n 10:\t\tselect CRYPTO_LZO if UBIFS_FS_LZO\n 11:\t\tselect CRYPTO_DEFLATE if UBIFS_FS_ZLIB\n 12:\t\tselect CRYPTO_ZSTD if UBIFS_FS_ZSTD\n 13:\t\tselect CRYPTO_HASH_INFO\n 14:\t\tselect UBIFS_FS_XATTR if FS_ENCRYPTION\n 15:\t\tselect FS_ENCRYPTION_ALGS if FS_ENCRYPTION\n 16:\t\tdepends on MTD_UBI\n 17:\t\thelp\n 18:\t\t UBIFS is a file system for flash devices which works on top of UBI.\n 19:\t\n 20:\tif UBIFS_FS\n 21:\t\n 22:\tconfig UBIFS_FS_ADVANCED_COMPR\n 23:\t\tbool \"Advanced compression options\"\n 24:\t\thelp\n 25:\t\t This option allows to explicitly choose which compressions, if any,\n"
} |
| 23/2 | 2026/10/28 06:22 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 35766 output: 47 thoughts: 19 Thoughts: Here's my take on those thoughts: **Analyzing the CPUFreq Governor Configuration** Okay, so I need to get a handle on how CPU frequency scaling is configured within this system. My first thought is to dig into the `drivers/cpufreq/Kconfig` file. That's usually the go-to spot for the core configuration options related to CPU frequency governors. I'm expecting to find the key settings there – the ones that control which governors are built, which are enabled by default, and how the user might customize them. I know I can find a lot of information on the options here to see what is possible. From there, I can probably determine the default behavior and any constraints. This will be the starting point to understand the available options. |
| 24/2 | 2026/10/28 06:22 | tool | grepper |
0mArgs:{
"Expression": "CPU_FREQ_GOV_ONDEMAND|CPU_FREQ_GOV_CONSERVATIVE",
"PathPrefixes": [
"drivers/cpufreq"
]
}Results: {
"Output": "drivers/cpufreq/Kconfig=72=config CPU_FREQ_DEFAULT_GOV_ONDEMAND\n--\ndrivers/cpufreq/Kconfig-74-\tdepends on !(X86_INTEL_PSTATE \u0026\u0026 SMP)\ndrivers/cpufreq/Kconfig:75:\tselect CPU_FREQ_GOV_ONDEMAND\ndrivers/cpufreq/Kconfig-76-\tselect CPU_FREQ_GOV_PERFORMANCE\n--\ndrivers/cpufreq/Kconfig=85=config CPU_FREQ_DEFAULT_GOV_CONSERVATIVE\n--\ndrivers/cpufreq/Kconfig-87-\tdepends on !(X86_INTEL_PSTATE \u0026\u0026 SMP)\ndrivers/cpufreq/Kconfig:88:\tselect CPU_FREQ_GOV_CONSERVATIVE\ndrivers/cpufreq/Kconfig-89-\tselect CPU_FREQ_GOV_PERFORMANCE\n--\ndrivers/cpufreq/Kconfig=132=config CPU_FREQ_GOV_USERSPACE\n--\ndrivers/cpufreq/Kconfig-144-\ndrivers/cpufreq/Kconfig:145:config CPU_FREQ_GOV_ONDEMAND\ndrivers/cpufreq/Kconfig-146-\ttristate \"'ondemand' cpufreq policy governor\"\n--\ndrivers/cpufreq/Kconfig-163-\ndrivers/cpufreq/Kconfig:164:config CPU_FREQ_GOV_CONSERVATIVE\ndrivers/cpufreq/Kconfig-165-\ttristate \"'conservative' cpufreq governor\"\n--\ndrivers/cpufreq/Kconfig.x86=156=config X86_AMD_FREQ_SENSITIVITY\ndrivers/cpufreq/Kconfig.x86-157-\ttristate \"AMD frequency sensitivity feedback powersave bias\"\ndrivers/cpufreq/Kconfig.x86:158:\tdepends on CPU_FREQ_GOV_ONDEMAND \u0026\u0026 X86_ACPI_CPUFREQ \u0026\u0026 CPU_SUP_AMD\ndrivers/cpufreq/Kconfig.x86-159-\thelp\n--\ndrivers/cpufreq/Makefile=11=obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE)\t+= cpufreq_userspace.o\ndrivers/cpufreq/Makefile:12:obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND)\t+= cpufreq_ondemand.o\ndrivers/cpufreq/Makefile:13:obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE)\t+= cpufreq_conservative.o\ndrivers/cpufreq/Makefile-14-obj-$(CONFIG_CPU_FREQ_GOV_COMMON)\t\t+= cpufreq_governor.o\n--\ndrivers/cpufreq/cpufreq_conservative.c=319=static struct dbs_governor cs_governor = {\n--\ndrivers/cpufreq/cpufreq_conservative.c-333-\ndrivers/cpufreq/cpufreq_conservative.c:334:#define CPU_FREQ_GOV_CONSERVATIVE\t(cs_governor.gov)\ndrivers/cpufreq/cpufreq_conservative.c-335-\n--\ndrivers/cpufreq/cpufreq_conservative.c=343=struct cpufreq_governor *cpufreq_default_governor(void)\ndrivers/cpufreq/cpufreq_conservative.c-344-{\ndrivers/cpufreq/cpufreq_conservative.c:345:\treturn \u0026CPU_FREQ_GOV_CONSERVATIVE;\ndrivers/cpufreq/cpufreq_conservative.c-346-}\n--\ndrivers/cpufreq/cpufreq_conservative.c-348-\ndrivers/cpufreq/cpufreq_conservative.c:349:cpufreq_governor_init(CPU_FREQ_GOV_CONSERVATIVE);\ndrivers/cpufreq/cpufreq_conservative.c:350:cpufreq_governor_exit(CPU_FREQ_GOV_CONSERVATIVE);\n--\ndrivers/cpufreq/cpufreq_ondemand.c=375=static struct dbs_governor od_dbs_gov = {\n--\ndrivers/cpufreq/cpufreq_ondemand.c-388-\ndrivers/cpufreq/cpufreq_ondemand.c:389:#define CPU_FREQ_GOV_ONDEMAND\t(od_dbs_gov.gov)\ndrivers/cpufreq/cpufreq_ondemand.c-390-\ndrivers/cpufreq/cpufreq_ondemand.c=391=static void od_set_powersave_bias(unsigned int powersave_bias)\n--\ndrivers/cpufreq/cpufreq_ondemand.c-412-\t\tpolicy = cpufreq_cpu_get_raw(cpu);\ndrivers/cpufreq/cpufreq_ondemand.c:413:\t\tif (!policy || policy-\u003egovernor != \u0026CPU_FREQ_GOV_ONDEMAND)\ndrivers/cpufreq/cpufreq_ondemand.c-414-\t\t\tcontinue;\n--\ndrivers/cpufreq/cpufreq_ondemand.c=454=struct cpufreq_governor *cpufreq_default_governor(void)\ndrivers/cpufreq/cpufreq_ondemand.c-455-{\ndrivers/cpufreq/cpufreq_ondemand.c:456:\treturn \u0026CPU_FREQ_GOV_ONDEMAND;\ndrivers/cpufreq/cpufreq_ondemand.c-457-}\n--\ndrivers/cpufreq/cpufreq_ondemand.c-459-\ndrivers/cpufreq/cpufreq_ondemand.c:460:cpufreq_governor_init(CPU_FREQ_GOV_ONDEMAND);\ndrivers/cpufreq/cpufreq_ondemand.c:461:cpufreq_governor_exit(CPU_FREQ_GOV_ONDEMAND);\n"
} |
| 25/2 | 2026/10/28 06:22 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 37461 output: 21 thoughts: 316 Thoughts: **Analyzing Recent Kernel Changes** Okay, let's dive back into these recent commits. I need a clear picture of what's been touched in `fs/dlm/lockspace.c`. Specifically, I want to refresh my memory on the function-level changes. Right, the key functions that were either newly introduced or modified are: `dlm_ls_release`, `free_lockspace`, `new_lockspace`, and `release_lockspace`. I should also keep in mind their relationship to `fs/dlm/user.c`, since I know `new_lockspace` and `release_lockspace` are called from `dlm_new_lockspace`, `dlm_release_lockspace`, `device_create_lockspace`, and `device_write` in that file. Moving on, what changes did they make in `fs/ubifs/sysfs.c`? Ah, I see: `ubifs_sysfs_init`, `ubifs_sysfs_register`, `ubifs_sysfs_unregister`, and `ubifs_sysfs_exit`. That makes sense; they're probably reorganizing the sysfs interface. And finally, I've got to review the updates to `cpufreq`. `cpufreq_dbs_data_release` and `cpufreq_dbs_governor_init` are the ones that have been changed. Wait a second, before I move on, I should verify the scope of the `dlm_new_lockspace` changes. Just to be thorough, I should search for all the call sites to `dlm_new_lockspace` across the kernel to be sure I haven't missed anything. I'll use grep for that; that'll give me a full picture. |
| 26/2 | 2026/10/28 06:22 | tool | grepper |
0mArgs:{
"Expression": "dlm_new_lockspace"
}Results: {
"Output": "drivers/md/md-cluster.c=883=static int join(struct mddev *mddev, int nodes)\n--\ndrivers/md/md-cluster.c-904-\tsprintf(str, \"%pU\", mddev-\u003euuid);\ndrivers/md/md-cluster.c:905:\tret = dlm_new_lockspace(str, mddev-\u003ebitmap_info.cluster_name,\ndrivers/md/md-cluster.c-906-\t\t\t\tDLM_LSFL_SOFTIRQ, LVB_SIZE, \u0026md_ls_ops, mddev,\n--\nfs/dlm/lockspace.c=371=static int new_lockspace(const char *name, const char *cluster,\n--\nfs/dlm/lockspace.c-637-\nfs/dlm/lockspace.c:638:static int __dlm_new_lockspace(const char *name, const char *cluster,\nfs/dlm/lockspace.c-639-\t\t\t uint32_t flags, int lvblen,\n--\nfs/dlm/lockspace.c-666-\nfs/dlm/lockspace.c:667:int dlm_new_lockspace(const char *name, const char *cluster, uint32_t flags,\nfs/dlm/lockspace.c-668-\t\t int lvblen, const struct dlm_lockspace_ops *ops,\n--\nfs/dlm/lockspace.c-671-{\nfs/dlm/lockspace.c:672:\treturn __dlm_new_lockspace(name, cluster, flags | DLM_LSFL_FS, lvblen,\nfs/dlm/lockspace.c-673-\t\t\t\t ops, ops_arg, ops_result, lockspace);\n--\nfs/dlm/lockspace.c=676=int dlm_new_user_lockspace(const char *name, const char *cluster,\n--\nfs/dlm/lockspace.c-684-\nfs/dlm/lockspace.c:685:\treturn __dlm_new_lockspace(name, cluster, flags, lvblen, ops,\nfs/dlm/lockspace.c-686-\t\t\t\t ops_arg, ops_result, lockspace);\n--\nfs/dlm/main.c=99=MODULE_LICENSE(\"GPL\");\nfs/dlm/main.c-100-\nfs/dlm/main.c:101:EXPORT_SYMBOL_GPL(dlm_new_lockspace);\nfs/dlm/main.c-102-EXPORT_SYMBOL_GPL(dlm_release_lockspace);\n--\nfs/dlm/user.c=469=static int check_version(struct dlm_write_request *req)\n--\nfs/dlm/user.c-501- * device_create_lockspace\nfs/dlm/user.c:502: * dlm_new_lockspace\nfs/dlm/user.c-503- *\n--\nfs/gfs2/lock_dlm.c=1292=static int gdlm_mount(struct gfs2_sbd *sdp, const char *table)\n--\nfs/gfs2/lock_dlm.c-1320-\t/*\nfs/gfs2/lock_dlm.c:1321:\t * prepare dlm_new_lockspace args\nfs/gfs2/lock_dlm.c-1322-\t */\n--\nfs/gfs2/lock_dlm.c-1340-\tinit_rwsem(\u0026ls-\u003els_sem);\nfs/gfs2/lock_dlm.c:1341:\terror = dlm_new_lockspace(fsname, cluster, flags, GDLM_LVB_SIZE,\nfs/gfs2/lock_dlm.c-1342-\t\t\t\t \u0026gdlm_lockspace_ops, sdp, \u0026ops_result,\n--\nfs/gfs2/lock_dlm.c-1344-\tif (error) {\nfs/gfs2/lock_dlm.c:1345:\t\tfs_err(sdp, \"dlm_new_lockspace error %d\\n\", error);\nfs/gfs2/lock_dlm.c-1346-\t\tgoto fail_free;\n--\nfs/ocfs2/stack_user.c=958=static int user_cluster_connect(struct ocfs2_cluster_connection *conn)\n--\nfs/ocfs2/stack_user.c-975-\nfs/ocfs2/stack_user.c:976:\trc = dlm_new_lockspace(conn-\u003ecc_name, conn-\u003ecc_cluster_name,\nfs/ocfs2/stack_user.c-977-\t\t\t DLM_LSFL_NEWEXCL, DLM_LVB_LEN,\n--\ninclude/linux/dlm.h=31=struct dlm_lockspace_ops {\n--\ninclude/linux/dlm.h-41-/*\ninclude/linux/dlm.h:42: * dlm_new_lockspace\ninclude/linux/dlm.h-43- *\n--\ninclude/linux/dlm.h-50- * including terminating null). Optional. When cluster is null, it\ninclude/linux/dlm.h:51: * is not used. When set, dlm_new_lockspace() returns -EBADR if cluster\ninclude/linux/dlm.h-52- * is not equal to the dlm cluster name.\n--\ninclude/linux/dlm.h-59- * DLM_LSFL_NEWEXCL\ninclude/linux/dlm.h:60: * dlm_new_lockspace() should return -EEXIST if the lockspace exists.\ninclude/linux/dlm.h-61- * DLM_LSFL_SOFTIRQ\n--\ninclude/linux/dlm.h-67- * lvblen: length of lvb in bytes. Must be multiple of 8.\ninclude/linux/dlm.h:68: * dlm_new_lockspace() returns an error if this does not match\ninclude/linux/dlm.h-69- * what other nodes are using.\n--\ninclude/linux/dlm.h-72- * caller can coordinate its recovery and know lockspace members.\ninclude/linux/dlm.h:73: * This is only used by the initial dlm_new_lockspace() call.\ninclude/linux/dlm.h-74- * Optional.\n--\ninclude/linux/dlm.h-84-\ninclude/linux/dlm.h:85:int dlm_new_lockspace(const char *name, const char *cluster,\ninclude/linux/dlm.h-86-\t\t uint32_t flags, int lvblen,\n--\ninclude/linux/dlm.h=126=int dlm_release_lockspace(dlm_lockspace_t *lockspace,\n--\ninclude/linux/dlm.h-163- * any locking calls they please. If DLM_LSFL_SOFTIRQ for kernel\ninclude/linux/dlm.h:164: * users of dlm_new_lockspace() is passed the ast and bast callbacks\ninclude/linux/dlm.h-165- * can be processed in softirq context. Also some of the callback\n--\ninclude/uapi/linux/dlm.h=62=struct dlm_lksb {\n--\ninclude/uapi/linux/dlm.h-68-\ninclude/uapi/linux/dlm.h:69:/* dlm_new_lockspace() flags */\ninclude/uapi/linux/dlm.h-70-\n"
} |
| 27/2 | 2026/10/28 06:23 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 40116 output: 36 thoughts: 45 Thoughts: Okay, let's dive into this. I need to understand how user space interacts with DLM to establish a lockspace. My intuition tells me that `device_create_lockspace` is the likely entry point. To solidify this, I'll need to reference the code. Let's head over to `fs/dlm/user.c` and zero in on around line 400. That's probably where the magic happens. |
| 28/2 | 2026/10/28 06:23 | tool | read-file |
0mArgs:{
"File": "fs/dlm/user.c",
"FirstLine": 400,
"LineCount": 50
}Results: {
"Contents": " 400:\t\terror = dlm_user_purge(ls, proc, params-\u003enodeid, params-\u003epid);\n 401:\t\n 402:\t\tdlm_put_lockspace(ls);\n 403:\t\treturn error;\n 404:\t}\n 405:\t\n 406:\tstatic int device_create_lockspace(struct dlm_lspace_params *params)\n 407:\t{\n 408:\t\tdlm_lockspace_t *lockspace;\n 409:\t\tstruct dlm_ls *ls;\n 410:\t\tint error;\n 411:\t\n 412:\t\tif (!capable(CAP_SYS_ADMIN))\n 413:\t\t\treturn -EPERM;\n 414:\t\n 415:\t\terror = dlm_new_user_lockspace(params-\u003ename, dlm_config.ci_cluster_name,\n 416:\t\t\t\t\t params-\u003eflags, DLM_USER_LVB_LEN, NULL,\n 417:\t\t\t\t\t NULL, NULL, \u0026lockspace);\n 418:\t\tif (error)\n 419:\t\t\treturn error;\n 420:\t\n 421:\t\tls = dlm_find_lockspace_local(lockspace);\n 422:\t\tif (!ls)\n 423:\t\t\treturn -ENOENT;\n 424:\t\n 425:\t\terror = dlm_device_register(ls, params-\u003ename);\n 426:\t\tdlm_put_lockspace(ls);\n 427:\t\n 428:\t\tif (error)\n 429:\t\t\tdlm_release_lockspace(lockspace, DLM_RELEASE_NO_LOCKS);\n 430:\t\telse\n 431:\t\t\terror = ls-\u003els_device.minor;\n 432:\t\n 433:\t\treturn error;\n 434:\t}\n 435:\t\n 436:\tstatic int device_remove_lockspace(struct dlm_lspace_params *params)\n 437:\t{\n 438:\t\tdlm_lockspace_t *lockspace;\n 439:\t\tstruct dlm_ls *ls;\n 440:\t\tint error, force = DLM_RELEASE_NO_LOCKS;\n 441:\t\n 442:\t\tif (!capable(CAP_SYS_ADMIN))\n 443:\t\t\treturn -EPERM;\n 444:\t\n 445:\t\tls = dlm_find_lockspace_device(params-\u003eminor);\n 446:\t\tif (!ls)\n 447:\t\t\treturn -ENOENT;\n 448:\t\n 449:\t\tif (params-\u003eflags \u0026 DLM_USER_LSFLG_FORCEFREE)\n"
} |
| 29/2 | 2026/10/28 06:23 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 41013 output: 32 thoughts: 269 Thoughts: **Analyzing Lockspace Creation and Removal in the Linux Kernel** Okay, let's break this down. My focus right now is on how lockspaces are handled within the kernel, specifically concerning the creation and removal processes. I'm seeing that `device_create_lockspace` and `device_remove_lockspace` are the key functions here. Importantly, these are triggered via `device_write` to `/dev/dlm-control`. My brain is immediately mapping this out: `device_create_lockspace` ultimately calls `dlm_new_user_lockspace`, which then leads to the creation of a new lockspace, which they're calling `new_lockspace`. Conversely, `device_remove_lockspace` calls `dlm_release_lockspace`, resulting in the lockspace being released through `release_lockspace`. The interesting point that leaps out is that when a lockspace is ultimately freed, the `free_lockspace` function is running in a workqueue. This is a common pattern, and I'm noting the crucial step within `free_lockspace`: the call to `kobject_put(&ls->ls_kobj); wait_for_completion(&ls->ls_kobj_done);`. This is important for ensuring proper reference counting and clean-up, and the completion wait signals that everything's actually finished. Now, let's zoom out to the broader context. I'm seeing that filesystems like `gfs2`, `ocfs2`, and even `md-cluster` all leverage these `dlm_new_lockspace` and `dlm_release_lockspace` functions. This means they're involved in their filesystem mount and unmount operations, or in cluster joining and leaving. A little side-note here, I'm noting that `ubifs` uses the `ubifs_sysfs_register` and `ubifs_sysfs_unregister` for its own mount and unmount process. Let me quickly cross-reference that in `fs/ubifs/sysfs.c` just to get an understanding of the interplay. |
| 30/2 | 2026/10/28 06:23 | tool | grepper |
0mArgs:{
"Expression": "ubifs_sysfs_register",
"PathPrefixes": [
"fs/ubifs"
]
}Results: {
"Output": "fs/ubifs/super.c=1199=static int mount_ubifs(struct ubifs_info *c)\n--\nfs/ubifs/super.c-1216-\nfs/ubifs/super.c:1217:\terr = ubifs_sysfs_register(c);\nfs/ubifs/super.c-1218-\tif (err)\n--\nfs/ubifs/sysfs.c=83=static struct kset *ubifs_kset;\nfs/ubifs/sysfs.c-84-\nfs/ubifs/sysfs.c:85:int ubifs_sysfs_register(struct ubifs_info *c)\nfs/ubifs/sysfs.c-86-{\n--\nfs/ubifs/ubifs.h=2110=void ubifs_sysfs_exit(void);\nfs/ubifs/ubifs.h:2111:int ubifs_sysfs_register(struct ubifs_info *c);\nfs/ubifs/ubifs.h-2112-void ubifs_sysfs_unregister(struct ubifs_info *c);\n"
} |
| 31/2 | 2026/10/28 06:23 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 42052 output: 32 thoughts: 1907 Thoughts: **Analysis of kobject Release Function Usage in Kernel Patches** Okay, let's break this down. First, I'm looking at the `cpufreq_dbs_data_release` function within `drivers/cpufreq/cpufreq_governor.c`. It's the release function for a `kobject` within `dbs_data->attr_set.kobj`. The implication here is that when the governor changes or stops, this function is called, ultimately freeing up resources. The key is how `kobject_put` calls `cpufreq_dbs_data_release` when the reference count drops to zero. Now, I need to understand the scope of this change, so I've looked at the files that were modified with this patch. It's a broad touch, hitting documentation, architectures (arm64, powerpc, sh), various drivers (ACPI, cpufreq, dma, GPU, infiniband, parisc, power, s390, soc, video, xen), filesystems (dlm, erofs, f2fs, ocfs2, ubifs), some include files, and a script. I'm particularly interested in `fs/dlm/lockspace.c` because it's a good example to analyze. `dlm_ls_release` is the release function there. Initially, I thought it was static, but looking closer it's address is actually being used (`dlm_ktype.release = dlm_ls_release;`). This means it will *not* be inlined. The focus should be on the more specific functions in this case. `dlm_ls_release` is static but whose address is taken, so it *is* an appropriate target. `free_lockspace` is also static, but its address is taken for `ls_free_work`. There are also non-static functions like `dlm_new_lockspace`, `dlm_release_lockspace`, and `dlm_new_user_lockspace`. Moving on to `fs/ubifs/sysfs.c`, I'm noting the functions related to sysfs initialization and unregistration: `ubifs_sysfs_init`, `ubifs_sysfs_register`, `ubifs_sysfs_unregister`, and `ubifs_sysfs_exit`. These are important entry points. Finally, within the cpufreq changes, I see `cpufreq_dbs_data_release` and the initialization function `cpufreq_dbs_governor_init`. My next step is to verify whether certain functions, including the static ones whose addresses are taken, are indeed visible in the vmlinux symbol table. My analysis shows that several of these functions, while static, are *not* inlined due to their address being passed around and therefore are eligible. `dlm_ls_release`, `free_lockspace`, and `cpufreq_dbs_data_release` are relevant because of their lifecycle. I will check `dlm_release_lockspace` in `fs/dlm/lockspace.c` to understand the full context. |
| 32/2 | 2026/10/28 06:23 | tool | grepper |
0mArgs:{
"Expression": "dlm_release_lockspace",
"PathPrefixes": [
"fs/dlm"
]
}Results: {
"Output": "fs/dlm/lockspace.c=721=static int release_lockspace(struct dlm_ls *ls, unsigned int release_option)\n--\nfs/dlm/lockspace.c-808-\nfs/dlm/lockspace.c:809:int dlm_release_lockspace(void *lockspace, unsigned int release_option)\nfs/dlm/lockspace.c-810-{\n--\nfs/dlm/main.c=101=EXPORT_SYMBOL_GPL(dlm_new_lockspace);\nfs/dlm/main.c:102:EXPORT_SYMBOL_GPL(dlm_release_lockspace);\nfs/dlm/main.c-103-EXPORT_SYMBOL_GPL(dlm_lock);\n--\nfs/dlm/member.c=479=static void dlm_lsop_recover_slot(struct dlm_ls *ls, struct dlm_member *memb,\n--\nfs/dlm/member.c-492-\t we consider the node to have failed (versus\nfs/dlm/member.c:493:\t being removed due to dlm_release_lockspace) */\nfs/dlm/member.c-494-\n--\nfs/dlm/user.c=377=int dlm_device_deregister(struct dlm_ls *ls)\n--\nfs/dlm/user.c-380-\t was never used from userspace, or when device_create_lockspace()\nfs/dlm/user.c:381:\t calls dlm_release_lockspace() after the register fails. */\nfs/dlm/user.c-382-\tif (!ls-\u003els_device.name)\n--\nfs/dlm/user.c=406=static int device_create_lockspace(struct dlm_lspace_params *params)\n--\nfs/dlm/user.c-428-\tif (error)\nfs/dlm/user.c:429:\t\tdlm_release_lockspace(lockspace, DLM_RELEASE_NO_LOCKS);\nfs/dlm/user.c-430-\telse\n--\nfs/dlm/user.c=436=static int device_remove_lockspace(struct dlm_lspace_params *params)\n--\nfs/dlm/user.c-454-\nfs/dlm/user.c:455:\t/* The final dlm_release_lockspace waits for references to go to\nfs/dlm/user.c-456-\t zero, so all processes will need to close their device for the\n--\nfs/dlm/user.c-461-\nfs/dlm/user.c:462:\terror = dlm_release_lockspace(lockspace, force);\nfs/dlm/user.c-463-\tif (error \u003e 0)\n--\nfs/dlm/user.c=469=static int check_version(struct dlm_write_request *req)\n--\nfs/dlm/user.c-504- * device_remove_lockspace\nfs/dlm/user.c:505: * dlm_release_lockspace\nfs/dlm/user.c-506- */\n"
} |
| 33/2 | 2026/10/28 06:23 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 45493 output: 47 thoughts: 253 Thoughts: **Configuration Dependencies Check** Okay, time to systematically review these configurations. Let's start with DLM. First, `CONFIG_DLM` itself... Ah, yes, it depends on `INET`, `SYSFS`, and `CONFIGFS_FS`. And we have the debugging option, `CONFIG_DLM_DEBUG`. Hmm, I should double-check if there are any other dependencies it might require. Let me just glance at `fs/dlm/Kconfig` again... lines 4 and 5... Yep, `depends on INET` and `depends on SYSFS && CONFIGFS_FS`, just as expected. That seems comprehensive for DLM. Next, UBIFS. `CONFIG_UBIFS_FS`. Okay, looking at `fs/ubifs/Kconfig`, it's clear: it depends on `MTD_UBI`, which, of course, needs `MTD`. Straightforward enough. Finally, the CPUFreq DBS governors. Specifically, `CONFIG_CPU_FREQ_GOV_ONDEMAND` and `CONFIG_CPU_FREQ_GOV_CONSERVATIVE`. We also have `CONFIG_CPU_FREQ_GOV_COMMON`, which is automatically selected. I should verify that `CONFIG_CPU_FREQ_GOV_ONDEMAND` is indeed dependent on `CPU_FREQ`. Let's check `drivers/cpufreq/Kconfig` and verify that dependency. |
| 34/2 | 2026/10/28 06:23 | tool | grepper |
0mArgs:{
"Expression": "config CPU_FREQ_GOV_COMMON|config CPU_FREQ_GOV_ONDEMAND",
"PathPrefixes": [
"drivers/cpufreq"
]
}Results: {
"Output": "drivers/cpufreq/Kconfig=22=config CPU_FREQ_GOV_ATTR_SET\n--\ndrivers/cpufreq/Kconfig-24-\ndrivers/cpufreq/Kconfig:25:config CPU_FREQ_GOV_COMMON\ndrivers/cpufreq/Kconfig-26-\tselect CPU_FREQ_GOV_ATTR_SET\n--\ndrivers/cpufreq/Kconfig=132=config CPU_FREQ_GOV_USERSPACE\n--\ndrivers/cpufreq/Kconfig-144-\ndrivers/cpufreq/Kconfig:145:config CPU_FREQ_GOV_ONDEMAND\ndrivers/cpufreq/Kconfig-146-\ttristate \"'ondemand' cpufreq policy governor\"\n"
} |
| 35/2 | 2026/10/28 06:23 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 46289 output: 36 thoughts: 24 Thoughts: Okay, here's my take on those lines from `drivers/cpufreq/Kconfig`, summarized as though I'm the one thinking it: **Digging into cpufreq/Kconfig** Alright, time to get my hands dirty. Let's zero in on lines 140 through 175 of the `drivers/cpufreq/Kconfig` file. I need to refresh my memory on the configuration options related to CPU frequency scaling. I'm especially interested in understanding the interplay of those options with the wider cpufreq framework, and possibly their dependencies on other kernel features. Let's see... I'm guessing this section probably covers different scaling governors or specific hardware support, depending on the architecture. I'm keen to identify if there are any new or changed options that I haven't seen before, or potentially spot a refactor or the introduction of a new platform. Ultimately, I'm expecting to either refresh my own knowledge or, even better, discover something new and interesting related to CPU frequency scaling. Let's get to it! |
| 36/2 | 2026/10/28 06:23 | tool | read-file |
0mArgs:{
"File": "drivers/cpufreq/Kconfig",
"FirstLine": 140,
"LineCount": 35
}Results: {
"Contents": " 140:\t\t To compile this driver as a module, choose M here: the\n 141:\t\t module will be called cpufreq_userspace.\n 142:\t\n 143:\t\t If in doubt, say Y.\n 144:\t\n 145:\tconfig CPU_FREQ_GOV_ONDEMAND\n 146:\t\ttristate \"'ondemand' cpufreq policy governor\"\n 147:\t\tselect CPU_FREQ_GOV_COMMON\n 148:\t\thelp\n 149:\t\t 'ondemand' - This driver adds a dynamic cpufreq policy governor.\n 150:\t\t The governor does a periodic polling and \n 151:\t\t changes frequency based on the CPU utilization.\n 152:\t\t The support for this governor depends on CPU capability to\n 153:\t\t do fast frequency switching (i.e, very low latency frequency\n 154:\t\t transitions). \n 155:\t\n 156:\t\t To compile this driver as a module, choose M here: the\n 157:\t\t module will be called cpufreq_ondemand.\n 158:\t\n 159:\t\t For details, take a look at\n 160:\t\t \u003cfile:Documentation/admin-guide/pm/cpufreq.rst\u003e.\n 161:\t\n 162:\t\t If in doubt, say N.\n 163:\t\n 164:\tconfig CPU_FREQ_GOV_CONSERVATIVE\n 165:\t\ttristate \"'conservative' cpufreq governor\"\n 166:\t\tselect CPU_FREQ_GOV_COMMON\n 167:\t\thelp\n 168:\t\t 'conservative' - this driver is rather similar to the 'ondemand'\n 169:\t\t governor both in its source code and its purpose, the difference is\n 170:\t\t its optimisation for better suitability in a battery powered\n 171:\t\t environment. The frequency is gracefully increased and decreased\n 172:\t\t rather than jumping to 100% when speed is required.\n 173:\t\n 174:\t\t If you have a desktop machine then you should really be considering\n"
} |
| 37/2 | 2026/10/28 06:23 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 47138 output: 482 thoughts: 1176 Thoughts: **Analysis of Kobject Lifecycle Refactoring in Kernel Code** Okay, let's break this down. First, I need to check the relevant configuration options, ensuring the features we're looking at are enabled. I see `CONFIG_CPU_FREQ` as a parent, and need to confirm that `DLM`, `CONFIGFS_FS`, `SYSFS`, `INET`, `UBIFS_FS`, `MTD_UBI`, `CPU_FREQ`, `CPU_FREQ_GOV_ONDEMAND`, and `CPU_FREQ_GOV_CONSERVATIVE` are all enabled, as they seem relevant. Now, let's identify what symbols need scrutiny. I'm focusing on subsystems that have notable executable code changes. For DLM, I'm noting `dlm_ls_release`, `free_lockspace`, `new_lockspace`, `release_lockspace`, `dlm_new_lockspace`, `dlm_release_lockspace`, and `dlm_new_user_lockspace`. For UBIFS, I see `ubifs_sysfs_register` and `ubifs_sysfs_unregister`. And for CPUFreq, `cpufreq_dbs_data_release`. I'll quickly verify the UBIFS functions are indeed direct entry points for UBIFS sysfs handling. Yes, confirmed. `mount_ubifs` calls `ubifs_sysfs_register`, and `ubifs_put_super` calls `ubifs_sysfs_unregister`. I'm seeing that in `fs/ubifs/sysfs.c`, `ubifs_sysfs_register` registers `c->kobj` with the parent `ubifs_kset`, which has been changed from a static struct to a pointer initialized via `kset_create_and_add`. Next, I need to analyze the DLM changes. In `fs/dlm/lockspace.c`, `dlm_ls_release` is a new release handler. `free_lockspace` now calls `kobject_put` and waits for `ls_kobj_done`. `new_lockspace` initializes `ls_kobj_done`, initializes `ls_kobj` earlier, and handles error unwinding, waiting for `ls->ls_kobj_done` completion. `release_lockspace` removes the `ls_kobj` from sysfs (`kobject_del`) and defers the `kobject_put` to `free_lockspace`. The `dlm_new_lockspace`, `dlm_release_lockspace`, and `dlm_new_user_lockspace` functions are the API entrypoints. This is a significant rework. Finally, in `drivers/cpufreq/`, `cpufreq_dbs_data_release` is the governor's release function, now exported and hooked up to `cs_governor.kobj_type.release` and `od_dbs_gov.kobj_type.release`. Crucially, none of these changes introduce generic functions. This means these are all specific feature logic and entry points for the kobject lifetimes within their respective subsystems. My reasoning, then, is this: the patch introduces `__must_init` on `struct kobj_type.release`, which forces explicit release callbacks for kobjects at compile time. This necessitated refactoring or fixing kobject lifetimes in these core subsystems: 1. `fs/dlm/`: A significant rework of the lifecycle and destruction synchronization of `struct dlm_ls` kobjects. The patch adds a completion (`ls_kobj_done`), a release callback (`dlm_ls_release`), changes error unwinding, defers `kobject_put`, and adds a wait for `ls_kobj_done` completion. This affects synchronization and destruction in filesystem/clustering code (accessible via `/dev/dlm-control`). 2. `fs/ubifs/`: The `ubifs_kset` is now dynamically allocated, affecting UBIFS sysfs registration/unregistration during mount/unmount. 3. `drivers/cpufreq/`: The governor `kobj_type.release` assignment is now statically initialized, with `cpufreq_dbs_data_release` being exported. While there are changes in other files, these primarily relate to unreachable hardware or are architecture-specific. The changes in `fs/dlm`, `fs/ubifs`, and `cpufreq` are in fully reachable code on amd64. Therefore, fuzzing is warranted to look for regressions, race conditions, or hangs, especially around the DLM code and concurrent sysfs access. I'm ready to call `set-results`. |
| 38/2 | 2026/10/28 06:24 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"DLM",
"CONFIGFS_FS",
"SYSFS",
"INET",
"UBIFS_FS",
"MTD_UBI",
"CPU_FREQ",
"CPU_FREQ_GOV_ONDEMAND",
"CPU_FREQ_GOV_CONSERVATIVE"
],
"FocusSymbols": [
"dlm_ls_release",
"free_lockspace",
"new_lockspace",
"release_lockspace",
"dlm_new_lockspace",
"dlm_release_lockspace",
"dlm_new_user_lockspace",
"ubifs_sysfs_register",
"ubifs_sysfs_unregister",
"cpufreq_dbs_data_release"
],
"Reasoning": "The patch introduces '__must_init' on 'struct kobj_type.release' and addresses missing or improper kobject release callbacks across various drivers and subsystems. In reachable core subsystems on amd64, notable functional and synchronization refactorings were introduced:\n1. In fs/dlm/lockspace.c, the lifecycle of struct dlm_ls kobjects was overhauled by introducing a new completion (ls_kobj_done), a release callback (dlm_ls_release), reordered kobject initialization/teardown in new_lockspace(), moving kobject_put() into free_lockspace(), and waiting on the completion before freeing the lockspace. This changes destruction and synchronization behavior on code accessible via /dev/dlm-control and filesystem mounts.\n2. In fs/ubifs/sysfs.c, ubifs_kset was transitioned from a static struct kset to a dynamically allocated kset created via kset_create_and_add().\n3. In drivers/cpufreq/, dbs_governor kobj_type release callback handling was refactored with exported cpufreq_dbs_data_release.\n\nThese alterations in reachable filesystem and core subsystem lifecycle code warrant fuzzing to identify potential regressions, use-after-free, or hang/deadlock conditions (particularly around the new completion wait during dlm lockspace teardown).",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"DLM",
"CONFIGFS_FS",
"SYSFS",
"INET",
"UBIFS_FS",
"MTD_UBI",
"CPU_FREQ",
"CPU_FREQ_GOV_ONDEMAND",
"CPU_FREQ_GOV_CONSERVATIVE"
],
"FocusSymbols": [
"dlm_ls_release",
"free_lockspace",
"new_lockspace",
"release_lockspace",
"dlm_new_lockspace",
"dlm_release_lockspace",
"dlm_new_user_lockspace",
"ubifs_sysfs_register",
"ubifs_sysfs_unregister",
"cpufreq_dbs_data_release"
],
"Reasoning": "The patch introduces '__must_init' on 'struct kobj_type.release' and addresses missing or improper kobject release callbacks across various drivers and subsystems. In reachable core subsystems on amd64, notable functional and synchronization refactorings were introduced:\n1. In fs/dlm/lockspace.c, the lifecycle of struct dlm_ls kobjects was overhauled by introducing a new completion (ls_kobj_done), a release callback (dlm_ls_release), reordered kobject initialization/teardown in new_lockspace(), moving kobject_put() into free_lockspace(), and waiting on the completion before freeing the lockspace. This changes destruction and synchronization behavior on code accessible via /dev/dlm-control and filesystem mounts.\n2. In fs/ubifs/sysfs.c, ubifs_kset was transitioned from a static struct kset to a dynamically allocated kset created via kset_create_and_add().\n3. In drivers/cpufreq/, dbs_governor kobj_type release callback handling was refactored with exported cpufreq_dbs_data_release.\n\nThese alterations in reachable filesystem and core subsystem lifecycle code warrant fuzzing to identify potential regressions, use-after-free, or hang/deadlock conditions (particularly around the new completion wait during dlm lockspace teardown).",
"WorthFuzzing": true
} |
| 39/1 | 2026/10/28 06:24 | action | If |
0mArgs:{
"WorthFuzzing": true
}Results: null |
| 40/2 | 2026/10/28 06:24 | agent | kmsan-evaluator |
0mModel:core Args: null Results: {
"KMSANReasoning": "The patch series introduces a new compile-time attribute `__must_init` (using Clang's `__require_explicit_initialization__` attribute) on `struct kobj_type.release` to require explicit initialization of the kobject release callback. In order to comply with this requirement and address kobject lifecycle issues, the patch adds explicit `.release` entries (either `NULL` for embedded/static kobjects or proper cleanup callbacks) and refactors kobject lifecycle handling in several subsystems (e.g., amdkfd queue release, DLM lockspace completion on release, and dynamic allocation of ubifs_kset).\n\nThese changes purely involve compile-time attribute validation and runtime kobject reference counting and object lifecycle management. Potential bugs arising from these changes (such as use-after-free, double free, or invalid refcounting) are within the domain of KASAN, refcount tracking, and CONFIG_DEBUG_KOBJECT_RELEASE. The patch does not introduce or modify any uninitialized memory reads, uninitialized struct fields, bounds/length calculations on raw memory buffers, or kernel-to-user information copies. Therefore, a dedicated KMSAN fuzzing session is not warranted.",
"NeedsKMSAN": false
}Instruction: You are an expert Linux kernel security engineer specializing in kernel memory
error detectors (KASAN and KMSAN). Your job is to review the provided patch series and
determine if the code changes justify spawning a dedicated KMSAN (KernelMemorySanitizer)
fuzzing session in addition to standard KASAN fuzzing.
CRITICAL DISTINCTION BETWEEN KASAN AND KMSAN:
- Standard KASAN kernel builds (upstream-apparmor-kasan.config) already enable
a comprehensive suite of debugging tools and sanitizers, including KASAN
(out-of-bounds accesses, use-after-free, double free, invalid free), LOCKDEP
(locking bugs and deadlocks), UB-sanitizers, and memory corruption checks.
- KMSAN (KernelMemorySanitizer) detects reads of UNINITIALIZED memory (stack, heap,
or page allocations) and kernel-to-user memory info-leaks.
Rule: THERE IS NO SENSE IN RUNNING A KMSAN SESSION IF A BUG CAN BE CAUGHT BY KASAN,
LOCKDEP, OR OTHER STANDARD BUG DETECTORS.
A dedicated KMSAN fuzzing session incurs significant resource costs. You must ONLY
set NeedsKMSAN=true if the code changes introduce or expose UNINITIALIZED MEMORY risks
that are detected ONLY by KMSAN.
Look holistically at the patch series and surrounding code. Even if no direct
uninitialized field accesses or new buffer allocations are added in the diff itself,
a patch may alter control flow, bounds checking, or data length calculations in ways
that change how the rest of the code operates on existing buffers (e.g. allowing
uninitialized stack/heap memory to be read, copied to user space, or used in control
flow). Do not hesitate to use your code access tools to inspect the surrounding code,
called functions, and callers.
Set NeedsKMSAN=true ONLY IF the patch introduces or modifies:
1. Kernel structures sent to user space (via copy_to_user, put_user, netlink skb
attributes, ioctl output arguments, socket options, or BPF buffers) where fields
or structure padding might not be fully initialized/zeroed.
2. Conditional logic or branching that depends on potentially uninitialized variables
or struct fields.
3. Allocation or initialization of complex data structures where uninitialized fields
could be read later in reachable code paths.
4. Bounds checks, lengths, or logic in a way that allows surrounding code to access
uninitialized bytes of existing buffers.
Set NeedsKMSAN=false IF:
- The code changes primarily risk out-of-bounds access, array overflows, NULL pointer
dereferences, locking deadlocks, or use-after-free bugs (these are already caught
by KASAN, LOCKDEP, or standard bug detectors).
- All stack/heap structures touched or introduced by the patch are fully zeroed
or initialized (e.g. using = {0}, memset, kzalloc) before being read or copied.
- The patch does not introduce any risk of uninitialized memory usage or info-leaks.
Use your code access tools to inspect the surrounding code if necessary, then provide
detailed KMSANReasoning contrasting KASAN vs KMSAN applicability for this patch.
Prefer calling several tools at the same time to save round-trips.
Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.
Prompt: Target architecture: amd64
For your convenience, here is the diff of the changes:
commit aeb7a14c32eb7ebc6a77c24bd1d1349164380cbb
Author: syz-cluster <triage@syzkaller.com>
Date: Wed Oct 28 06:19:50 2026 +0000
syz-cluster: applied patch under review
diff --git a/Documentation/conf.py b/Documentation/conf.py
index 5ab26ce89dafe6..baaa4035258c86 100644
--- a/Documentation/conf.py
+++ b/Documentation/conf.py
@@ -203,6 +203,7 @@ c_id_attributes = [
"__noreturn",
"__packed",
"__pure",
+ "__must_init",
"__section",
"__always_unused",
"__maybe_unused",
diff --git a/arch/arm64/kernel/cpuinfo.c b/arch/arm64/kernel/cpuinfo.c
index 94e6cd211d70e6..7a4ac8dd0b86a6 100644
--- a/arch/arm64/kernel/cpuinfo.c
+++ b/arch/arm64/kernel/cpuinfo.c
@@ -295,6 +295,11 @@ const struct seq_operations cpuinfo_op = {
static const struct kobj_type cpuregs_kobj_type = {
+ /*
+ * Pre-existing: info->kobj is embedded in per-CPU cpu_data;
+ * cpuid_cpu_offline() only calls kobject_del().
+ */
+ .release = NULL,
.sysfs_ops = &kobj_sysfs_ops,
};
diff --git a/arch/powerpc/kernel/secvar-sysfs.c b/arch/powerpc/kernel/secvar-sysfs.c
index 395399bbab2c69..f3f6ac25ea788f 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,
};
diff --git a/arch/sh/kernel/cpu/sh4/sq.c b/arch/sh/kernel/cpu/sh4/sq.c
index 908a8e09113b7d..f33864958487ba 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,
};
diff --git a/drivers/acpi/sysfs.c b/drivers/acpi/sysfs.c
index a993735471261c..1948b80e8a4a0e 100644
--- a/drivers/acpi/sysfs.c
+++ b/drivers/acpi/sysfs.c
@@ -973,6 +973,8 @@ static struct attribute *hotplug_profile_attrs[] = {
ATTRIBUTE_GROUPS(hotplug_profile);
static const struct kobj_type acpi_hotplug_profile_ktype = {
+ /* Pre-existing: hotplug->kobj is embedded in static struct acpi_scan_hotplug objects. */
+ .release = NULL,
.sysfs_ops = &kobj_sysfs_ops,
.default_groups = hotplug_profile_groups,
};
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index 02bfd46543e99c..146a2353b1a204 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -318,7 +318,10 @@ static void cs_limits(struct cpufreq_policy *policy)
static struct dbs_governor cs_governor = {
.gov = CPUFREQ_DBS_GOVERNOR_INITIALIZER("conservative"),
- .kobj_type = { .default_groups = cs_groups },
+ .kobj_type = {
+ .release = cpufreq_dbs_data_release,
+ .default_groups = cs_groups,
+ },
.gov_dbs_update = cs_dbs_update,
.alloc = cs_alloc,
.free = cs_free,
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
index f3bd3dbe7c419c..f8b5aca09b6b69 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -419,7 +419,7 @@ static void free_policy_dbs_info(struct policy_dbs_info *policy_dbs,
gov->free(policy_dbs);
}
-static void cpufreq_dbs_data_release(struct kobject *kobj)
+void cpufreq_dbs_data_release(struct kobject *kobj)
{
struct dbs_data *dbs_data = to_dbs_data(to_gov_attr_set(kobj));
struct dbs_governor *gov = dbs_data->gov;
@@ -427,6 +427,7 @@ static void cpufreq_dbs_data_release(struct kobject *kobj)
gov->exit(dbs_data);
kfree(dbs_data);
}
+EXPORT_SYMBOL_GPL(cpufreq_dbs_data_release);
int cpufreq_dbs_governor_init(struct cpufreq_policy *policy)
{
@@ -488,7 +489,6 @@ int cpufreq_dbs_governor_init(struct cpufreq_policy *policy)
policy->governor_data = policy_dbs;
gov->kobj_type.sysfs_ops = &governor_sysfs_ops;
- gov->kobj_type.release = cpufreq_dbs_data_release;
ret = kobject_init_and_add(&dbs_data->attr_set.kobj, &gov->kobj_type,
get_governor_parent_kobj(policy),
"%s", gov->gov.name);
diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h
index 806d8fb4dff1d9..1026712bb79b87 100644
--- a/drivers/cpufreq/cpufreq_governor.h
+++ b/drivers/cpufreq/cpufreq_governor.h
@@ -150,6 +150,7 @@ static inline struct dbs_governor *dbs_governor_of(struct cpufreq_policy *policy
}
/* Governor callback routines */
+void cpufreq_dbs_data_release(struct kobject *kobj);
int cpufreq_dbs_governor_init(struct cpufreq_policy *policy);
void cpufreq_dbs_governor_exit(struct cpufreq_policy *policy);
int cpufreq_dbs_governor_start(struct cpufreq_policy *policy);
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 9942dbb38dae41..7386d043c66541 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,
diff --git a/drivers/dma/ioat/sysfs.c b/drivers/dma/ioat/sysfs.c
index e796ddb5383f8f..5ba44876eb96e3 100644
--- a/drivers/dma/ioat/sysfs.c
+++ b/drivers/dma/ioat/sysfs.c
@@ -167,6 +167,13 @@ static const struct attribute *const ioat_attrs[] = {
ATTRIBUTE_GROUPS(ioat);
const struct kobj_type ioat_ktype = {
+ /*
+ * Pre-existing: ioatdma_chan is freed by release_ioatdma(), not
+ * by kobject_put(). With CONFIG_DEBUG_KOBJECT_RELEASE the delayed
+ * kobject cleanup queued by ioat_kobject_del() may run after
+ * that kfree(), a use-after-free.
+ */
+ .release = NULL,
.sysfs_ops = &ioat_sysfs_ops,
.default_groups = ioat_groups,
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
index 17888cf544472c..c2cccd924b03c4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ualink.c
@@ -885,6 +885,11 @@ static const struct attribute_group ualink_xcp_info_group = {
};
static const struct kobj_type ualink_xcp_info_ktype = {
+ /*
+ * Pre-existing: xcp->ualink.kobj is embedded in struct amdgpu_xcp_mgr
+ * rather than freed individually by kobject_put().
+ */
+ .release = NULL,
.sysfs_ops = &kobj_sysfs_ops
};
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
index ab14079d1c4222..0847134a139171 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xcp.c
@@ -797,6 +797,11 @@ static const struct sysfs_ops xcp_cfg_res_sysfs_ops = {
};
static const struct kobj_type xcp_cfg_res_sysfs_ktype = {
+ /*
+ * Pre-existing: xcp_res is embedded in struct amdgpu_xcp_cfg
+ * rather than freed individually by kobject_put().
+ */
+ .release = NULL,
.sysfs_ops = &xcp_cfg_res_sysfs_ops,
.default_groups = xcp_cfg_res_sysfs_groups,
};
@@ -1061,6 +1066,11 @@ static const struct attribute_group amdgpu_xcp_attrs_group = {
};
static const struct kobj_type xcp_sysfs_ktype = {
+ /*
+ * Pre-existing: xcp is embedded in struct amdgpu_xcp_mgr
+ * rather than freed individually by kobject_put().
+ */
+ .release = NULL,
.sysfs_ops = &kobj_sysfs_ops,
};
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index 226f52626e849d..8e6136d52a50d0 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -512,7 +512,15 @@ static const struct sysfs_ops procfs_queue_ops = {
.show = kfd_procfs_queue_show,
};
+static void kfd_procfs_queue_release(struct kobject *kobj)
+{
+ struct queue *q = container_of(kobj, struct queue, kobj);
+
+ kfree(q);
+}
+
static const struct kobj_type procfs_queue_type = {
+ .release = kfd_procfs_queue_release,
.sysfs_ops = &procfs_queue_ops,
.default_groups = procfs_queue_groups,
};
@@ -552,7 +560,6 @@ int kfd_procfs_add_queue(struct queue *q)
if (ret < 0) {
pr_warn("Creating proc/<pid>/queues/%u failed",
q->properties.queue_id);
- kobject_put(&q->kobj);
return ret;
}
@@ -697,11 +704,10 @@ static void kfd_procfs_add_sysfs_files(struct kfd_process *p)
void kfd_procfs_del_queue(struct queue *q)
{
- if (!q || !q->process->kobj)
+ if (!q || !q->process || !q->process->kobj || !q->kobj.state_in_sysfs)
return;
kobject_del(&q->kobj);
- kobject_put(&q->kobj);
}
int kfd_process_create_wq(void)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_queue.c
index ae3e7c54014a86..4666110aebe07c 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)
diff --git a/drivers/infiniband/hw/hfi1/sysfs.c b/drivers/infiniband/hw/hfi1/sysfs.c
index 372cfd13dc6160..5a1aca06b542b2 100644
--- a/drivers/infiniband/hw/hfi1/sysfs.c
+++ b/drivers/infiniband/hw/hfi1/sysfs.c
@@ -608,6 +608,11 @@ static const struct sysfs_ops sde_sysfs_ops = {
};
static struct kobj_type sde_ktype = {
+ /*
+ * Pre-existing: sdma_engine is embedded in dd->per_sdma array
+ * rather than freed by kobject_put().
+ */
+ .release = NULL,
.sysfs_ops = &sde_sysfs_ops,
};
diff --git a/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c b/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
index fdb63a8fb9974b..df0e48070c2ee9 100644
--- a/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
+++ b/drivers/infiniband/hw/usnic/usnic_ib_sysfs.c
@@ -245,6 +245,8 @@ static struct attribute *usnic_ib_qpn_default_attrs[] = {
ATTRIBUTE_GROUPS(usnic_ib_qpn_default);
static struct kobj_type usnic_ib_qpn_type = {
+ /* Pre-existing: usnic_ib_qp_grp is embedded in RDMA core-managed struct usnic_ib_qp_grp. */
+ .release = NULL,
.sysfs_ops = &usnic_ib_qpn_sysfs_ops,
.default_groups = usnic_ib_qpn_default_groups,
};
diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c
index 6b567a74fc2cb2..2f530e8c675793 100644
--- a/drivers/parisc/pdc_stable.c
+++ b/drivers/parisc/pdc_stable.c
@@ -484,6 +484,11 @@ ATTRIBUTE_GROUPS(paths_subsys);
/* Specific kobject type for our PDC paths */
static const struct kobj_type ktype_pdcspath = {
+ /*
+ * Pre-existing: pdcspath_entry instances are static; lifetime
+ * is not controlled by kobject_put().
+ */
+ .release = NULL,
.sysfs_ops = &pdcspath_attr_ops,
.default_groups = paths_subsys_groups,
};
diff --git a/drivers/power/supply/ab8500_fg.c b/drivers/power/supply/ab8500_fg.c
index e6b5efdf5dc9bc..d62411e4f5355d 100644
--- a/drivers/power/supply/ab8500_fg.c
+++ b/drivers/power/supply/ab8500_fg.c
@@ -2531,6 +2531,11 @@ static struct attribute *ab8500_fg_attrs[] = {
ATTRIBUTE_GROUPS(ab8500_fg);
static const struct kobj_type ab8500_fg_ktype = {
+ /*
+ * Pre-existing: fg_kobject is embedded in devm-allocated struct
+ * ab8500_fg; ab8500_fg_sysfs_exit() only calls kobject_del().
+ */
+ .release = NULL,
.sysfs_ops = &ab8500_fg_sysfs_ops,
.default_groups = ab8500_fg_groups,
};
diff --git a/drivers/s390/char/sclp_mem.c b/drivers/s390/char/sclp_mem.c
index 6df1926d4c62a1..2fb7271dce362f 100644
--- a/drivers/s390/char/sclp_mem.c
+++ b/drivers/s390/char/sclp_mem.c
@@ -305,6 +305,8 @@ static ssize_t sclp_memmap_on_memory_store(struct kobject *kobj, struct kobj_att
}
static const struct kobj_type ktype = {
+ /* Pre-existing: permanent firmware kobjects, never freed */
+ .release = NULL,
.sysfs_ops = &kobj_sysfs_ops,
};
diff --git a/drivers/soc/hisilicon/kunpeng_hccs.c b/drivers/soc/hisilicon/kunpeng_hccs.c
index 0cc2953d59a54b..da7a64c9505878 100644
--- a/drivers/soc/hisilicon/kunpeng_hccs.c
+++ b/drivers/soc/hisilicon/kunpeng_hccs.c
@@ -1038,6 +1038,13 @@ static struct attribute *hccs_port_default_attrs[] = {
ATTRIBUTE_GROUPS(hccs_port_default);
static const struct kobj_type hccs_port_type = {
+ /*
+ * Pre-existing: hccs_port_info is allocated via devm_kzalloc()
+ * rather than freed by kobject_put(). With
+ * CONFIG_DEBUG_KOBJECT_RELEASE the delayed kobject cleanup may run
+ * after devm frees it on unbind, a use-after-free.
+ */
+ .release = NULL,
.sysfs_ops = &hccs_comm_ops,
.default_groups = hccs_port_default_groups,
};
@@ -1110,6 +1117,13 @@ static struct attribute *hccs_die_default_attrs[] = {
ATTRIBUTE_GROUPS(hccs_die_default);
static const struct kobj_type hccs_die_type = {
+ /*
+ * Pre-existing: hccs_die_info is allocated via devm_kzalloc()
+ * rather than freed by kobject_put(). With
+ * CONFIG_DEBUG_KOBJECT_RELEASE the delayed kobject cleanup may run
+ * after devm frees it on unbind, a use-after-free.
+ */
+ .release = NULL,
.sysfs_ops = &hccs_comm_ops,
.default_groups = hccs_die_default_groups,
};
@@ -1213,6 +1227,13 @@ static struct attribute *hccs_chip_default_attrs[] = {
ATTRIBUTE_GROUPS(hccs_chip_default);
static const struct kobj_type hccs_chip_type = {
+ /*
+ * Pre-existing: hccs_chip_info is allocated via devm_kzalloc()
+ * rather than freed by kobject_put(). With
+ * CONFIG_DEBUG_KOBJECT_RELEASE the delayed kobject cleanup may run
+ * after devm frees it on unbind, a use-after-free.
+ */
+ .release = NULL,
.sysfs_ops = &hccs_comm_ops,
.default_groups = hccs_chip_default_groups,
};
diff --git a/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c b/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c
index ae937854403b12..452920a4e2a9a9 100644
--- a/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c
+++ b/drivers/video/fbdev/omap2/omapfb/dss/display-sysfs.c
@@ -304,6 +304,13 @@ static const struct sysfs_ops display_sysfs_ops = {
};
static struct kobj_type display_ktype = {
+ /*
+ * Pre-existing: dssdev->kobj is embedded in struct omap_dss_device
+ * and zeroed in display_uninit_sysfs() right after kobject_put().
+ * With CONFIG_DEBUG_KOBJECT_RELEASE that memset() clobbers the
+ * pending delayed kobject cleanup.
+ */
+ .release = NULL,
.sysfs_ops = &display_sysfs_ops,
.default_groups = display_sysfs_groups,
};
diff --git a/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c b/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c
index 1b644be5fe2ed0..40ec750f431559 100644
--- a/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c
+++ b/drivers/video/fbdev/omap2/omapfb/dss/manager-sysfs.c
@@ -496,6 +496,11 @@ static const struct sysfs_ops manager_sysfs_ops = {
};
static struct kobj_type manager_ktype = {
+ /*
+ * Pre-existing: mgr->kobj is embedded in static managers[] and
+ * zeroed in dss_manager_kobj_uninit().
+ */
+ .release = NULL,
.sysfs_ops = &manager_sysfs_ops,
.default_groups = manager_sysfs_groups,
};
diff --git a/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c b/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c
index 1da4fb1c77b4a6..4d333031b18d6d 100644
--- a/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c
+++ b/drivers/video/fbdev/omap2/omapfb/dss/overlay-sysfs.c
@@ -429,6 +429,11 @@ static const struct sysfs_ops overlay_sysfs_ops = {
};
static struct kobj_type overlay_ktype = {
+ /*
+ * Pre-existing: ovl->kobj is embedded in static overlays[];
+ * dss_overlay_kobj_uninit() drops the kobject ref.
+ */
+ .release = NULL,
.sysfs_ops = &overlay_sysfs_ops,
.default_groups = overlay_sysfs_groups,
};
diff --git a/drivers/xen/sys-hypervisor.c b/drivers/xen/sys-hypervisor.c
index 91923242a5ae71..0e8a2cd69fd69a 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,
};
diff --git a/fs/dlm/dlm_internal.h b/fs/dlm/dlm_internal.h
index 74c2e77d1b553e..95b3bff0cb57aa 100644
--- a/fs/dlm/dlm_internal.h
+++ b/fs/dlm/dlm_internal.h
@@ -576,6 +576,7 @@ struct dlm_ls {
int ls_create_count; /* create/release refcount */
unsigned long ls_flags; /* LSFL_ */
struct kobject ls_kobj;
+ struct completion ls_kobj_done;
struct xarray ls_lkbxa;
rwlock_t ls_lkbxa_lock;
diff --git a/fs/dlm/lockspace.c b/fs/dlm/lockspace.c
index a9c98b4f378f3a..2dccd080a10f64 100644
--- a/fs/dlm/lockspace.c
+++ b/fs/dlm/lockspace.c
@@ -179,7 +179,15 @@ static const struct sysfs_ops dlm_attr_ops = {
.store = dlm_attr_store,
};
+static void dlm_ls_release(struct kobject *kobj)
+{
+ struct dlm_ls *ls = container_of(kobj, struct dlm_ls, ls_kobj);
+
+ complete(&ls->ls_kobj_done);
+}
+
static struct kobj_type dlm_ktype = {
+ .release = dlm_ls_release,
.default_groups = dlm_groups,
.sysfs_ops = &dlm_attr_ops,
};
@@ -355,6 +363,8 @@ static void free_lockspace(struct work_struct *work)
*/
rhashtable_free_and_destroy(&ls->ls_rsbtbl, rhash_free_rsb, NULL);
+ kobject_put(&ls->ls_kobj);
+ wait_for_completion(&ls->ls_kobj_done);
kfree(ls);
}
@@ -435,7 +445,10 @@ static int new_lockspace(const char *name, const char *cluster,
ls->ls_lvblen = lvblen;
atomic_set(&ls->ls_count, 0);
init_waitqueue_head(&ls->ls_count_wait);
+ init_completion(&ls->ls_kobj_done);
ls->ls_flags = 0;
+ ls->ls_kobj.kset = dlm_kset;
+ kobject_init(&ls->ls_kobj, &dlm_ktype);
if (ops && dlm_config.ci_recover_callbacks) {
ls->ls_ops = ops;
@@ -567,9 +580,7 @@ static int new_lockspace(const char *name, const char *cluster,
wait_event(ls->ls_recover_lock_wait,
test_bit(LSFL_RECOVER_LOCK, &ls->ls_flags));
- ls->ls_kobj.kset = dlm_kset;
- error = kobject_init_and_add(&ls->ls_kobj, &dlm_ktype, NULL,
- "%s", ls->ls_name);
+ error = kobject_add(&ls->ls_kobj, NULL, "%s", ls->ls_name);
if (error)
goto out_recoverd;
kobject_uevent(&ls->ls_kobj, KOBJ_ADD);
@@ -582,7 +593,7 @@ static int new_lockspace(const char *name, const char *cluster,
error = do_uevent(ls, 1, 0);
if (error < 0)
- goto out_recoverd;
+ goto out_kobj;
/* wait until recovery is successful or failed */
wait_for_completion(&ls->ls_recovery_done);
@@ -600,6 +611,8 @@ static int new_lockspace(const char *name, const char *cluster,
do_uevent(ls, 0, 0);
dlm_clear_members(ls);
kfree(ls->ls_node_array);
+ out_kobj:
+ kobject_del(&ls->ls_kobj);
out_recoverd:
dlm_recoverd_stop(ls);
out_callback:
@@ -615,6 +628,7 @@ static int new_lockspace(const char *name, const char *cluster,
rhashtable_destroy(&ls->ls_rsbtbl);
out_lsfree:
kobject_put(&ls->ls_kobj);
+ wait_for_completion(&ls->ls_kobj_done);
kfree(ls);
out:
module_put(THIS_MODULE);
@@ -740,6 +754,8 @@ static int release_lockspace(struct dlm_ls *ls, unsigned int release_option)
dlm_user_daemon_available())
do_uevent(ls, 0, (release_option == DLM_RELEASE_RECOVER));
+ kobject_del(&ls->ls_kobj);
+
dlm_recoverd_stop(ls);
/* clear the LSFL_RUNNING flag to fast up
@@ -759,8 +775,6 @@ static int release_lockspace(struct dlm_ls *ls, unsigned int release_option)
dlm_delete_debug_file(ls);
- kobject_put(&ls->ls_kobj);
-
xa_destroy(&ls->ls_recover_xa);
kfree(ls->ls_recover_buf);
diff --git a/fs/erofs/sysfs.c b/fs/erofs/sysfs.c
index dfcec9376cd54d..2ea6773cd98fdd 100644
--- a/fs/erofs/sysfs.c
+++ b/fs/erofs/sysfs.c
@@ -238,6 +238,11 @@ static const struct kobj_type erofs_sb_ktype = {
static const struct kobj_type erofs_ktype = {
.default_groups = erofs_groups,
.sysfs_ops = &erofs_attr_ops,
+ /*
+ * Pre-existing: erofs_root is a static struct kset; lifetime
+ * is not controlled by kobject_put().
+ */
+ .release = NULL,
};
static struct kset erofs_root = {
@@ -247,6 +252,11 @@ static struct kset erofs_root = {
static const struct kobj_type erofs_feat_ktype = {
.default_groups = erofs_feat_groups,
.sysfs_ops = &erofs_attr_ops,
+ /*
+ * Pre-existing: erofs_feat is a static struct kobject; lifetime
+ * is not controlled by kobject_put().
+ */
+ .release = NULL,
};
static struct kobject erofs_feat = {
diff --git a/fs/f2fs/sysfs.c b/fs/f2fs/sysfs.c
index 430356e500afd6..6e15695cb75f1c 100644
--- a/fs/f2fs/sysfs.c
+++ b/fs/f2fs/sysfs.c
@@ -1683,6 +1683,11 @@ static const struct kobj_type f2fs_sb_ktype = {
static const struct kobj_type f2fs_ktype = {
.sysfs_ops = &f2fs_attr_ops,
+ /*
+ * Pre-existing: f2fs_kset is a static struct kset; lifetime
+ * is not controlled by kobject_put().
+ */
+ .release = NULL,
};
static struct kset f2fs_kset = {
@@ -1697,6 +1702,11 @@ static const struct sysfs_ops f2fs_feat_attr_ops = {
static const struct kobj_type f2fs_feat_ktype = {
.default_groups = f2fs_feat_groups,
.sysfs_ops = &f2fs_feat_attr_ops,
+ /*
+ * Pre-existing: f2fs_feat is a static struct kobject; lifetime
+ * is not controlled by kobject_put().
+ */
+ .release = NULL,
};
static struct kobject f2fs_feat = {
@@ -1711,6 +1721,11 @@ static const struct sysfs_ops f2fs_tune_attr_ops = {
static const struct kobj_type f2fs_tune_ktype = {
.default_groups = f2fs_tune_groups,
.sysfs_ops = &f2fs_tune_attr_ops,
+ /*
+ * Pre-existing: f2fs_tune is a static struct kobject; lifetime
+ * is not controlled by kobject_put().
+ */
+ .release = NULL,
};
static struct kobject f2fs_tune = {
diff --git a/fs/ocfs2/cluster/masklog.c b/fs/ocfs2/cluster/masklog.c
index 563881ddbf00c8..ff8a1cf51e72f7 100644
--- a/fs/ocfs2/cluster/masklog.c
+++ b/fs/ocfs2/cluster/masklog.c
@@ -147,6 +147,11 @@ static const struct sysfs_ops mlog_attr_ops = {
static struct kobj_type mlog_ktype = {
.default_groups = mlog_default_groups,
.sysfs_ops = &mlog_attr_ops,
+ /*
+ * Pre-existing: mlog_kset is a static struct kset; lifetime
+ * is not controlled by kobject_put().
+ */
+ .release = NULL,
};
static struct kset mlog_kset = {
diff --git a/fs/ubifs/sysfs.c b/fs/ubifs/sysfs.c
index dbf967dcf26e66..e20931e3a62f96 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);
}
diff --git a/include/linux/compiler_attributes.h b/include/linux/compiler_attributes.h
index 476c4c560d1743..b9c0b56dd22e79 100644
--- a/include/linux/compiler_attributes.h
+++ b/include/linux/compiler_attributes.h
@@ -322,6 +322,18 @@
*/
#define __pure __attribute__((__pure__))
+/*
+ * Optional: not supported by gcc
+ * Optional: only supported since clang >= 20.0
+ *
+ * clang: https://clang.llvm.org/docs/AttributeReference.html#require-explicit-initialization
+ */
+#if __has_attribute(__require_explicit_initialization__)
+# define __must_init __attribute__((__require_explicit_initialization__))
+#else
+# define __must_init
+#endif
+
/*
* gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-section-function-attribute
* gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attributes.html#index-section-variable-attribute
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 55e37a5d405ef7..8a133203088477 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -114,7 +114,7 @@ void kobject_get_ownership(const struct kobject *kobj, kuid_t *uid, kgid_t *gid)
char *kobject_get_path(const struct kobject *kobj, gfp_t flag);
struct kobj_type {
- void (*release)(struct kobject *kobj);
+ void (*release)(struct kobject *kobj) __must_init;
const struct sysfs_ops *sysfs_ops;
const struct attribute_group **default_groups;
const struct kobj_ns_type_operations *(*child_ns_type)(const struct kobject *kobj);
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index c9840f5219c2a9..5232f66d2b80f1 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -6860,6 +6860,7 @@ sub process {
"noreturn" => "__noreturn",
"packed" => "__packed",
"pure" => "__pure",
+ "require_explicit_initialization" => "__must_init",
"section" => "__section",
"used" => "__used",
"weak" => "__weak"
diff --git a/tools/lib/python/kdoc/xforms_lists.py b/tools/lib/python/kdoc/xforms_lists.py
index 320f977c5bac2c..3c744cbd2f34f7 100644
--- a/tools/lib/python/kdoc/xforms_lists.py
+++ b/tools/lib/python/kdoc/xforms_lists.py
@@ -36,6 +36,7 @@ class CTransforms:
(CMatch("CRYPTO_MINALIGN_ATTR"), ""),
(CMatch("__private"), ""),
(CMatch("__rcu"), ""),
+ (CMatch("__must_init"), ""),
(CMatch("____cacheline_aligned_in_smp"), ""),
(CMatch("____cacheline_aligned"), ""),
(CMatch("__cacheline_group_(?:begin|end)"), ""),
|
| 41/3 | 2026/10/28 06:24 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 13579 output: 274 thoughts: 2634 Thoughts: **KMSAN Assessment: No Need for Dedicated Fuzzing Session** Okay, I need to decide if this patch series warrants a dedicated KMSAN fuzzing run. Let's break it down. It looks like the main purpose is to enforce explicit initialization of the `.release` field in `struct kobj_type` using a compiler attribute, `__must_init`. This attribute, implemented using Clang's `__attribute__((__require_explicit_initialization__))`, is essentially a compile-time check. The series also cleans up some kobject lifetime and memory management issues along the way, likely to satisfy this new requirement. Looking through the patches, I see a consistent pattern: adding `.release = NULL` or `.release = <release_function>` to various `struct kobj_type` initializations, and occasionally fixing issues related to object lifetimes. For example, the `kfd_procfs_*` changes are about ensuring proper `kobject_put()` calls and release, the DLM patch adds a completion to synchronize kobject release, and the UBIFS patch changes from a static `ubifs_kset` to dynamic allocation using `kset_create_and_add()`. Crucially, I don't see anything that directly introduces or alters risks that KMSAN is designed to catch. This isn't about uninitialized memory in code paths that send data to userspace (`copy_to_user`, ioctls, etc.). The `__must_init` attribute *forces* developers to explicitly initialize that release callback. The static initialization of structs in C guarantees zero-initialization of omitted fields. The primary goal is improved code cleanliness and robustness, with respect to object lifetime management. Any bugs in that lifetime management (use-after-free, double-free) are squarely caught by KASAN and the standard kobject release debugging features (CONFIG_DEBUG_KOBJECT_RELEASE). Therefore, this patch series doesn't seem to introduce or expose uninitialized memory reads or kernel-to-user information leaks. It's more about improving kobject lifetime. KMSAN is irrelevant here. The KMSAN reasoning is that KMSAN detects uninitialized memory reads and kernel-to-user info leaks. This patch series introduces a compile-time check, `__must_init`, and cleans up kobject lifetimes. These changes address object lifecycle, reference counting, and use-after-free/leak issues. Any lifetime issues (such as use-after-free or premature destruction) are detected by KASAN and standard debuggers, not KMSAN. There are no uninitialized heap/stack memory reads, buffer length manipulations, and no kernel-to-user data leaks introduced or modified. KMSAN is not applicable. I'll set NeedsKMSAN = false. |
| 42/3 | 2026/10/28 06:24 | tool | set-results |
0mArgs:{
"KMSANReasoning": "The patch series introduces a new compile-time attribute `__must_init` (using Clang's `__require_explicit_initialization__` attribute) on `struct kobj_type.release` to require explicit initialization of the kobject release callback. In order to comply with this requirement and address kobject lifecycle issues, the patch adds explicit `.release` entries (either `NULL` for embedded/static kobjects or proper cleanup callbacks) and refactors kobject lifecycle handling in several subsystems (e.g., amdkfd queue release, DLM lockspace completion on release, and dynamic allocation of ubifs_kset).\n\nThese changes purely involve compile-time attribute validation and runtime kobject reference counting and object lifecycle management. Potential bugs arising from these changes (such as use-after-free, double free, or invalid refcounting) are within the domain of KASAN, refcount tracking, and CONFIG_DEBUG_KOBJECT_RELEASE. The patch does not introduce or modify any uninitialized memory reads, uninitialized struct fields, bounds/length calculations on raw memory buffers, or kernel-to-user information copies. Therefore, a dedicated KMSAN fuzzing session is not warranted.",
"NeedsKMSAN": false
}Results: {
"KMSANReasoning": "The patch series introduces a new compile-time attribute `__must_init` (using Clang's `__require_explicit_initialization__` attribute) on `struct kobj_type.release` to require explicit initialization of the kobject release callback. In order to comply with this requirement and address kobject lifecycle issues, the patch adds explicit `.release` entries (either `NULL` for embedded/static kobjects or proper cleanup callbacks) and refactors kobject lifecycle handling in several subsystems (e.g., amdkfd queue release, DLM lockspace completion on release, and dynamic allocation of ubifs_kset).\n\nThese changes purely involve compile-time attribute validation and runtime kobject reference counting and object lifecycle management. Potential bugs arising from these changes (such as use-after-free, double free, or invalid refcounting) are within the domain of KASAN, refcount tracking, and CONFIG_DEBUG_KOBJECT_RELEASE. The patch does not introduce or modify any uninitialized memory reads, uninitialized struct fields, bounds/length calculations on raw memory buffers, or kernel-to-user information copies. Therefore, a dedicated KMSAN fuzzing session is not warranted.",
"NeedsKMSAN": false
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|