PCI: hotplug: ACPI: Fix context refcounting in acpiphp_grab_context()
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>
Fri, 26 Jun 2020 17:42:34 +0000 (19:42 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 21 Aug 2020 09:02:07 +0000 (11:02 +0200)
commit dae68d7fd4930315389117e9da35b763f12238f9 upstream.

If context is not NULL in acpiphp_grab_context(), but the
is_going_away flag is set for the device's parent, the reference
counter of the context needs to be decremented before returning
NULL or the context will never be freed, so make that happen.

Fixes: edf5bf34d408 ("ACPI / dock: Use callback pointers from devices' ACPI hotplug contexts")
Reported-by: Vasily Averin <vvs@virtuozzo.com>
Cc: 3.15+ <stable@vger.kernel.org> # 3.15+
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/pci/hotplug/acpiphp_glue.c

index d44b55879c673dec27e7f46a66f33516d8472b8d..7f2b9ef185e4486c446cfd844c980540c8694dd4 100644 (file)
@@ -136,13 +136,21 @@ static struct acpiphp_context *acpiphp_grab_context(struct acpi_device *adev)
        struct acpiphp_context *context;
 
        acpi_lock_hp_context();
+
        context = acpiphp_get_context(adev);
-       if (!context || context->func.parent->is_going_away) {
-               acpi_unlock_hp_context();
-               return NULL;
+       if (!context)
+               goto unlock;
+
+       if (context->func.parent->is_going_away) {
+               acpiphp_put_context(context);
+               context = NULL;
+               goto unlock;
        }
+
        get_bridge(context->func.parent);
        acpiphp_put_context(context);
+
+unlock:
        acpi_unlock_hp_context();
        return context;
 }