1 From f5d17a89c386b9e711ab3bb535bb343becb75223 Mon Sep 17 00:00:00 2001
2 From: Aaron Hill <aa1ronham@gmail.com>
3 Date: Mon, 24 Dec 2018 14:23:36 -0500
4 Subject: drivers: thermal: int340x_thermal: Fix sysfs race condition
6 [ Upstream commit 129699bb8c7572106b5bbb2407c2daee4727ccad ]
9 * Use dev_info instead of printk
10 * Use dev_warn instead of BUG_ON
12 Previously, sysfs_create_group was called before all initialization had
13 fully run - specifically, before pci_set_drvdata was called. Since the
14 sysctl group is visible to userspace as soon as sysfs_create_group
15 returns, a small window of time existed during which a process could read
16 from an uninitialized/partially-initialized device.
18 This commit moves the creation of the sysctl group to after all
19 initialized is completed. This ensures that it's impossible for
20 userspace to read from a sysctl file before initialization has fully
23 To catch any future regressions, I've added a check to ensure
24 that proc_thermal_emum_mode is never PROC_THERMAL_NONE when a process
25 tries to read from a sysctl file. Previously, the aforementioned race
26 condition could result in the 'else' branch
27 running while PROC_THERMAL_NONE was set,
28 leading to a null pointer deference.
30 Signed-off-by: Aaron Hill <aa1ronham@gmail.com>
31 Signed-off-by: Zhang Rui <rui.zhang@intel.com>
32 Signed-off-by: Sasha Levin <sashal@kernel.org>
34 .../processor_thermal_device.c | 28 ++++++++++---------
35 1 file changed, 15 insertions(+), 13 deletions(-)
37 diff --git a/drivers/thermal/int340x_thermal/processor_thermal_device.c b/drivers/thermal/int340x_thermal/processor_thermal_device.c
38 index 06d46e2ff337e..1fdf6fd24cdff 100644
39 --- a/drivers/thermal/int340x_thermal/processor_thermal_device.c
40 +++ b/drivers/thermal/int340x_thermal/processor_thermal_device.c
41 @@ -77,7 +77,12 @@ static ssize_t power_limit_##index##_##suffix##_show(struct device *dev, \
42 struct pci_dev *pci_dev; \
43 struct platform_device *pdev; \
44 struct proc_thermal_device *proc_dev; \
47 + if (proc_thermal_emum_mode == PROC_THERMAL_NONE) { \
48 + dev_warn(dev, "Attempted to get power limit before device was initialized!\n"); \
52 if (proc_thermal_emum_mode == PROC_THERMAL_PLATFORM_DEV) { \
53 pdev = to_platform_device(dev); \
54 proc_dev = platform_get_drvdata(pdev); \
55 @@ -291,11 +296,6 @@ static int proc_thermal_add(struct device *dev,
58 ret = proc_thermal_read_ppcc(proc_priv);
60 - ret = sysfs_create_group(&dev->kobj,
61 - &power_limit_attribute_group);
67 @@ -309,8 +309,7 @@ static int proc_thermal_add(struct device *dev,
69 proc_priv->int340x_zone = int340x_thermal_zone_add(adev, ops);
70 if (IS_ERR(proc_priv->int340x_zone)) {
71 - ret = PTR_ERR(proc_priv->int340x_zone);
73 + return PTR_ERR(proc_priv->int340x_zone);
77 @@ -324,9 +323,6 @@ static int proc_thermal_add(struct device *dev,
80 int340x_thermal_zone_remove(proc_priv->int340x_zone);
82 - sysfs_remove_group(&proc_priv->dev->kobj,
83 - &power_limit_attribute_group);
87 @@ -357,7 +353,10 @@ static int int3401_add(struct platform_device *pdev)
88 platform_set_drvdata(pdev, proc_priv);
89 proc_thermal_emum_mode = PROC_THERMAL_PLATFORM_DEV;
92 + dev_info(&pdev->dev, "Creating sysfs group for PROC_THERMAL_PLATFORM_DEV\n");
94 + return sysfs_create_group(&pdev->dev.kobj,
95 + &power_limit_attribute_group);
98 static int int3401_remove(struct platform_device *pdev)
99 @@ -434,7 +433,10 @@ static int proc_thermal_pci_probe(struct pci_dev *pdev,
100 dev_err(&pdev->dev, "No auxiliary DTSs enabled\n");
104 + dev_info(&pdev->dev, "Creating sysfs group for PROC_THERMAL_PCI\n");
106 + return sysfs_create_group(&pdev->dev.kobj,
107 + &power_limit_attribute_group);
110 static void proc_thermal_pci_remove(struct pci_dev *pdev)