Skip to contentSkip to conversation

cpufreq: qcom-cpufreq-hw: Avoid stack buffer for IRQ name

PATCH In review Ard Biesheuvel 5 participants 5 messages Sep 1, 2021 – Dec 20, 2021

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

PATCH 1/1 cpufreq: qcom-cpufreq-hw: Avoid stack buffer for IRQ name

Registering an IRQ requires the string buffer containing the name to remain allocated, as the name is not copied into another buffer.

So let's add a irq_name field to the data struct instead, which is guaranteed to have the appropriate lifetime.

Cc Thara Gopinath <[email protected]>
Cc Bjorn Andersson <[email protected]>
Cc Andy Gross <[email protected]>

---
I'm not following msm development closely, so apologies if this was already fixed, or if this is not based on the right tree.

This fixes a crash on my Yoga C630 when reading /proc/interrupts.

 drivers/cpufreq/qcom-cpufreq-hw.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/cpufreq/qcom-cpufreq-hw.c +4 -4
index 3cc27d9e2ed1..6613228fe68c 100644
@@ -44,6 +44,7 @@ struct qcom_cpufreq_data {
 	/* Lock to synchronize between de-init sequence and re-starting LMh polling/interrupts */
 	spinlock_t throttle_lock;
 	int throttle_irq;
+	char irq_name[15];
 	bool cancel_throttle;
 };
 
@@ -371,7 +372,6 @@ static int qcom_cpufreq_hw_lmh_init(struct cpufreq_policy *policy, int index)
 {
 	struct qcom_cpufreq_data *data = policy->driver_data;
 	struct platform_device *pdev = cpufreq_get_driver_data();
-	char irq_name[15];
 	int ret;
 
 	/*
@@ -388,11 +388,11 @@ static int qcom_cpufreq_hw_lmh_init(struct cpufreq_policy *policy, int index)
 	spin_lock_init(&data->throttle_lock);
 	INIT_DEFERRABLE_WORK(&data->throttle_work, qcom_lmh_dcvs_poll);
 
-	snprintf(irq_name, sizeof(irq_name), "dcvsh-irq-%u", policy->cpu);
+	snprintf(data->irq_name, sizeof(data->irq_name), "dcvsh-irq-%u", policy->cpu);
 	ret = request_threaded_irq(data->throttle_irq, NULL, qcom_lmh_dcvs_handle_irq,
-				   IRQF_ONESHOT, irq_name, data);
+				   IRQF_ONESHOT, data->irq_name, data);
 	if (ret) {
-		dev_err(&pdev->dev, "Error registering %s: %d\n", irq_name, ret);
+		dev_err(&pdev->dev, "Error registering %s: %d\n", data->irq_name, ret);
 		return 0;
 	}
 
Signature · 1 line
2.30.2
Tested-by on v1 1/1
#1 lore raw
Quoted 45 lines · Ard Biesheuvel

Registering an IRQ requires the string buffer containing the name to remain allocated, as the name is not copied into another buffer.

So let's add a irq_name field to the data struct instead, which is guaranteed to have the appropriate lifetime.

Cc Thara Gopinath <[email protected]>
Cc Bjorn Andersson <[email protected]>
Cc Andy Gross <[email protected]>

---
I'm not following msm development closely, so apologies if this was already fixed, or if this is not based on the right tree.

This fixes a crash on my Yoga C630 when reading /proc/interrupts.

 drivers/cpufreq/qcom-cpufreq-hw.c | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)
drivers/cpufreq/qcom-cpufreq-hw.c +1 -2
index 3cc27d9e2ed1..6613228fe68c 100644
@@ -44,6 +44,7 @@ struct qcom_cpufreq_data {
 	/* Lock to synchronize between de-init sequence and re-starting LMh polling/interrupts */
 	spinlock_t throttle_lock;
 	int throttle_irq;
+	char irq_name[15];
 	bool cancel_throttle;
 };
 
@@ -371,7 +372,6 @@ static int qcom_cpufreq_hw_lmh_init(struct cpufreq_policy *policy, int index)
 {
 	struct qcom_cpufreq_data *data = policy->driver_data;
 	struct platform_device *pdev = cpufreq_get_driver_data();
-	char irq_name[15];
 	int ret;
 
 	/*
@@ -388,11 +388,11 @@ static int qcom_cpufreq_hw_lmh_init(struct cpufreq_policy *policy, int index)
 	spin_lock_init(&data->throttle_lock);
 	INIT_DEFERRABLE_WORK(&data->throttle_work, qcom_lmh_dcvs_poll);
 
-	snprintf(irq_name, sizeof(irq_name), "dcvsh-irq-%u", policy->cpu);

drivers/cpufreq/qcom-cpufreq-hw.c static int qcom_cpufreq_hw_lmh_init(struct cpufreq_policy *policy, int index) · line 398

Quoted 10 lines
drivers/cpufreq/qcom-cpufreq-hw.c +3 -2
+	snprintf(data->irq_name, sizeof(data->irq_name), "dcvsh-irq-%u", policy->cpu);
 	ret = request_threaded_irq(data->throttle_irq, NULL, qcom_lmh_dcvs_handle_irq,
-				   IRQF_ONESHOT, irq_name, data);
+				   IRQF_ONESHOT, data->irq_name, data);
 	if (ret) {
-		dev_err(&pdev->dev, "Error registering %s: %d\n", irq_name, ret);
+		dev_err(&pdev->dev, "Error registering %s: %d\n", data->irq_name, ret);
 		return 0;
 	}
 

I haven't experienced the crash here, but I also tested the patch on my C630, and still don't see the issue so, if you want:

Reviewed-by on v1 1/1
#2 lore raw
In reply to Ard Biesheuvel
Quoted 11 lines · Ard Biesheuvel

Registering an IRQ requires the string buffer containing the name to remain allocated, as the name is not copied into another buffer.

So let's add a irq_name field to the data struct instead, which is guaranteed to have the appropriate lifetime.

Cc Thara Gopinath <[email protected]>
Cc Bjorn Andersson <[email protected]>
Cc Andy Gross <[email protected]>

Thanks for the fix.

Signature · 2 lines
Warm Regards
Thara (She/Her/Hers)
Quoted 45 lines

---
I'm not following msm development closely, so apologies if this was already fixed, or if this is not based on the right tree.

This fixes a crash on my Yoga C630 when reading /proc/interrupts.

  drivers/cpufreq/qcom-cpufreq-hw.c | 8 ++++----
  1 file changed, 4 insertions(+), 4 deletions(-)
drivers/cpufreq/qcom-cpufreq-hw.c +4 -4
index 3cc27d9e2ed1..6613228fe68c 100644
@@ -44,6 +44,7 @@ struct qcom_cpufreq_data {
  	/* Lock to synchronize between de-init sequence and re-starting LMh polling/interrupts */
  	spinlock_t throttle_lock;
  	int throttle_irq;
+	char irq_name[15];
  	bool cancel_throttle;
  };
 
@@ -371,7 +372,6 @@ static int qcom_cpufreq_hw_lmh_init(struct cpufreq_policy *policy, int index)
  {
  	struct qcom_cpufreq_data *data = policy->driver_data;
  	struct platform_device *pdev = cpufreq_get_driver_data();
-	char irq_name[15];
  	int ret;
 
  	/*
@@ -388,11 +388,11 @@ static int qcom_cpufreq_hw_lmh_init(struct cpufreq_policy *policy, int index)
  	spin_lock_init(&data->throttle_lock);
  	INIT_DEFERRABLE_WORK(&data->throttle_work, qcom_lmh_dcvs_poll);
 
-	snprintf(irq_name, sizeof(irq_name), "dcvsh-irq-%u", policy->cpu);
+	snprintf(data->irq_name, sizeof(data->irq_name), "dcvsh-irq-%u", policy->cpu);
  	ret = request_threaded_irq(data->throttle_irq, NULL, qcom_lmh_dcvs_handle_irq,
-				   IRQF_ONESHOT, irq_name, data);
+				   IRQF_ONESHOT, data->irq_name, data);
  	if (ret) {
-		dev_err(&pdev->dev, "Error registering %s: %d\n", irq_name, ret);
+		dev_err(&pdev->dev, "Error registering %s: %d\n", data->irq_name, ret);
  		return 0;
  	}
 
#3 lore raw
Quoted 13 lines · Ard Biesheuvel
Quoted 11 lines

Registering an IRQ requires the string buffer containing the name to remain allocated, as the name is not copied into another buffer.

So let's add a irq_name field to the data struct instead, which is guaranteed to have the appropriate lifetime.

Cc Thara Gopinath <[email protected]>
Cc Bjorn Andersson <[email protected]>
Cc Andy Gross <[email protected]>
Quoted 3 lines

Thanks for the fix.

Seems this patch has been overlooked. Would it be possible to resubmit it with a 'Fixes' tag?

Regards,
Loic

#4 lore raw
Quoted 13 lines · Loic Poulain
Quoted 13 lines · Ard Biesheuvel
Quoted 11 lines

Registering an IRQ requires the string buffer containing the name to remain allocated, as the name is not copied into another buffer.

So let's add a irq_name field to the data struct instead, which is guaranteed to have the appropriate lifetime.

Cc Thara Gopinath <[email protected]>
Cc Bjorn Andersson <[email protected]>
Cc Andy Gross <[email protected]>
Quoted 7 lines
Quoted 3 lines

Thanks for the fix.

Seems this patch has been overlooked. Would it be possible to resubmit it with a 'Fixes' tag?

This was resubmitted by Vladimir and Viresh replied that it's applied, see:

https://lore.kernel.org/all/20211125065014.phkfugo2wptosrgv@vireshk-i7/

Regards,
Bjorn