All of lore.kernel.org
 help / color / mirror / Atom feed
From: Ross Zwisler <ross.zwisler-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
To: Dan Williams <dan.j.williams-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
Cc: linux-acpi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	Lv Zheng <lv.zheng-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>,
	stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
	linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw@public.gmane.org
Subject: Re: [PATCH] acpi, nfit: fix acpi_get_table leak
Date: Mon, 3 Apr 2017 13:00:14 -0600	[thread overview]
Message-ID: <20170403190014.GA20892@linux.intel.com> (raw)
In-Reply-To: <149107472042.16205.8935477753191459036.stgit-p8uTFz9XbKj2zm6wflaqv1nYeNYlB/vhral2JQCrhuEAvxtiuMwx3w@public.gmane.org>

On Sat, Apr 01, 2017 at 12:25:20PM -0700, Dan Williams wrote:
> Calls to acpi_get_table() must be paired with acpi_put_table() to undo
> the mapping established by acpi_tb_acquire_table().
> 
> Cc: <stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org>
> Fixes: 6b11d1d67713 ("ACPI / osl: Remove acpi_get_table_with_size()/early_acpi_os_unmap_memory() users")
> Cc: Lv Zheng <lv.zheng-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> Reported-by: Ross Zwisler <ross.zwisler-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
> Signed-off-by: Dan Williams <dan.j.williams-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
> ---
>  drivers/acpi/nfit/core.c |    9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
> index c8ea9d698cd0..6acfea69f061 100644
> --- a/drivers/acpi/nfit/core.c
> +++ b/drivers/acpi/nfit/core.c
> @@ -2818,6 +2818,11 @@ void acpi_nfit_desc_init(struct acpi_nfit_desc *acpi_desc, struct device *dev)
>  }
>  EXPORT_SYMBOL_GPL(acpi_nfit_desc_init);
>  
> +static void acpi_nfit_put_table(void *table)
> +{
> +	acpi_put_table(table);
> +}
> +
>  static int acpi_nfit_add(struct acpi_device *adev)
>  {
>  	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
> @@ -2834,6 +2839,10 @@ static int acpi_nfit_add(struct acpi_device *adev)
>  		dev_dbg(dev, "failed to find NFIT at startup\n");
>  		return 0;
>  	}
> +
> +	rc = devm_add_action_or_reset(dev, acpi_nfit_put_table, tbl);
> +	if (rc)
> +		return rc;
>  	sz = tbl->length;
>  
>  	acpi_desc = devm_kzalloc(dev, sizeof(*acpi_desc), GFP_KERNEL);

I've been looking at this this as well, and I think it might be better to just
drop the reference immediately in acpi_nfit_add() after we're done processing
the tables?  

Anyway, here's the patch I was working on, but I think either works.

------ 8< ------
>From 4819cd889b08c3c17f8f9fcf895a083f21fa0898 Mon Sep 17 00:00:00 2001
From: Ross Zwisler <ross.zwisler-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
Date: Mon, 3 Apr 2017 11:53:32 -0600
Subject: [PATCH] nfit: release reference on ACPI nfit table

Currently acpi_nfit_add() grabs a reference to the ACPI NFIT table
structures via acpi_get_table(), but never releases it with
acpi_put_table().  This means that the refcount protecting the ioremap for
the NFIT table never decrements, so the ioremap can never be undone.  The
ioremap happens via this path:

acpi_get_table()
  acpi_tb_get_table()
    acpi_tb_validate_table()
      acpi_tb_acquire_table()
        acpi_os_map_memory()

In practice this fix is correct but won't have a usable visible impact
because the ACPI sysfs code (acpi_table_attr_init() et al.), which
populates /sys/firmware/acpi/tables/NFIT, also keeps a table reference, so
the NFIT table memory will always remain mapped.

We drop the refcount at the end of acpi_nfit_add() instead of waiting till
driver unload and doing it via acpi_nfit_remove() or something akin to
acpi_nfit_destruct() called via the devm_ interface.  This is because
during acpi_nfit_add() we never actually keep any references to the
original ACPI tables.  We either copy individual elements out, or we make
whole copies of tables in functions like add_spa(), add memdev(), etc.

Signed-off-by: Ross Zwisler <ross.zwisler-VuQAYsv1563Yd54FQh9/CA@public.gmane.org>
---
 drivers/acpi/nfit/core.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index 662036b..ad0dfd6 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -2833,8 +2833,10 @@ static int acpi_nfit_add(struct acpi_device *adev)
 	sz = tbl->length;
 
 	acpi_desc = devm_kzalloc(dev, sizeof(*acpi_desc), GFP_KERNEL);
-	if (!acpi_desc)
-		return -ENOMEM;
+	if (!acpi_desc) {
+		rc = -ENOMEM;
+		goto out;
+	}
 	acpi_nfit_desc_init(acpi_desc, &adev->dev);
 
 	/* Save the acpi header for exporting the revision via sysfs */
@@ -2857,6 +2859,8 @@ static int acpi_nfit_add(struct acpi_device *adev)
 		rc = acpi_nfit_init(acpi_desc, (void *) tbl
 				+ sizeof(struct acpi_table_nfit),
 				sz - sizeof(struct acpi_table_nfit));
+out:
+	acpi_put_table(tbl);
 	return rc;
 }
 
-- 
2.9.3

WARNING: multiple messages have this Message-ID (diff)
From: Ross Zwisler <ross.zwisler@linux.intel.com>
To: Dan Williams <dan.j.williams@intel.com>
Cc: linux-acpi@vger.kernel.org, Lv Zheng <lv.zheng@intel.com>,
	stable@vger.kernel.org, linux-nvdimm@lists.01.org
Subject: Re: [PATCH] acpi, nfit: fix acpi_get_table leak
Date: Mon, 3 Apr 2017 13:00:14 -0600	[thread overview]
Message-ID: <20170403190014.GA20892@linux.intel.com> (raw)
In-Reply-To: <149107472042.16205.8935477753191459036.stgit@dwillia2-desk3.amr.corp.intel.com>

On Sat, Apr 01, 2017 at 12:25:20PM -0700, Dan Williams wrote:
> Calls to acpi_get_table() must be paired with acpi_put_table() to undo
> the mapping established by acpi_tb_acquire_table().
> 
> Cc: <stable@vger.kernel.org>
> Fixes: 6b11d1d67713 ("ACPI / osl: Remove acpi_get_table_with_size()/early_acpi_os_unmap_memory() users")
> Cc: Lv Zheng <lv.zheng@intel.com>
> Reported-by: Ross Zwisler <ross.zwisler@linux.intel.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
>  drivers/acpi/nfit/core.c |    9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
> index c8ea9d698cd0..6acfea69f061 100644
> --- a/drivers/acpi/nfit/core.c
> +++ b/drivers/acpi/nfit/core.c
> @@ -2818,6 +2818,11 @@ void acpi_nfit_desc_init(struct acpi_nfit_desc *acpi_desc, struct device *dev)
>  }
>  EXPORT_SYMBOL_GPL(acpi_nfit_desc_init);
>  
> +static void acpi_nfit_put_table(void *table)
> +{
> +	acpi_put_table(table);
> +}
> +
>  static int acpi_nfit_add(struct acpi_device *adev)
>  {
>  	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
> @@ -2834,6 +2839,10 @@ static int acpi_nfit_add(struct acpi_device *adev)
>  		dev_dbg(dev, "failed to find NFIT at startup\n");
>  		return 0;
>  	}
> +
> +	rc = devm_add_action_or_reset(dev, acpi_nfit_put_table, tbl);
> +	if (rc)
> +		return rc;
>  	sz = tbl->length;
>  
>  	acpi_desc = devm_kzalloc(dev, sizeof(*acpi_desc), GFP_KERNEL);

I've been looking at this this as well, and I think it might be better to just
drop the reference immediately in acpi_nfit_add() after we're done processing
the tables?  

Anyway, here's the patch I was working on, but I think either works.

------ 8< ------
>From 4819cd889b08c3c17f8f9fcf895a083f21fa0898 Mon Sep 17 00:00:00 2001
From: Ross Zwisler <ross.zwisler@linux.intel.com>
Date: Mon, 3 Apr 2017 11:53:32 -0600
Subject: [PATCH] nfit: release reference on ACPI nfit table

Currently acpi_nfit_add() grabs a reference to the ACPI NFIT table
structures via acpi_get_table(), but never releases it with
acpi_put_table().  This means that the refcount protecting the ioremap for
the NFIT table never decrements, so the ioremap can never be undone.  The
ioremap happens via this path:

acpi_get_table()
  acpi_tb_get_table()
    acpi_tb_validate_table()
      acpi_tb_acquire_table()
        acpi_os_map_memory()

In practice this fix is correct but won't have a usable visible impact
because the ACPI sysfs code (acpi_table_attr_init() et al.), which
populates /sys/firmware/acpi/tables/NFIT, also keeps a table reference, so
the NFIT table memory will always remain mapped.

We drop the refcount at the end of acpi_nfit_add() instead of waiting till
driver unload and doing it via acpi_nfit_remove() or something akin to
acpi_nfit_destruct() called via the devm_ interface.  This is because
during acpi_nfit_add() we never actually keep any references to the
original ACPI tables.  We either copy individual elements out, or we make
whole copies of tables in functions like add_spa(), add memdev(), etc.

Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
---
 drivers/acpi/nfit/core.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index 662036b..ad0dfd6 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -2833,8 +2833,10 @@ static int acpi_nfit_add(struct acpi_device *adev)
 	sz = tbl->length;
 
 	acpi_desc = devm_kzalloc(dev, sizeof(*acpi_desc), GFP_KERNEL);
-	if (!acpi_desc)
-		return -ENOMEM;
+	if (!acpi_desc) {
+		rc = -ENOMEM;
+		goto out;
+	}
 	acpi_nfit_desc_init(acpi_desc, &adev->dev);
 
 	/* Save the acpi header for exporting the revision via sysfs */
@@ -2857,6 +2859,8 @@ static int acpi_nfit_add(struct acpi_device *adev)
 		rc = acpi_nfit_init(acpi_desc, (void *) tbl
 				+ sizeof(struct acpi_table_nfit),
 				sz - sizeof(struct acpi_table_nfit));
+out:
+	acpi_put_table(tbl);
 	return rc;
 }
 
-- 
2.9.3
_______________________________________________
Linux-nvdimm mailing list
Linux-nvdimm@lists.01.org
https://lists.01.org/mailman/listinfo/linux-nvdimm

WARNING: multiple messages have this Message-ID (diff)
From: Ross Zwisler <ross.zwisler@linux.intel.com>
To: Dan Williams <dan.j.williams@intel.com>
Cc: linux-nvdimm@lists.01.org, linux-acpi@vger.kernel.org,
	Ross Zwisler <ross.zwisler@linux.intel.com>,
	Lv Zheng <lv.zheng@intel.com>,
	stable@vger.kernel.org
Subject: Re: [PATCH] acpi, nfit: fix acpi_get_table leak
Date: Mon, 3 Apr 2017 13:00:14 -0600	[thread overview]
Message-ID: <20170403190014.GA20892@linux.intel.com> (raw)
In-Reply-To: <149107472042.16205.8935477753191459036.stgit@dwillia2-desk3.amr.corp.intel.com>

On Sat, Apr 01, 2017 at 12:25:20PM -0700, Dan Williams wrote:
> Calls to acpi_get_table() must be paired with acpi_put_table() to undo
> the mapping established by acpi_tb_acquire_table().
> 
> Cc: <stable@vger.kernel.org>
> Fixes: 6b11d1d67713 ("ACPI / osl: Remove acpi_get_table_with_size()/early_acpi_os_unmap_memory() users")
> Cc: Lv Zheng <lv.zheng@intel.com>
> Reported-by: Ross Zwisler <ross.zwisler@linux.intel.com>
> Signed-off-by: Dan Williams <dan.j.williams@intel.com>
> ---
>  drivers/acpi/nfit/core.c |    9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
> index c8ea9d698cd0..6acfea69f061 100644
> --- a/drivers/acpi/nfit/core.c
> +++ b/drivers/acpi/nfit/core.c
> @@ -2818,6 +2818,11 @@ void acpi_nfit_desc_init(struct acpi_nfit_desc *acpi_desc, struct device *dev)
>  }
>  EXPORT_SYMBOL_GPL(acpi_nfit_desc_init);
>  
> +static void acpi_nfit_put_table(void *table)
> +{
> +	acpi_put_table(table);
> +}
> +
>  static int acpi_nfit_add(struct acpi_device *adev)
>  {
>  	struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL };
> @@ -2834,6 +2839,10 @@ static int acpi_nfit_add(struct acpi_device *adev)
>  		dev_dbg(dev, "failed to find NFIT at startup\n");
>  		return 0;
>  	}
> +
> +	rc = devm_add_action_or_reset(dev, acpi_nfit_put_table, tbl);
> +	if (rc)
> +		return rc;
>  	sz = tbl->length;
>  
>  	acpi_desc = devm_kzalloc(dev, sizeof(*acpi_desc), GFP_KERNEL);

I've been looking at this this as well, and I think it might be better to just
drop the reference immediately in acpi_nfit_add() after we're done processing
the tables?  

Anyway, here's the patch I was working on, but I think either works.

------ 8< ------
>From 4819cd889b08c3c17f8f9fcf895a083f21fa0898 Mon Sep 17 00:00:00 2001
From: Ross Zwisler <ross.zwisler@linux.intel.com>
Date: Mon, 3 Apr 2017 11:53:32 -0600
Subject: [PATCH] nfit: release reference on ACPI nfit table

Currently acpi_nfit_add() grabs a reference to the ACPI NFIT table
structures via acpi_get_table(), but never releases it with
acpi_put_table().  This means that the refcount protecting the ioremap for
the NFIT table never decrements, so the ioremap can never be undone.  The
ioremap happens via this path:

acpi_get_table()
  acpi_tb_get_table()
    acpi_tb_validate_table()
      acpi_tb_acquire_table()
        acpi_os_map_memory()

In practice this fix is correct but won't have a usable visible impact
because the ACPI sysfs code (acpi_table_attr_init() et al.), which
populates /sys/firmware/acpi/tables/NFIT, also keeps a table reference, so
the NFIT table memory will always remain mapped.

We drop the refcount at the end of acpi_nfit_add() instead of waiting till
driver unload and doing it via acpi_nfit_remove() or something akin to
acpi_nfit_destruct() called via the devm_ interface.  This is because
during acpi_nfit_add() we never actually keep any references to the
original ACPI tables.  We either copy individual elements out, or we make
whole copies of tables in functions like add_spa(), add memdev(), etc.

Signed-off-by: Ross Zwisler <ross.zwisler@linux.intel.com>
---
 drivers/acpi/nfit/core.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index 662036b..ad0dfd6 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -2833,8 +2833,10 @@ static int acpi_nfit_add(struct acpi_device *adev)
 	sz = tbl->length;
 
 	acpi_desc = devm_kzalloc(dev, sizeof(*acpi_desc), GFP_KERNEL);
-	if (!acpi_desc)
-		return -ENOMEM;
+	if (!acpi_desc) {
+		rc = -ENOMEM;
+		goto out;
+	}
 	acpi_nfit_desc_init(acpi_desc, &adev->dev);
 
 	/* Save the acpi header for exporting the revision via sysfs */
@@ -2857,6 +2859,8 @@ static int acpi_nfit_add(struct acpi_device *adev)
 		rc = acpi_nfit_init(acpi_desc, (void *) tbl
 				+ sizeof(struct acpi_table_nfit),
 				sz - sizeof(struct acpi_table_nfit));
+out:
+	acpi_put_table(tbl);
 	return rc;
 }
 
-- 
2.9.3

  parent reply	other threads:[~2017-04-03 19:00 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-01 19:25 [PATCH] acpi, nfit: fix acpi_get_table leak Dan Williams
2017-04-01 19:25 ` Dan Williams
     [not found] ` <149107472042.16205.8935477753191459036.stgit-p8uTFz9XbKj2zm6wflaqv1nYeNYlB/vhral2JQCrhuEAvxtiuMwx3w@public.gmane.org>
2017-04-03 19:00   ` Ross Zwisler [this message]
2017-04-03 19:00     ` Ross Zwisler
2017-04-03 19:00     ` Ross Zwisler
2017-04-03 20:47     ` Dan Williams
2017-04-03 20:47       ` Dan Williams

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20170403190014.GA20892@linux.intel.com \
    --to=ross.zwisler-vuqaysv1563yd54fqh9/ca@public.gmane.org \
    --cc=dan.j.williams-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
    --cc=linux-acpi-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    --cc=linux-nvdimm-hn68Rpc1hR1g9hUCZPvPmw@public.gmane.org \
    --cc=lv.zheng-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org \
    --cc=stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.