linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v1 1/1] ACPI: utils: Fix reference counting in for_each_acpi_dev_match()
@ 2021-05-19 21:02 Andy Shevchenko
  2021-05-20 19:13 ` Rafael J. Wysocki
  0 siblings, 1 reply; 5+ messages in thread
From: Andy Shevchenko @ 2021-05-19 21:02 UTC (permalink / raw)
  To: Rafael J. Wysocki, Andy Shevchenko, Daniel Scally, linux-acpi,
	linux-kernel, linux-media, devel
  Cc: Rafael J. Wysocki, Len Brown, Yong Zhi, Sakari Ailus, Bingbu Cao,
	Tianshu Qiu, Mauro Carvalho Chehab, Robert Moore, Erik Kaneda

Currently it's possible to iterate over the dangling pointer in case the device
suddenly disappears. This may happen becase callers put it at the end of a loop.

Instead, let's move that call inside acpi_dev_get_next_match_dev().

Fixes: 803abec64ef9 ("media: ipu3-cio2: Add cio2-bridge to ipu3-cio2 driver")
Fixes: bf263f64e804 ("media: ACPI / bus: Add acpi_dev_get_next_match_dev() and helper macro")
Cc: Daniel Scally <djrscally@gmail.com>
Cc: Sakari Ailus <sakari.ailus@linux.intel.com>
Signed-off-by: Andy Shevchenko <andy.shevchenko@gmail.com>
---
 drivers/acpi/utils.c                       | 5 +----
 drivers/media/pci/intel/ipu3/cio2-bridge.c | 8 +++-----
 include/acpi/acpi_bus.h                    | 5 -----
 3 files changed, 4 insertions(+), 14 deletions(-)

diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
index 3b54b8fd7396..ccfc484dbffd 100644
--- a/drivers/acpi/utils.c
+++ b/drivers/acpi/utils.c
@@ -846,10 +846,6 @@ EXPORT_SYMBOL(acpi_dev_present);
  * Return the next match of ACPI device if another matching device was present
  * at the moment of invocation, or NULL otherwise.
  *
- * FIXME: The function does not tolerate the sudden disappearance of @adev, e.g.
- * in the case of a hotplug event. That said, the caller should ensure that
- * this will never happen.
- *
  * The caller is responsible for invoking acpi_dev_put() on the returned device.
  *
  * See additional information in acpi_dev_present() as well.
@@ -866,6 +862,7 @@ acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const cha
 	match.hrv = hrv;
 
 	dev = bus_find_device(&acpi_bus_type, start, &match, acpi_dev_match_cb);
+	acpi_dev_put(adev);
 	return dev ? to_acpi_device(dev) : NULL;
 }
 EXPORT_SYMBOL(acpi_dev_get_next_match_dev);
diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c
index e8511787c1e4..477417261b6e 100644
--- a/drivers/media/pci/intel/ipu3/cio2-bridge.c
+++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c
@@ -178,13 +178,11 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,
 
 		if (bridge->n_sensors >= CIO2_NUM_PORTS) {
 			dev_err(&cio2->dev, "Exceeded available CIO2 ports\n");
-			cio2_bridge_unregister_sensors(bridge);
 			ret = -EINVAL;
-			goto err_out;
+			goto err_put_adev;
 		}
 
 		sensor = &bridge->sensors[bridge->n_sensors];
-		sensor->adev = adev;
 		strscpy(sensor->name, cfg->hid, sizeof(sensor->name));
 
 		ret = cio2_bridge_read_acpi_buffer(adev, "SSDB",
@@ -214,6 +212,7 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,
 			goto err_free_swnodes;
 		}
 
+		sensor->adev = acpi_dev_get(adev);
 		adev->fwnode.secondary = fwnode;
 
 		dev_info(&cio2->dev, "Found supported sensor %s\n",
@@ -227,8 +226,7 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,
 err_free_swnodes:
 	software_node_unregister_nodes(sensor->swnodes);
 err_put_adev:
-	acpi_dev_put(sensor->adev);
-err_out:
+	acpi_dev_put(adev);
 	return ret;
 }
 
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 3a82faac5767..bff6a11bb21f 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -698,11 +698,6 @@ acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv);
  * @hrv: Hardware Revision of the device, pass -1 to not check _HRV
  *
  * The caller is responsible for invoking acpi_dev_put() on the returned device.
- *
- * FIXME: Due to above requirement there is a window that may invalidate @adev
- * and next iteration will use a dangling pointer, e.g. in the case of a
- * hotplug event. That said, the caller should ensure that this will never
- * happen.
  */
 #define for_each_acpi_dev_match(adev, hid, uid, hrv)			\
 	for (adev = acpi_dev_get_first_match_dev(hid, uid, hrv);	\
-- 
2.31.1


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

* Re: [PATCH v1 1/1] ACPI: utils: Fix reference counting in for_each_acpi_dev_match()
  2021-05-19 21:02 [PATCH v1 1/1] ACPI: utils: Fix reference counting in for_each_acpi_dev_match() Andy Shevchenko
@ 2021-05-20 19:13 ` Rafael J. Wysocki
  2021-05-20 19:40   ` Rafael J. Wysocki
  0 siblings, 1 reply; 5+ messages in thread
From: Rafael J. Wysocki @ 2021-05-20 19:13 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Rafael J. Wysocki, Daniel Scally, ACPI Devel Maling List,
	Linux Kernel Mailing List, Linux Media Mailing List,
	open list:ACPI COMPONENT ARCHITECTURE (ACPICA),
	Rafael J. Wysocki, Len Brown, Yong Zhi, Sakari Ailus, Bingbu Cao,
	Tianshu Qiu, Mauro Carvalho Chehab, Robert Moore, Erik Kaneda

On Wed, May 19, 2021 at 11:19 PM Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
>
> Currently it's possible to iterate over the dangling pointer in case the device
> suddenly disappears. This may happen becase callers put it at the end of a loop.
>
> Instead, let's move that call inside acpi_dev_get_next_match_dev().

Not really.

> Fixes: 803abec64ef9 ("media: ipu3-cio2: Add cio2-bridge to ipu3-cio2 driver")
> Fixes: bf263f64e804 ("media: ACPI / bus: Add acpi_dev_get_next_match_dev() and helper macro")
> Cc: Daniel Scally <djrscally@gmail.com>
> Cc: Sakari Ailus <sakari.ailus@linux.intel.com>
> Signed-off-by: Andy Shevchenko <andy.shevchenko@gmail.com>
> ---
>  drivers/acpi/utils.c                       | 5 +----
>  drivers/media/pci/intel/ipu3/cio2-bridge.c | 8 +++-----
>  include/acpi/acpi_bus.h                    | 5 -----
>  3 files changed, 4 insertions(+), 14 deletions(-)
>
> diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
> index 3b54b8fd7396..ccfc484dbffd 100644
> --- a/drivers/acpi/utils.c
> +++ b/drivers/acpi/utils.c
> @@ -846,10 +846,6 @@ EXPORT_SYMBOL(acpi_dev_present);
>   * Return the next match of ACPI device if another matching device was present
>   * at the moment of invocation, or NULL otherwise.
>   *
> - * FIXME: The function does not tolerate the sudden disappearance of @adev, e.g.
> - * in the case of a hotplug event. That said, the caller should ensure that
> - * this will never happen.
> - *
>   * The caller is responsible for invoking acpi_dev_put() on the returned device.
>   *
>   * See additional information in acpi_dev_present() as well.
> @@ -866,6 +862,7 @@ acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const cha
>         match.hrv = hrv;
>
>         dev = bus_find_device(&acpi_bus_type, start, &match, acpi_dev_match_cb);
> +       acpi_dev_put(adev);

What's the point?

The caller may as well put it after this returns, can't it?

And what if the caller still wants to do something with adev after this returns?

>         return dev ? to_acpi_device(dev) : NULL;
>  }
>  EXPORT_SYMBOL(acpi_dev_get_next_match_dev);

The original changelog is somewhat unclear.  It should say that it is
required to reference-count the start-point device before passing it
to this function, but beyond that I don't see a bug here.

> diff --git a/drivers/media/pci/intel/ipu3/cio2-bridge.c b/drivers/media/pci/intel/ipu3/cio2-bridge.c
> index e8511787c1e4..477417261b6e 100644
> --- a/drivers/media/pci/intel/ipu3/cio2-bridge.c
> +++ b/drivers/media/pci/intel/ipu3/cio2-bridge.c
> @@ -178,13 +178,11 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,
>
>                 if (bridge->n_sensors >= CIO2_NUM_PORTS) {
>                         dev_err(&cio2->dev, "Exceeded available CIO2 ports\n");
> -                       cio2_bridge_unregister_sensors(bridge);
>                         ret = -EINVAL;
> -                       goto err_out;
> +                       goto err_put_adev;
>                 }
>
>                 sensor = &bridge->sensors[bridge->n_sensors];
> -               sensor->adev = adev;
>                 strscpy(sensor->name, cfg->hid, sizeof(sensor->name));
>
>                 ret = cio2_bridge_read_acpi_buffer(adev, "SSDB",
> @@ -214,6 +212,7 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,
>                         goto err_free_swnodes;
>                 }
>
> +               sensor->adev = acpi_dev_get(adev);
>                 adev->fwnode.secondary = fwnode;
>
>                 dev_info(&cio2->dev, "Found supported sensor %s\n",
> @@ -227,8 +226,7 @@ static int cio2_bridge_connect_sensor(const struct cio2_sensor_config *cfg,
>  err_free_swnodes:
>         software_node_unregister_nodes(sensor->swnodes);
>  err_put_adev:
> -       acpi_dev_put(sensor->adev);
> -err_out:
> +       acpi_dev_put(adev);
>         return ret;
>  }
>
> diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
> index 3a82faac5767..bff6a11bb21f 100644
> --- a/include/acpi/acpi_bus.h
> +++ b/include/acpi/acpi_bus.h
> @@ -698,11 +698,6 @@ acpi_dev_get_first_match_dev(const char *hid, const char *uid, s64 hrv);
>   * @hrv: Hardware Revision of the device, pass -1 to not check _HRV
>   *
>   * The caller is responsible for invoking acpi_dev_put() on the returned device.
> - *
> - * FIXME: Due to above requirement there is a window that may invalidate @adev
> - * and next iteration will use a dangling pointer, e.g. in the case of a
> - * hotplug event. That said, the caller should ensure that this will never
> - * happen.
>   */
>  #define for_each_acpi_dev_match(adev, hid, uid, hrv)                   \
>         for (adev = acpi_dev_get_first_match_dev(hid, uid, hrv);        \
> --
> 2.31.1
>

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

* Re: [PATCH v1 1/1] ACPI: utils: Fix reference counting in for_each_acpi_dev_match()
  2021-05-20 19:13 ` Rafael J. Wysocki
@ 2021-05-20 19:40   ` Rafael J. Wysocki
  2021-05-25 22:29     ` Daniel Scally
  0 siblings, 1 reply; 5+ messages in thread
From: Rafael J. Wysocki @ 2021-05-20 19:40 UTC (permalink / raw)
  To: Andy Shevchenko
  Cc: Rafael J. Wysocki, Daniel Scally, ACPI Devel Maling List,
	Linux Kernel Mailing List, Linux Media Mailing List,
	open list:ACPI COMPONENT ARCHITECTURE (ACPICA),
	Rafael J. Wysocki, Len Brown, Yong Zhi, Sakari Ailus, Bingbu Cao,
	Tianshu Qiu, Mauro Carvalho Chehab, Robert Moore, Erik Kaneda

On Thu, May 20, 2021 at 9:13 PM Rafael J. Wysocki <rafael@kernel.org> wrote:
>
> On Wed, May 19, 2021 at 11:19 PM Andy Shevchenko
> <andy.shevchenko@gmail.com> wrote:
> >
> > Currently it's possible to iterate over the dangling pointer in case the device
> > suddenly disappears. This may happen becase callers put it at the end of a loop.
> >
> > Instead, let's move that call inside acpi_dev_get_next_match_dev().
>
> Not really.

OK, I see what you want to achieve and the macro is actually buggy,
because it leaves unbalanced references behind.

> > Fixes: 803abec64ef9 ("media: ipu3-cio2: Add cio2-bridge to ipu3-cio2 driver")
> > Fixes: bf263f64e804 ("media: ACPI / bus: Add acpi_dev_get_next_match_dev() and helper macro")
> > Cc: Daniel Scally <djrscally@gmail.com>
> > Cc: Sakari Ailus <sakari.ailus@linux.intel.com>
> > Signed-off-by: Andy Shevchenko <andy.shevchenko@gmail.com>
> > ---
> >  drivers/acpi/utils.c                       | 5 +----
> >  drivers/media/pci/intel/ipu3/cio2-bridge.c | 8 +++-----
> >  include/acpi/acpi_bus.h                    | 5 -----
> >  3 files changed, 4 insertions(+), 14 deletions(-)
> >
> > diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
> > index 3b54b8fd7396..ccfc484dbffd 100644
> > --- a/drivers/acpi/utils.c
> > +++ b/drivers/acpi/utils.c
> > @@ -846,10 +846,6 @@ EXPORT_SYMBOL(acpi_dev_present);
> >   * Return the next match of ACPI device if another matching device was present
> >   * at the moment of invocation, or NULL otherwise.
> >   *
> > - * FIXME: The function does not tolerate the sudden disappearance of @adev, e.g.
> > - * in the case of a hotplug event. That said, the caller should ensure that
> > - * this will never happen.
> > - *
> >   * The caller is responsible for invoking acpi_dev_put() on the returned device.
> >   *
> >   * See additional information in acpi_dev_present() as well.

But the kerneldoc really needs to say that the caller is required to
obtain a reference on adev before passing it here, because that
reference will be dropped and the object pointed to by adev may not be
present any more after this returns.

> > @@ -866,6 +862,7 @@ acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const cha
> >         match.hrv = hrv;
> >
> >         dev = bus_find_device(&acpi_bus_type, start, &match, acpi_dev_match_cb);
> > +       acpi_dev_put(adev);

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

* Re: [PATCH v1 1/1] ACPI: utils: Fix reference counting in for_each_acpi_dev_match()
  2021-05-20 19:40   ` Rafael J. Wysocki
@ 2021-05-25 22:29     ` Daniel Scally
  2021-05-26  8:35       ` Andy Shevchenko
  0 siblings, 1 reply; 5+ messages in thread
From: Daniel Scally @ 2021-05-25 22:29 UTC (permalink / raw)
  To: Rafael J. Wysocki, Andy Shevchenko
  Cc: Rafael J. Wysocki, ACPI Devel Maling List,
	Linux Kernel Mailing List, Linux Media Mailing List,
	open list:ACPI COMPONENT ARCHITECTURE (ACPICA),
	Rafael J. Wysocki, Len Brown, Yong Zhi, Sakari Ailus, Bingbu Cao,
	Tianshu Qiu, Mauro Carvalho Chehab, Robert Moore, Erik Kaneda

Hi Rafael, Andy

On 20/05/2021 20:40, Rafael J. Wysocki wrote:
> On Thu, May 20, 2021 at 9:13 PM Rafael J. Wysocki <rafael@kernel.org> wrote:
>> On Wed, May 19, 2021 at 11:19 PM Andy Shevchenko
>> <andy.shevchenko@gmail.com> wrote:
>>> Currently it's possible to iterate over the dangling pointer in case the device
>>> suddenly disappears. This may happen becase callers put it at the end of a loop.
>>>
>>> Instead, let's move that call inside acpi_dev_get_next_match_dev().
>> Not really.
> OK, I see what you want to achieve and the macro is actually buggy,
> because it leaves unbalanced references behind.


Yeah; I guess the originally intended use (which was "get all these
devices") doesn't really tally with the naming or with the operation of
similar functions in the kernel like the fwnode_handle ops; sorry about
that. Anyway; I think Andy's fix is the right way to do it, so the
calling code's responsible for holding onto a reference if it wants to
keep it.

>
>>> Fixes: 803abec64ef9 ("media: ipu3-cio2: Add cio2-bridge to ipu3-cio2 driver")
>>> Fixes: bf263f64e804 ("media: ACPI / bus: Add acpi_dev_get_next_match_dev() and helper macro")
>>> Cc: Daniel Scally <djrscally@gmail.com>
>>> Cc: Sakari Ailus <sakari.ailus@linux.intel.com>
>>> Signed-off-by: Andy Shevchenko <andy.shevchenko@gmail.com>
>>> ---
>>>  drivers/acpi/utils.c                       | 5 +----
>>>  drivers/media/pci/intel/ipu3/cio2-bridge.c | 8 +++-----
>>>  include/acpi/acpi_bus.h                    | 5 -----
>>>  3 files changed, 4 insertions(+), 14 deletions(-)
>>>
>>> diff --git a/drivers/acpi/utils.c b/drivers/acpi/utils.c
>>> index 3b54b8fd7396..ccfc484dbffd 100644
>>> --- a/drivers/acpi/utils.c
>>> +++ b/drivers/acpi/utils.c
>>> @@ -846,10 +846,6 @@ EXPORT_SYMBOL(acpi_dev_present);
>>>   * Return the next match of ACPI device if another matching device was present
>>>   * at the moment of invocation, or NULL otherwise.
>>>   *
>>> - * FIXME: The function does not tolerate the sudden disappearance of @adev, e.g.
>>> - * in the case of a hotplug event. That said, the caller should ensure that
>>> - * this will never happen.
>>> - *
>>>   * The caller is responsible for invoking acpi_dev_put() on the returned device.
>>>   *
>>>   * See additional information in acpi_dev_present() as well.
> But the kerneldoc really needs to say that the caller is required to
> obtain a reference on adev before passing it here, because that
> reference will be dropped and the object pointed to by adev may not be
> present any more after this returns.
>
>>> @@ -866,6 +862,7 @@ acpi_dev_get_next_match_dev(struct acpi_device *adev, const char *hid, const cha
>>>         match.hrv = hrv;
>>>
>>>         dev = bus_find_device(&acpi_bus_type, start, &match, acpi_dev_match_cb);
>>> +       acpi_dev_put(adev);

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

* Re: [PATCH v1 1/1] ACPI: utils: Fix reference counting in for_each_acpi_dev_match()
  2021-05-25 22:29     ` Daniel Scally
@ 2021-05-26  8:35       ` Andy Shevchenko
  0 siblings, 0 replies; 5+ messages in thread
From: Andy Shevchenko @ 2021-05-26  8:35 UTC (permalink / raw)
  To: Daniel Scally
  Cc: Rafael J. Wysocki, Rafael J. Wysocki, ACPI Devel Maling List,
	Linux Kernel Mailing List, Linux Media Mailing List,
	open list:ACPI COMPONENT ARCHITECTURE (ACPICA),
	Rafael J. Wysocki, Len Brown, Yong Zhi, Sakari Ailus, Bingbu Cao,
	Tianshu Qiu, Mauro Carvalho Chehab, Robert Moore, Erik Kaneda

On Wed, May 26, 2021 at 1:29 AM Daniel Scally <djrscally@gmail.com> wrote:
> On 20/05/2021 20:40, Rafael J. Wysocki wrote:
> > On Thu, May 20, 2021 at 9:13 PM Rafael J. Wysocki <rafael@kernel.org> wrote:
> >> On Wed, May 19, 2021 at 11:19 PM Andy Shevchenko
> >> <andy.shevchenko@gmail.com> wrote:
> >>> Currently it's possible to iterate over the dangling pointer in case the device
> >>> suddenly disappears. This may happen becase callers put it at the end of a loop.
> >>>
> >>> Instead, let's move that call inside acpi_dev_get_next_match_dev().
> >> Not really.
> > OK, I see what you want to achieve and the macro is actually buggy,
> > because it leaves unbalanced references behind.
>
>
> Yeah; I guess the originally intended use (which was "get all these
> devices") doesn't really tally with the naming or with the operation of
> similar functions in the kernel like the fwnode_handle ops; sorry about
> that. Anyway; I think Andy's fix is the right way to do it, so the
> calling code's responsible for holding onto a reference if it wants to
> keep it.

I think we need to postpone the fix till v5.14-rc1 is out. It appears
that some code has been changed in EFI and media subsystems so that
patch will be in conflict with.


-- 
With Best Regards,
Andy Shevchenko

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

end of thread, other threads:[~2021-05-26  8:35 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-05-19 21:02 [PATCH v1 1/1] ACPI: utils: Fix reference counting in for_each_acpi_dev_match() Andy Shevchenko
2021-05-20 19:13 ` Rafael J. Wysocki
2021-05-20 19:40   ` Rafael J. Wysocki
2021-05-25 22:29     ` Daniel Scally
2021-05-26  8:35       ` Andy Shevchenko

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).