]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
powerpc/eeh: Fix use-after-release of EEH driver
authorSam Bobroff <sbobroff@linux.ibm.com>
Fri, 25 May 2018 03:11:30 +0000 (13:11 +1000)
committerStefan Bader <stefan.bader@canonical.com>
Fri, 1 Mar 2019 13:20:32 +0000 (14:20 +0100)
BugLink: http://bugs.launchpad.net/bugs/1815234
[ Upstream commit 46d4be41b987a6b2d25a2ebdd94cafb44e21d6c5 ]

Correct two cases where eeh_pcid_get() is used to reference the driver's
module but the reference is dropped before the driver pointer is used.

In eeh_rmv_device() also refactor a little so that only two calls to
eeh_pcid_put() are needed, rather than three and the reference isn't
taken at all if it wasn't needed.

Signed-off-by: Sam Bobroff <sbobroff@linux.ibm.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
arch/powerpc/kernel/eeh_driver.c

index ea62e95b22a8ed8f27e14ba746058d846e259830..546cc8f46055b68be7e4b7c8dd75656890e453ef 100644 (file)
@@ -450,9 +450,11 @@ static void *eeh_add_virt_device(void *data, void *userdata)
 
        driver = eeh_pcid_get(dev);
        if (driver) {
-               eeh_pcid_put(dev);
-               if (driver->err_handler)
+               if (driver->err_handler) {
+                       eeh_pcid_put(dev);
                        return NULL;
+               }
+               eeh_pcid_put(dev);
        }
 
 #ifdef CONFIG_PPC_POWERNV
@@ -489,17 +491,19 @@ static void *eeh_rmv_device(void *data, void *userdata)
        if (eeh_dev_removed(edev))
                return NULL;
 
-       driver = eeh_pcid_get(dev);
-       if (driver) {
-               eeh_pcid_put(dev);
-               if (removed &&
-                   eeh_pe_passed(edev->pe))
-                       return NULL;
-               if (removed &&
-                   driver->err_handler &&
-                   driver->err_handler->error_detected &&
-                   driver->err_handler->slot_reset)
+       if (removed) {
+               if (eeh_pe_passed(edev->pe))
                        return NULL;
+               driver = eeh_pcid_get(dev);
+               if (driver) {
+                       if (driver->err_handler &&
+                           driver->err_handler->error_detected &&
+                           driver->err_handler->slot_reset) {
+                               eeh_pcid_put(dev);
+                               return NULL;
+                       }
+                       eeh_pcid_put(dev);
+               }
        }
 
        /* Remove it from PCI subsystem */