All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] iommu/arm-smmu: Fix arm_smmu_device refcount leak when arm_smmu_rpm_get fails
@ 2021-06-09 13:35 ` Xiyu Yang via iommu
  0 siblings, 0 replies; 9+ messages in thread
From: Xiyu Yang @ 2021-06-09 13:35 UTC (permalink / raw)
  To: Will Deacon, Robin Murphy, Joerg Roedel, Nicolin Chen,
	Bjorn Andersson, Krishna Reddy, Jordan Crouse,
	Sai Prakash Ranjan, linux-arm-kernel, iommu, linux-kernel
  Cc: yuanxzhang, Xiyu Yang, Xin Tan

arm_smmu_rpm_get() invokes pm_runtime_get_sync(), which increases the
refcount of the "smmu" even though the return value is less than 0.

The reference counting issue happens in some error handling paths of
arm_smmu_rpm_get() in its caller functions. When arm_smmu_rpm_get()
fails, the caller functions forget to decrease the refcount of "smmu"
increased by arm_smmu_rpm_get(), causing a refcount leak.

Fix this issue by calling arm_smmu_rpm_put() or jumping to the "rpm_put"
label when arm_smmu_rpm_get() fails.

Signed-off-by: Xiyu Yang <xiyuyang19@fudan.edu.cn>
Signed-off-by: Xin Tan <tanxin.ctf@gmail.com>
---
 drivers/iommu/arm/arm-smmu/arm-smmu.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index 6f72c4d208ca..177ee54c5534 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -840,7 +840,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
 
 	ret = arm_smmu_rpm_get(smmu);
 	if (ret < 0)
-		return;
+		goto rpm_put;
 
 	/*
 	 * Disable the context bank and free the page tables before freeing
@@ -857,6 +857,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
 	free_io_pgtable_ops(smmu_domain->pgtbl_ops);
 	__arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx);
 
+rpm_put:
 	arm_smmu_rpm_put(smmu);
 }
 
@@ -1153,7 +1154,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
 
 	ret = arm_smmu_rpm_get(smmu);
 	if (ret < 0)
-		return ret;
+		goto rpm_put;
 
 	/* Ensure that the domain is finalised */
 	ret = arm_smmu_init_domain_context(domain, smmu, dev);
@@ -1404,7 +1405,7 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
 
 	ret = arm_smmu_rpm_get(smmu);
 	if (ret < 0)
-		goto out_cfg_free;
+		goto rpm_put;
 
 	ret = arm_smmu_master_alloc_smes(dev);
 	arm_smmu_rpm_put(smmu);
@@ -1417,6 +1418,8 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
 
 	return &smmu->iommu;
 
+rpm_put:
+	arm_smmu_rpm_put(smmu);
 out_cfg_free:
 	kfree(cfg);
 out_free:
@@ -1438,8 +1441,10 @@ static void arm_smmu_release_device(struct device *dev)
 	smmu = cfg->smmu;
 
 	ret = arm_smmu_rpm_get(smmu);
-	if (ret < 0)
+	if (ret < 0) {
+		arm_smmu_rpm_put(smmu);
 		return;
+	}
 
 	arm_smmu_master_free_smes(cfg, fwspec);
 
-- 
2.7.4


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

* [PATCH] iommu/arm-smmu: Fix arm_smmu_device refcount leak when arm_smmu_rpm_get fails
@ 2021-06-09 13:35 ` Xiyu Yang via iommu
  0 siblings, 0 replies; 9+ messages in thread
From: Xiyu Yang via iommu @ 2021-06-09 13:35 UTC (permalink / raw)
  To: Will Deacon, Robin Murphy, Joerg Roedel, Nicolin Chen,
	Bjorn Andersson, Krishna Reddy, Jordan Crouse,
	Sai Prakash Ranjan, linux-arm-kernel, iommu, linux-kernel
  Cc: Xin Tan, yuanxzhang, Xiyu Yang

arm_smmu_rpm_get() invokes pm_runtime_get_sync(), which increases the
refcount of the "smmu" even though the return value is less than 0.

The reference counting issue happens in some error handling paths of
arm_smmu_rpm_get() in its caller functions. When arm_smmu_rpm_get()
fails, the caller functions forget to decrease the refcount of "smmu"
increased by arm_smmu_rpm_get(), causing a refcount leak.

Fix this issue by calling arm_smmu_rpm_put() or jumping to the "rpm_put"
label when arm_smmu_rpm_get() fails.

Signed-off-by: Xiyu Yang <xiyuyang19@fudan.edu.cn>
Signed-off-by: Xin Tan <tanxin.ctf@gmail.com>
---
 drivers/iommu/arm/arm-smmu/arm-smmu.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index 6f72c4d208ca..177ee54c5534 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -840,7 +840,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
 
 	ret = arm_smmu_rpm_get(smmu);
 	if (ret < 0)
-		return;
+		goto rpm_put;
 
 	/*
 	 * Disable the context bank and free the page tables before freeing
@@ -857,6 +857,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
 	free_io_pgtable_ops(smmu_domain->pgtbl_ops);
 	__arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx);
 
+rpm_put:
 	arm_smmu_rpm_put(smmu);
 }
 
@@ -1153,7 +1154,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
 
 	ret = arm_smmu_rpm_get(smmu);
 	if (ret < 0)
-		return ret;
+		goto rpm_put;
 
 	/* Ensure that the domain is finalised */
 	ret = arm_smmu_init_domain_context(domain, smmu, dev);
@@ -1404,7 +1405,7 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
 
 	ret = arm_smmu_rpm_get(smmu);
 	if (ret < 0)
-		goto out_cfg_free;
+		goto rpm_put;
 
 	ret = arm_smmu_master_alloc_smes(dev);
 	arm_smmu_rpm_put(smmu);
@@ -1417,6 +1418,8 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
 
 	return &smmu->iommu;
 
+rpm_put:
+	arm_smmu_rpm_put(smmu);
 out_cfg_free:
 	kfree(cfg);
 out_free:
@@ -1438,8 +1441,10 @@ static void arm_smmu_release_device(struct device *dev)
 	smmu = cfg->smmu;
 
 	ret = arm_smmu_rpm_get(smmu);
-	if (ret < 0)
+	if (ret < 0) {
+		arm_smmu_rpm_put(smmu);
 		return;
+	}
 
 	arm_smmu_master_free_smes(cfg, fwspec);
 
-- 
2.7.4

_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

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

* [PATCH] iommu/arm-smmu: Fix arm_smmu_device refcount leak when arm_smmu_rpm_get fails
@ 2021-06-09 13:35 ` Xiyu Yang via iommu
  0 siblings, 0 replies; 9+ messages in thread
From: Xiyu Yang @ 2021-06-09 13:35 UTC (permalink / raw)
  To: Will Deacon, Robin Murphy, Joerg Roedel, Nicolin Chen,
	Bjorn Andersson, Krishna Reddy, Jordan Crouse,
	Sai Prakash Ranjan, linux-arm-kernel, iommu, linux-kernel
  Cc: yuanxzhang, Xiyu Yang, Xin Tan

arm_smmu_rpm_get() invokes pm_runtime_get_sync(), which increases the
refcount of the "smmu" even though the return value is less than 0.

The reference counting issue happens in some error handling paths of
arm_smmu_rpm_get() in its caller functions. When arm_smmu_rpm_get()
fails, the caller functions forget to decrease the refcount of "smmu"
increased by arm_smmu_rpm_get(), causing a refcount leak.

Fix this issue by calling arm_smmu_rpm_put() or jumping to the "rpm_put"
label when arm_smmu_rpm_get() fails.

Signed-off-by: Xiyu Yang <xiyuyang19@fudan.edu.cn>
Signed-off-by: Xin Tan <tanxin.ctf@gmail.com>
---
 drivers/iommu/arm/arm-smmu/arm-smmu.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index 6f72c4d208ca..177ee54c5534 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -840,7 +840,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
 
 	ret = arm_smmu_rpm_get(smmu);
 	if (ret < 0)
-		return;
+		goto rpm_put;
 
 	/*
 	 * Disable the context bank and free the page tables before freeing
@@ -857,6 +857,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
 	free_io_pgtable_ops(smmu_domain->pgtbl_ops);
 	__arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx);
 
+rpm_put:
 	arm_smmu_rpm_put(smmu);
 }
 
@@ -1153,7 +1154,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
 
 	ret = arm_smmu_rpm_get(smmu);
 	if (ret < 0)
-		return ret;
+		goto rpm_put;
 
 	/* Ensure that the domain is finalised */
 	ret = arm_smmu_init_domain_context(domain, smmu, dev);
@@ -1404,7 +1405,7 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
 
 	ret = arm_smmu_rpm_get(smmu);
 	if (ret < 0)
-		goto out_cfg_free;
+		goto rpm_put;
 
 	ret = arm_smmu_master_alloc_smes(dev);
 	arm_smmu_rpm_put(smmu);
@@ -1417,6 +1418,8 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
 
 	return &smmu->iommu;
 
+rpm_put:
+	arm_smmu_rpm_put(smmu);
 out_cfg_free:
 	kfree(cfg);
 out_free:
@@ -1438,8 +1441,10 @@ static void arm_smmu_release_device(struct device *dev)
 	smmu = cfg->smmu;
 
 	ret = arm_smmu_rpm_get(smmu);
-	if (ret < 0)
+	if (ret < 0) {
+		arm_smmu_rpm_put(smmu);
 		return;
+	}
 
 	arm_smmu_master_free_smes(cfg, fwspec);
 
-- 
2.7.4


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: [PATCH] iommu/arm-smmu: Fix arm_smmu_device refcount leak when arm_smmu_rpm_get fails
  2021-06-09 13:35 ` Xiyu Yang via iommu
  (?)
@ 2021-06-09 14:12   ` Robin Murphy
  -1 siblings, 0 replies; 9+ messages in thread
From: Robin Murphy @ 2021-06-09 14:12 UTC (permalink / raw)
  To: Xiyu Yang, Will Deacon, Joerg Roedel, Nicolin Chen,
	Bjorn Andersson, Krishna Reddy, Jordan Crouse,
	Sai Prakash Ranjan, linux-arm-kernel, iommu, linux-kernel
  Cc: yuanxzhang, Xin Tan

On 2021-06-09 14:35, Xiyu Yang wrote:
> arm_smmu_rpm_get() invokes pm_runtime_get_sync(), which increases the
> refcount of the "smmu" even though the return value is less than 0.
> 
> The reference counting issue happens in some error handling paths of
> arm_smmu_rpm_get() in its caller functions. When arm_smmu_rpm_get()
> fails, the caller functions forget to decrease the refcount of "smmu"
> increased by arm_smmu_rpm_get(), causing a refcount leak.
> 
> Fix this issue by calling arm_smmu_rpm_put() or jumping to the "rpm_put"
> label when arm_smmu_rpm_get() fails.

If only there was some kind of helper function which could encapsulate 
the correct expected behaviour in a single place...

In fact with the new pm_runtime_resume_and_get() API I think these two 
patches boil down to a one-line change.

Thanks,
Robin.

> Signed-off-by: Xiyu Yang <xiyuyang19@fudan.edu.cn>
> Signed-off-by: Xin Tan <tanxin.ctf@gmail.com>
> ---
>   drivers/iommu/arm/arm-smmu/arm-smmu.c | 13 +++++++++----
>   1 file changed, 9 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> index 6f72c4d208ca..177ee54c5534 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> @@ -840,7 +840,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
>   
>   	ret = arm_smmu_rpm_get(smmu);
>   	if (ret < 0)
> -		return;
> +		goto rpm_put;
>   
>   	/*
>   	 * Disable the context bank and free the page tables before freeing
> @@ -857,6 +857,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
>   	free_io_pgtable_ops(smmu_domain->pgtbl_ops);
>   	__arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx);
>   
> +rpm_put:
>   	arm_smmu_rpm_put(smmu);
>   }
>   
> @@ -1153,7 +1154,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
>   
>   	ret = arm_smmu_rpm_get(smmu);
>   	if (ret < 0)
> -		return ret;
> +		goto rpm_put;
>   
>   	/* Ensure that the domain is finalised */
>   	ret = arm_smmu_init_domain_context(domain, smmu, dev);
> @@ -1404,7 +1405,7 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
>   
>   	ret = arm_smmu_rpm_get(smmu);
>   	if (ret < 0)
> -		goto out_cfg_free;
> +		goto rpm_put;
>   
>   	ret = arm_smmu_master_alloc_smes(dev);
>   	arm_smmu_rpm_put(smmu);
> @@ -1417,6 +1418,8 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
>   
>   	return &smmu->iommu;
>   
> +rpm_put:
> +	arm_smmu_rpm_put(smmu);
>   out_cfg_free:
>   	kfree(cfg);
>   out_free:
> @@ -1438,8 +1441,10 @@ static void arm_smmu_release_device(struct device *dev)
>   	smmu = cfg->smmu;
>   
>   	ret = arm_smmu_rpm_get(smmu);
> -	if (ret < 0)
> +	if (ret < 0) {
> +		arm_smmu_rpm_put(smmu);
>   		return;
> +	}
>   
>   	arm_smmu_master_free_smes(cfg, fwspec);
>   
> 

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

* Re: [PATCH] iommu/arm-smmu: Fix arm_smmu_device refcount leak when arm_smmu_rpm_get fails
@ 2021-06-09 14:12   ` Robin Murphy
  0 siblings, 0 replies; 9+ messages in thread
From: Robin Murphy @ 2021-06-09 14:12 UTC (permalink / raw)
  To: Xiyu Yang, Will Deacon, Joerg Roedel, Nicolin Chen,
	Bjorn Andersson, Krishna Reddy, Jordan Crouse,
	Sai Prakash Ranjan, linux-arm-kernel, iommu, linux-kernel
  Cc: Xin Tan, yuanxzhang

On 2021-06-09 14:35, Xiyu Yang wrote:
> arm_smmu_rpm_get() invokes pm_runtime_get_sync(), which increases the
> refcount of the "smmu" even though the return value is less than 0.
> 
> The reference counting issue happens in some error handling paths of
> arm_smmu_rpm_get() in its caller functions. When arm_smmu_rpm_get()
> fails, the caller functions forget to decrease the refcount of "smmu"
> increased by arm_smmu_rpm_get(), causing a refcount leak.
> 
> Fix this issue by calling arm_smmu_rpm_put() or jumping to the "rpm_put"
> label when arm_smmu_rpm_get() fails.

If only there was some kind of helper function which could encapsulate 
the correct expected behaviour in a single place...

In fact with the new pm_runtime_resume_and_get() API I think these two 
patches boil down to a one-line change.

Thanks,
Robin.

> Signed-off-by: Xiyu Yang <xiyuyang19@fudan.edu.cn>
> Signed-off-by: Xin Tan <tanxin.ctf@gmail.com>
> ---
>   drivers/iommu/arm/arm-smmu/arm-smmu.c | 13 +++++++++----
>   1 file changed, 9 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> index 6f72c4d208ca..177ee54c5534 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> @@ -840,7 +840,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
>   
>   	ret = arm_smmu_rpm_get(smmu);
>   	if (ret < 0)
> -		return;
> +		goto rpm_put;
>   
>   	/*
>   	 * Disable the context bank and free the page tables before freeing
> @@ -857,6 +857,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
>   	free_io_pgtable_ops(smmu_domain->pgtbl_ops);
>   	__arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx);
>   
> +rpm_put:
>   	arm_smmu_rpm_put(smmu);
>   }
>   
> @@ -1153,7 +1154,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
>   
>   	ret = arm_smmu_rpm_get(smmu);
>   	if (ret < 0)
> -		return ret;
> +		goto rpm_put;
>   
>   	/* Ensure that the domain is finalised */
>   	ret = arm_smmu_init_domain_context(domain, smmu, dev);
> @@ -1404,7 +1405,7 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
>   
>   	ret = arm_smmu_rpm_get(smmu);
>   	if (ret < 0)
> -		goto out_cfg_free;
> +		goto rpm_put;
>   
>   	ret = arm_smmu_master_alloc_smes(dev);
>   	arm_smmu_rpm_put(smmu);
> @@ -1417,6 +1418,8 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
>   
>   	return &smmu->iommu;
>   
> +rpm_put:
> +	arm_smmu_rpm_put(smmu);
>   out_cfg_free:
>   	kfree(cfg);
>   out_free:
> @@ -1438,8 +1441,10 @@ static void arm_smmu_release_device(struct device *dev)
>   	smmu = cfg->smmu;
>   
>   	ret = arm_smmu_rpm_get(smmu);
> -	if (ret < 0)
> +	if (ret < 0) {
> +		arm_smmu_rpm_put(smmu);
>   		return;
> +	}
>   
>   	arm_smmu_master_free_smes(cfg, fwspec);
>   
> 
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

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

* Re: [PATCH] iommu/arm-smmu: Fix arm_smmu_device refcount leak when arm_smmu_rpm_get fails
@ 2021-06-09 14:12   ` Robin Murphy
  0 siblings, 0 replies; 9+ messages in thread
From: Robin Murphy @ 2021-06-09 14:12 UTC (permalink / raw)
  To: Xiyu Yang, Will Deacon, Joerg Roedel, Nicolin Chen,
	Bjorn Andersson, Krishna Reddy, Jordan Crouse,
	Sai Prakash Ranjan, linux-arm-kernel, iommu, linux-kernel
  Cc: yuanxzhang, Xin Tan

On 2021-06-09 14:35, Xiyu Yang wrote:
> arm_smmu_rpm_get() invokes pm_runtime_get_sync(), which increases the
> refcount of the "smmu" even though the return value is less than 0.
> 
> The reference counting issue happens in some error handling paths of
> arm_smmu_rpm_get() in its caller functions. When arm_smmu_rpm_get()
> fails, the caller functions forget to decrease the refcount of "smmu"
> increased by arm_smmu_rpm_get(), causing a refcount leak.
> 
> Fix this issue by calling arm_smmu_rpm_put() or jumping to the "rpm_put"
> label when arm_smmu_rpm_get() fails.

If only there was some kind of helper function which could encapsulate 
the correct expected behaviour in a single place...

In fact with the new pm_runtime_resume_and_get() API I think these two 
patches boil down to a one-line change.

Thanks,
Robin.

> Signed-off-by: Xiyu Yang <xiyuyang19@fudan.edu.cn>
> Signed-off-by: Xin Tan <tanxin.ctf@gmail.com>
> ---
>   drivers/iommu/arm/arm-smmu/arm-smmu.c | 13 +++++++++----
>   1 file changed, 9 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> index 6f72c4d208ca..177ee54c5534 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> @@ -840,7 +840,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
>   
>   	ret = arm_smmu_rpm_get(smmu);
>   	if (ret < 0)
> -		return;
> +		goto rpm_put;
>   
>   	/*
>   	 * Disable the context bank and free the page tables before freeing
> @@ -857,6 +857,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
>   	free_io_pgtable_ops(smmu_domain->pgtbl_ops);
>   	__arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx);
>   
> +rpm_put:
>   	arm_smmu_rpm_put(smmu);
>   }
>   
> @@ -1153,7 +1154,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
>   
>   	ret = arm_smmu_rpm_get(smmu);
>   	if (ret < 0)
> -		return ret;
> +		goto rpm_put;
>   
>   	/* Ensure that the domain is finalised */
>   	ret = arm_smmu_init_domain_context(domain, smmu, dev);
> @@ -1404,7 +1405,7 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
>   
>   	ret = arm_smmu_rpm_get(smmu);
>   	if (ret < 0)
> -		goto out_cfg_free;
> +		goto rpm_put;
>   
>   	ret = arm_smmu_master_alloc_smes(dev);
>   	arm_smmu_rpm_put(smmu);
> @@ -1417,6 +1418,8 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
>   
>   	return &smmu->iommu;
>   
> +rpm_put:
> +	arm_smmu_rpm_put(smmu);
>   out_cfg_free:
>   	kfree(cfg);
>   out_free:
> @@ -1438,8 +1441,10 @@ static void arm_smmu_release_device(struct device *dev)
>   	smmu = cfg->smmu;
>   
>   	ret = arm_smmu_rpm_get(smmu);
> -	if (ret < 0)
> +	if (ret < 0) {
> +		arm_smmu_rpm_put(smmu);
>   		return;
> +	}
>   
>   	arm_smmu_master_free_smes(cfg, fwspec);
>   
> 

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

* Re: Re: [PATCH] iommu/arm-smmu: Fix arm_smmu_device refcount leak when arm_smmu_rpm_get fails
  2021-06-09 14:12   ` Robin Murphy
  (?)
@ 2021-06-10  2:20     ` Xiyu Yang via iommu
  -1 siblings, 0 replies; 9+ messages in thread
From: Xiyu Yang @ 2021-06-10  2:20 UTC (permalink / raw)
  To: Robin Murphy
  Cc: Will Deacon, Joerg Roedel, Nicolin Chen, Bjorn Andersson,
	Krishna Reddy, Jordan Crouse, Sai Prakash Ranjan,
	linux-arm-kernel, iommu, linux-kernel, yuanxzhang, Xin Tan


Thanks for your advice, I'll send a v2 patch soon.


> -----Original Messages-----
> From: "Robin Murphy" <robin.murphy@arm.com>
> Sent Time: 2021-06-09 22:12:11 (Wednesday)
> To: "Xiyu Yang" <xiyuyang19@fudan.edu.cn>, "Will Deacon" <will@kernel.org>, "Joerg Roedel" <joro@8bytes.org>, "Nicolin Chen" <nicoleotsuka@gmail.com>, "Bjorn Andersson" <bjorn.andersson@linaro.org>, "Krishna Reddy" <vdumpa@nvidia.com>, "Jordan Crouse" <jordan@cosmicpenguin.net>, "Sai Prakash Ranjan" <saiprakash.ranjan@codeaurora.org>, linux-arm-kernel@lists.infradead.org, iommu@lists.linux-foundation.org, linux-kernel@vger.kernel.org
> Cc: yuanxzhang@fudan.edu.cn, "Xin Tan" <tanxin.ctf@gmail.com>
> Subject: Re: [PATCH] iommu/arm-smmu: Fix arm_smmu_device refcount leak when arm_smmu_rpm_get fails
> 
> On 2021-06-09 14:35, Xiyu Yang wrote:
> > arm_smmu_rpm_get() invokes pm_runtime_get_sync(), which increases the
> > refcount of the "smmu" even though the return value is less than 0.
> > 
> > The reference counting issue happens in some error handling paths of
> > arm_smmu_rpm_get() in its caller functions. When arm_smmu_rpm_get()
> > fails, the caller functions forget to decrease the refcount of "smmu"
> > increased by arm_smmu_rpm_get(), causing a refcount leak.
> > 
> > Fix this issue by calling arm_smmu_rpm_put() or jumping to the "rpm_put"
> > label when arm_smmu_rpm_get() fails.
> 
> If only there was some kind of helper function which could encapsulate 
> the correct expected behaviour in a single place...
> 
> In fact with the new pm_runtime_resume_and_get() API I think these two 
> patches boil down to a one-line change.
> 
> Thanks,
> Robin.
> 
> > Signed-off-by: Xiyu Yang <xiyuyang19@fudan.edu.cn>
> > Signed-off-by: Xin Tan <tanxin.ctf@gmail.com>
> > ---
> >   drivers/iommu/arm/arm-smmu/arm-smmu.c | 13 +++++++++----
> >   1 file changed, 9 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > index 6f72c4d208ca..177ee54c5534 100644
> > --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > @@ -840,7 +840,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
> >   
> >   	ret = arm_smmu_rpm_get(smmu);
> >   	if (ret < 0)
> > -		return;
> > +		goto rpm_put;
> >   
> >   	/*
> >   	 * Disable the context bank and free the page tables before freeing
> > @@ -857,6 +857,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
> >   	free_io_pgtable_ops(smmu_domain->pgtbl_ops);
> >   	__arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx);
> >   
> > +rpm_put:
> >   	arm_smmu_rpm_put(smmu);
> >   }
> >   
> > @@ -1153,7 +1154,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
> >   
> >   	ret = arm_smmu_rpm_get(smmu);
> >   	if (ret < 0)
> > -		return ret;
> > +		goto rpm_put;
> >   
> >   	/* Ensure that the domain is finalised */
> >   	ret = arm_smmu_init_domain_context(domain, smmu, dev);
> > @@ -1404,7 +1405,7 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
> >   
> >   	ret = arm_smmu_rpm_get(smmu);
> >   	if (ret < 0)
> > -		goto out_cfg_free;
> > +		goto rpm_put;
> >   
> >   	ret = arm_smmu_master_alloc_smes(dev);
> >   	arm_smmu_rpm_put(smmu);
> > @@ -1417,6 +1418,8 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
> >   
> >   	return &smmu->iommu;
> >   
> > +rpm_put:
> > +	arm_smmu_rpm_put(smmu);
> >   out_cfg_free:
> >   	kfree(cfg);
> >   out_free:
> > @@ -1438,8 +1441,10 @@ static void arm_smmu_release_device(struct device *dev)
> >   	smmu = cfg->smmu;
> >   
> >   	ret = arm_smmu_rpm_get(smmu);
> > -	if (ret < 0)
> > +	if (ret < 0) {
> > +		arm_smmu_rpm_put(smmu);
> >   		return;
> > +	}
> >   
> >   	arm_smmu_master_free_smes(cfg, fwspec);
> >   
> > 







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

* Re: Re: [PATCH] iommu/arm-smmu: Fix arm_smmu_device refcount leak when arm_smmu_rpm_get fails
@ 2021-06-10  2:20     ` Xiyu Yang via iommu
  0 siblings, 0 replies; 9+ messages in thread
From: Xiyu Yang via iommu @ 2021-06-10  2:20 UTC (permalink / raw)
  To: Robin Murphy
  Cc: linux-kernel, yuanxzhang, iommu, Xin Tan, Will Deacon, linux-arm-kernel


Thanks for your advice, I'll send a v2 patch soon.


> -----Original Messages-----
> From: "Robin Murphy" <robin.murphy@arm.com>
> Sent Time: 2021-06-09 22:12:11 (Wednesday)
> To: "Xiyu Yang" <xiyuyang19@fudan.edu.cn>, "Will Deacon" <will@kernel.org>, "Joerg Roedel" <joro@8bytes.org>, "Nicolin Chen" <nicoleotsuka@gmail.com>, "Bjorn Andersson" <bjorn.andersson@linaro.org>, "Krishna Reddy" <vdumpa@nvidia.com>, "Jordan Crouse" <jordan@cosmicpenguin.net>, "Sai Prakash Ranjan" <saiprakash.ranjan@codeaurora.org>, linux-arm-kernel@lists.infradead.org, iommu@lists.linux-foundation.org, linux-kernel@vger.kernel.org
> Cc: yuanxzhang@fudan.edu.cn, "Xin Tan" <tanxin.ctf@gmail.com>
> Subject: Re: [PATCH] iommu/arm-smmu: Fix arm_smmu_device refcount leak when arm_smmu_rpm_get fails
> 
> On 2021-06-09 14:35, Xiyu Yang wrote:
> > arm_smmu_rpm_get() invokes pm_runtime_get_sync(), which increases the
> > refcount of the "smmu" even though the return value is less than 0.
> > 
> > The reference counting issue happens in some error handling paths of
> > arm_smmu_rpm_get() in its caller functions. When arm_smmu_rpm_get()
> > fails, the caller functions forget to decrease the refcount of "smmu"
> > increased by arm_smmu_rpm_get(), causing a refcount leak.
> > 
> > Fix this issue by calling arm_smmu_rpm_put() or jumping to the "rpm_put"
> > label when arm_smmu_rpm_get() fails.
> 
> If only there was some kind of helper function which could encapsulate 
> the correct expected behaviour in a single place...
> 
> In fact with the new pm_runtime_resume_and_get() API I think these two 
> patches boil down to a one-line change.
> 
> Thanks,
> Robin.
> 
> > Signed-off-by: Xiyu Yang <xiyuyang19@fudan.edu.cn>
> > Signed-off-by: Xin Tan <tanxin.ctf@gmail.com>
> > ---
> >   drivers/iommu/arm/arm-smmu/arm-smmu.c | 13 +++++++++----
> >   1 file changed, 9 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > index 6f72c4d208ca..177ee54c5534 100644
> > --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > @@ -840,7 +840,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
> >   
> >   	ret = arm_smmu_rpm_get(smmu);
> >   	if (ret < 0)
> > -		return;
> > +		goto rpm_put;
> >   
> >   	/*
> >   	 * Disable the context bank and free the page tables before freeing
> > @@ -857,6 +857,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
> >   	free_io_pgtable_ops(smmu_domain->pgtbl_ops);
> >   	__arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx);
> >   
> > +rpm_put:
> >   	arm_smmu_rpm_put(smmu);
> >   }
> >   
> > @@ -1153,7 +1154,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
> >   
> >   	ret = arm_smmu_rpm_get(smmu);
> >   	if (ret < 0)
> > -		return ret;
> > +		goto rpm_put;
> >   
> >   	/* Ensure that the domain is finalised */
> >   	ret = arm_smmu_init_domain_context(domain, smmu, dev);
> > @@ -1404,7 +1405,7 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
> >   
> >   	ret = arm_smmu_rpm_get(smmu);
> >   	if (ret < 0)
> > -		goto out_cfg_free;
> > +		goto rpm_put;
> >   
> >   	ret = arm_smmu_master_alloc_smes(dev);
> >   	arm_smmu_rpm_put(smmu);
> > @@ -1417,6 +1418,8 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
> >   
> >   	return &smmu->iommu;
> >   
> > +rpm_put:
> > +	arm_smmu_rpm_put(smmu);
> >   out_cfg_free:
> >   	kfree(cfg);
> >   out_free:
> > @@ -1438,8 +1441,10 @@ static void arm_smmu_release_device(struct device *dev)
> >   	smmu = cfg->smmu;
> >   
> >   	ret = arm_smmu_rpm_get(smmu);
> > -	if (ret < 0)
> > +	if (ret < 0) {
> > +		arm_smmu_rpm_put(smmu);
> >   		return;
> > +	}
> >   
> >   	arm_smmu_master_free_smes(cfg, fwspec);
> >   
> > 






_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

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

* Re: Re: [PATCH] iommu/arm-smmu: Fix arm_smmu_device refcount leak when arm_smmu_rpm_get fails
@ 2021-06-10  2:20     ` Xiyu Yang via iommu
  0 siblings, 0 replies; 9+ messages in thread
From: Xiyu Yang @ 2021-06-10  2:20 UTC (permalink / raw)
  To: Robin Murphy
  Cc: Sai Prakash Ranjan, linux-kernel, Joerg Roedel, yuanxzhang,
	iommu, Jordan Crouse, Nicolin Chen, Xin Tan, Bjorn Andersson,
	Will Deacon, linux-arm-kernel


Thanks for your advice, I'll send a v2 patch soon.


> -----Original Messages-----
> From: "Robin Murphy" <robin.murphy@arm.com>
> Sent Time: 2021-06-09 22:12:11 (Wednesday)
> To: "Xiyu Yang" <xiyuyang19@fudan.edu.cn>, "Will Deacon" <will@kernel.org>, "Joerg Roedel" <joro@8bytes.org>, "Nicolin Chen" <nicoleotsuka@gmail.com>, "Bjorn Andersson" <bjorn.andersson@linaro.org>, "Krishna Reddy" <vdumpa@nvidia.com>, "Jordan Crouse" <jordan@cosmicpenguin.net>, "Sai Prakash Ranjan" <saiprakash.ranjan@codeaurora.org>, linux-arm-kernel@lists.infradead.org, iommu@lists.linux-foundation.org, linux-kernel@vger.kernel.org
> Cc: yuanxzhang@fudan.edu.cn, "Xin Tan" <tanxin.ctf@gmail.com>
> Subject: Re: [PATCH] iommu/arm-smmu: Fix arm_smmu_device refcount leak when arm_smmu_rpm_get fails
> 
> On 2021-06-09 14:35, Xiyu Yang wrote:
> > arm_smmu_rpm_get() invokes pm_runtime_get_sync(), which increases the
> > refcount of the "smmu" even though the return value is less than 0.
> > 
> > The reference counting issue happens in some error handling paths of
> > arm_smmu_rpm_get() in its caller functions. When arm_smmu_rpm_get()
> > fails, the caller functions forget to decrease the refcount of "smmu"
> > increased by arm_smmu_rpm_get(), causing a refcount leak.
> > 
> > Fix this issue by calling arm_smmu_rpm_put() or jumping to the "rpm_put"
> > label when arm_smmu_rpm_get() fails.
> 
> If only there was some kind of helper function which could encapsulate 
> the correct expected behaviour in a single place...
> 
> In fact with the new pm_runtime_resume_and_get() API I think these two 
> patches boil down to a one-line change.
> 
> Thanks,
> Robin.
> 
> > Signed-off-by: Xiyu Yang <xiyuyang19@fudan.edu.cn>
> > Signed-off-by: Xin Tan <tanxin.ctf@gmail.com>
> > ---
> >   drivers/iommu/arm/arm-smmu/arm-smmu.c | 13 +++++++++----
> >   1 file changed, 9 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > index 6f72c4d208ca..177ee54c5534 100644
> > --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> > @@ -840,7 +840,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
> >   
> >   	ret = arm_smmu_rpm_get(smmu);
> >   	if (ret < 0)
> > -		return;
> > +		goto rpm_put;
> >   
> >   	/*
> >   	 * Disable the context bank and free the page tables before freeing
> > @@ -857,6 +857,7 @@ static void arm_smmu_destroy_domain_context(struct iommu_domain *domain)
> >   	free_io_pgtable_ops(smmu_domain->pgtbl_ops);
> >   	__arm_smmu_free_bitmap(smmu->context_map, cfg->cbndx);
> >   
> > +rpm_put:
> >   	arm_smmu_rpm_put(smmu);
> >   }
> >   
> > @@ -1153,7 +1154,7 @@ static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
> >   
> >   	ret = arm_smmu_rpm_get(smmu);
> >   	if (ret < 0)
> > -		return ret;
> > +		goto rpm_put;
> >   
> >   	/* Ensure that the domain is finalised */
> >   	ret = arm_smmu_init_domain_context(domain, smmu, dev);
> > @@ -1404,7 +1405,7 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
> >   
> >   	ret = arm_smmu_rpm_get(smmu);
> >   	if (ret < 0)
> > -		goto out_cfg_free;
> > +		goto rpm_put;
> >   
> >   	ret = arm_smmu_master_alloc_smes(dev);
> >   	arm_smmu_rpm_put(smmu);
> > @@ -1417,6 +1418,8 @@ static struct iommu_device *arm_smmu_probe_device(struct device *dev)
> >   
> >   	return &smmu->iommu;
> >   
> > +rpm_put:
> > +	arm_smmu_rpm_put(smmu);
> >   out_cfg_free:
> >   	kfree(cfg);
> >   out_free:
> > @@ -1438,8 +1441,10 @@ static void arm_smmu_release_device(struct device *dev)
> >   	smmu = cfg->smmu;
> >   
> >   	ret = arm_smmu_rpm_get(smmu);
> > -	if (ret < 0)
> > +	if (ret < 0) {
> > +		arm_smmu_rpm_put(smmu);
> >   		return;
> > +	}
> >   
> >   	arm_smmu_master_free_smes(cfg, fwspec);
> >   
> > 







_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

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

end of thread, other threads:[~2021-06-10  4:45 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-06-09 13:35 [PATCH] iommu/arm-smmu: Fix arm_smmu_device refcount leak when arm_smmu_rpm_get fails Xiyu Yang
2021-06-09 13:35 ` Xiyu Yang
2021-06-09 13:35 ` Xiyu Yang via iommu
2021-06-09 14:12 ` Robin Murphy
2021-06-09 14:12   ` Robin Murphy
2021-06-09 14:12   ` Robin Murphy
2021-06-10  2:20   ` Xiyu Yang
2021-06-10  2:20     ` Xiyu Yang
2021-06-10  2:20     ` Xiyu Yang via iommu

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