Skip to content

Commit 5bc9de0

Browse files
committed
drm/i915/hwmon: Get rid of devm
When both hwmon and hwmon drvdata (on which hwmon depends) are device managed resources, the expectation, on device unbind, is that hwmon will be released before drvdata. However, in i915 there are two separate code paths, which both release either drvdata or hwmon and either can be released before the other. These code paths (for device unbind) are as follows (see also the bug referenced below): Call Trace: release_nodes+0x11/0x70 devres_release_group+0xb2/0x110 component_unbind_all+0x8d/0xa0 component_del+0xa5/0x140 intel_pxp_tee_component_fini+0x29/0x40 [i915] intel_pxp_fini+0x33/0x80 [i915] i915_driver_remove+0x4c/0x120 [i915] i915_pci_remove+0x19/0x30 [i915] pci_device_remove+0x32/0xa0 device_release_driver_internal+0x19c/0x200 unbind_store+0x9c/0xb0 and Call Trace: release_nodes+0x11/0x70 devres_release_all+0x8a/0xc0 device_unbind_cleanup+0x9/0x70 device_release_driver_internal+0x1c1/0x200 unbind_store+0x9c/0xb0 This means that in i915, if use devm, we cannot gurantee that hwmon will always be released before drvdata. Which means that we have a uaf if hwmon sysfs is accessed when drvdata has been released but hwmon hasn't. The only way out of this seems to be do get rid of devm_ and release/free everything explicitly during device unbind. v2: Change commit message and other minor code changes v3: Cleanup from i915_hwmon_register on error (Armin Wolf) v4: Eliminate potential static analyzer warning (Rodrigo) Eliminate fetch_and_zero (Jani) v5: Restore previous logic for ddat_gt->hwmon_dev error return (Andi) Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/10366 Reviewed-by: Rodrigo Vivi <[email protected]> Signed-off-by: Ashutosh Dixit <[email protected]> Reviewed-by: Andi Shyti <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent c086bfc commit 5bc9de0

File tree

1 file changed

+32
-14
lines changed

1 file changed

+32
-14
lines changed

drivers/gpu/drm/i915/i915_hwmon.c

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -793,7 +793,7 @@ void i915_hwmon_register(struct drm_i915_private *i915)
793793
if (!IS_DGFX(i915))
794794
return;
795795

796-
hwmon = devm_kzalloc(dev, sizeof(*hwmon), GFP_KERNEL);
796+
hwmon = kzalloc(sizeof(*hwmon), GFP_KERNEL);
797797
if (!hwmon)
798798
return;
799799

@@ -819,14 +819,12 @@ void i915_hwmon_register(struct drm_i915_private *i915)
819819
hwm_get_preregistration_info(i915);
820820

821821
/* hwmon_dev points to device hwmon<i> */
822-
hwmon_dev = devm_hwmon_device_register_with_info(dev, ddat->name,
823-
ddat,
824-
&hwm_chip_info,
825-
hwm_groups);
826-
if (IS_ERR(hwmon_dev)) {
827-
i915->hwmon = NULL;
828-
return;
829-
}
822+
hwmon_dev = hwmon_device_register_with_info(dev, ddat->name,
823+
ddat,
824+
&hwm_chip_info,
825+
hwm_groups);
826+
if (IS_ERR(hwmon_dev))
827+
goto err;
830828

831829
ddat->hwmon_dev = hwmon_dev;
832830

@@ -839,16 +837,36 @@ void i915_hwmon_register(struct drm_i915_private *i915)
839837
if (!hwm_gt_is_visible(ddat_gt, hwmon_energy, hwmon_energy_input, 0))
840838
continue;
841839

842-
hwmon_dev = devm_hwmon_device_register_with_info(dev, ddat_gt->name,
843-
ddat_gt,
844-
&hwm_gt_chip_info,
845-
NULL);
840+
hwmon_dev = hwmon_device_register_with_info(dev, ddat_gt->name,
841+
ddat_gt,
842+
&hwm_gt_chip_info,
843+
NULL);
846844
if (!IS_ERR(hwmon_dev))
847845
ddat_gt->hwmon_dev = hwmon_dev;
848846
}
847+
return;
848+
err:
849+
i915_hwmon_unregister(i915);
849850
}
850851

851852
void i915_hwmon_unregister(struct drm_i915_private *i915)
852853
{
853-
fetch_and_zero(&i915->hwmon);
854+
struct i915_hwmon *hwmon = i915->hwmon;
855+
struct intel_gt *gt;
856+
int i;
857+
858+
if (!hwmon)
859+
return;
860+
861+
for_each_gt(gt, i915, i)
862+
if (hwmon->ddat_gt[i].hwmon_dev)
863+
hwmon_device_unregister(hwmon->ddat_gt[i].hwmon_dev);
864+
865+
if (hwmon->ddat.hwmon_dev)
866+
hwmon_device_unregister(hwmon->ddat.hwmon_dev);
867+
868+
mutex_destroy(&hwmon->hwmon_lock);
869+
870+
kfree(i915->hwmon);
871+
i915->hwmon = NULL;
854872
}

0 commit comments

Comments
 (0)