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

Commit 0446cafa authored by Johannes Berg's avatar Johannes Berg Committed by Greg Kroah-Hartman
Browse files

iwlwifi: fix leaks/bad data after failed firmware load



[ Upstream commit ab07506b0454bea606095951e19e72c282bfbb42 ]

If firmware load fails after having loaded some parts of the
firmware, e.g. the IML image, then this would leak. For the
host command list we'd end up running into a WARN on the next
attempt to load another firmware image.

Fix this by calling iwl_dealloc_ucode() on failures, and make
that also clear the data so we start fresh on the next round.

Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Link: https://lore.kernel.org/r/iwlwifi.20211210110539.1f742f0eb58a.I1315f22f6aa632d94ae2069f85e1bca5e734dce0@changeid


Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
parent c8fe499c
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -183,6 +183,9 @@ static void iwl_dealloc_ucode(struct iwl_drv *drv)

	for (i = 0; i < IWL_UCODE_TYPE_MAX; i++)
		iwl_free_fw_img(drv, drv->fw.img + i);

	/* clear the data for the aborted load case */
	memset(&drv->fw, 0, sizeof(drv->fw));
}

static int iwl_alloc_fw_desc(struct iwl_drv *drv, struct fw_desc *desc,
@@ -1338,6 +1341,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
	int i;
	bool load_module = false;
	bool usniffer_images = false;
	bool failure = true;

	fw->ucode_capa.max_probe_length = IWL_DEFAULT_MAX_PROBE_LENGTH;
	fw->ucode_capa.standard_phy_calibration_size =
@@ -1604,6 +1608,7 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
				op->name, err);
#endif
	}
	failure = false;
	goto free;

 try_again:
@@ -1619,6 +1624,9 @@ static void iwl_req_fw_callback(const struct firmware *ucode_raw, void *context)
	complete(&drv->request_firmware_complete);
	device_release_driver(drv->trans->dev);
 free:
	if (failure)
		iwl_dealloc_ucode(drv);

	if (pieces) {
		for (i = 0; i < ARRAY_SIZE(pieces->img); i++)
			kfree(pieces->img[i].sec);