Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4ad13696 authored by Sriharsha Allenki's avatar Sriharsha Allenki Committed by Gerrit - the friendly Code Review server
Browse files

pci: pci-msm: Prevent double free of default state



In the case of a linkdown during pm_suspend, the
pci_saved_state during enumeration(default_state) is
used to restore config space. But this state is freed up
during pm_resume as part of pm_load_and_free_saved_state.

And if this state (default_state) is used again in case
of another linkdown, this leads to use after free.
Fix this by using a copy of the default_state instead
of the original copy for restoring config space incase
of a linkdown.

Change-Id: I6ac763ed88341c739f0b26992d1e31bf2513fdab
Signed-off-by: default avatarSriharsha Allenki <sallenki@codeaurora.org>
parent c6efde43
Loading
Loading
Loading
Loading
+19 −6
Original line number Diff line number Diff line
@@ -7275,24 +7275,37 @@ static int msm_pcie_pm_suspend(struct pci_dev *dev,

	if (dev) {
		if (msm_pcie_confirm_linkup(pcie_dev, true, true, dev)) {
			PCIE_DBG(pcie_dev, "PCIe: RC%d: save config space\n",
					 pcie_dev->rc_idx);
			ret = pci_save_state(dev);
			if (ret) {
				PCIE_ERR(pcie_dev,
					 "PCIe: RC%d: fail to save state of RC%d:%d.\n",
					 "PCIe: RC%d: fail to save state:%d.\n",
					 pcie_dev->rc_idx, ret);
				pcie_dev->suspending = false;
				return ret;
			}

			pcie_dev->saved_state = pci_store_saved_state(dev);
		} else {
			pci_load_and_free_saved_state(dev,
						      &pcie_dev->saved_state);
			pcie_dev->saved_state = pcie_dev->default_state;
			kfree(pcie_dev->saved_state);
			pcie_dev->saved_state = NULL;

			PCIE_DBG(pcie_dev,
				 "PCIe: RC%d: saved default config space\n",
				 "PCIe: RC%d: load default config space\n",
				 pcie_dev->rc_idx);
			ret = pci_load_saved_state(dev, pcie_dev->default_state);
			if (ret) {
				PCIE_ERR(pcie_dev,
					 "PCIe: RC%d: fail to load default state:%d.\n",
					 pcie_dev->rc_idx, ret);
				pcie_dev->suspending = false;
				return ret;
			}
		}

		PCIE_DBG(pcie_dev, "PCIe: RC%d: store saved state\n",
							 pcie_dev->rc_idx);
		pcie_dev->saved_state = pci_store_saved_state(dev);
	}

	spin_lock_irqsave(&pcie_dev->cfg_lock,