Commit fdb70083 authored by Johannes Berg's avatar Johannes Berg Committed by Luca Coelho
Browse files

iwlwifi: fw dump: add infrastructure for dump scrubbing



In firmware dumps, currently all kinds of key material may be
included, e.g. in host commands (if firmware crashes during the
processing of a key-related command) or in the TX FIFO(s) if
we have been using in-TX-command key material.

Additionally, some firmware versions will advertise sections
of their internal data to not dump, due to them containing some
sensitive data.

Add some infrastructure to allow scrubbing this data out, as
dependent on the opmode's idea of what will need to be done.

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.20211017123741.360cc8fe55b1.Ie3bd3ece38043969f7e116e61a6ec1197a58d78b@changeid


Signed-off-by: default avatarLuca Coelho <luciano.coelho@intel.com>
parent 4634b176
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@

#include <linux/bitops.h>

#define IWL_FW_INI_HW_SMEM_REGION_ID		15
#define IWL_FW_INI_MAX_REGION_ID		64
#define IWL_FW_INI_MAX_NAME			32
#define IWL_FW_INI_MAX_CFG_NAME			64
+41 −3
Original line number Diff line number Diff line
@@ -159,11 +159,15 @@ static void iwl_fwrt_dump_txf(struct iwl_fw_runtime *fwrt,
	iwl_trans_read_prph(fwrt->trans, TXF_READ_MODIFY_DATA + offset);

	/* Read FIFO */
	fifo_len /= sizeof(u32); /* Size in DWORDS */
	for (i = 0; i < fifo_len; i++)
	for (i = 0; i < fifo_len / sizeof(u32); i++)
		fifo_data[i] = iwl_trans_read_prph(fwrt->trans,
						  TXF_READ_MODIFY_DATA +
						  offset);

	if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_txf)
		fwrt->sanitize_ops->frob_txf(fwrt->sanitize_ctx,
					     fifo_data, fifo_len);

	*dump_data = iwl_fw_error_next_data(*dump_data);
}

@@ -659,6 +663,10 @@ static void iwl_fw_dump_mem(struct iwl_fw_runtime *fwrt,
	iwl_trans_read_mem_bytes(fwrt->trans, ofs, dump_mem->data, len);
	*dump_data = iwl_fw_error_next_data(*dump_data);

	if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem)
		fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx, ofs,
					     dump_mem->data, len);

	IWL_DEBUG_INFO(fwrt, "WRT memory dump. Type=%u\n", dump_mem->type);
}

@@ -752,6 +760,12 @@ static void iwl_dump_paging(struct iwl_fw_runtime *fwrt,
					   PAGING_BLOCK_SIZE,
					   DMA_BIDIRECTIONAL);
		(*data) = iwl_fw_error_next_data(*data);

		if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem)
			fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx,
						     fwrt->fw_paging_db[i].fw_offs,
						     paging->data,
						     PAGING_BLOCK_SIZE);
	}
}

@@ -980,6 +994,11 @@ iwl_fw_error_dump_file(struct iwl_fw_runtime *fwrt,
					 dump_data->data + data_size,
					 data_size);

		if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem)
			fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx, addr,
						     dump_data->data + data_size,
						     data_size);

		dump_data = iwl_fw_error_next_data(dump_data);
	}

@@ -1146,6 +1165,13 @@ static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt,
	iwl_trans_read_mem_bytes(fwrt->trans, addr, range->data,
				 le32_to_cpu(reg->dev_addr.size));

	if ((le32_to_cpu(reg->id) & IWL_FW_INI_REGION_V2_MASK) ==
		IWL_FW_INI_HW_SMEM_REGION_ID &&
	    fwrt->sanitize_ops && fwrt->sanitize_ops->frob_txf)
		fwrt->sanitize_ops->frob_txf(fwrt->sanitize_ctx,
					     range->data,
					     le32_to_cpu(reg->dev_addr.size));

	return sizeof(*range) + le32_to_cpu(range->range_data_size);
}

@@ -1338,6 +1364,10 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt,
	for (i = 0; i < iter->fifo_size; i += sizeof(*data))
		*data++ = cpu_to_le32(iwl_read_prph_no_grab(fwrt->trans, addr));

	if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_txf)
		fwrt->sanitize_ops->frob_txf(fwrt->sanitize_ctx,
					     reg_dump, iter->fifo_size);

out:
	iwl_trans_release_nic_access(fwrt->trans);

@@ -2360,7 +2390,9 @@ static void iwl_fw_error_dump(struct iwl_fw_runtime *fwrt,
	if (dump_data->monitor_only)
		dump_mask &= BIT(IWL_FW_ERROR_DUMP_FW_MONITOR);

	fw_error_dump.trans_ptr = iwl_trans_dump_data(fwrt->trans, dump_mask);
	fw_error_dump.trans_ptr = iwl_trans_dump_data(fwrt->trans, dump_mask,
						      fwrt->sanitize_ops,
						      fwrt->sanitize_ctx);
	file_len = le32_to_cpu(dump_file->file_len);
	fw_error_dump.fwrt_len = file_len;

@@ -2788,6 +2820,12 @@ void iwl_fw_dbg_read_d3_debug_data(struct iwl_fw_runtime *fwrt)
	iwl_trans_read_mem_bytes(fwrt->trans, cfg->d3_debug_data_base_addr,
				 fwrt->dump.d3_debug_data,
				 cfg->d3_debug_data_length);

	if (fwrt->sanitize_ops && fwrt->sanitize_ops->frob_mem)
		fwrt->sanitize_ops->frob_mem(fwrt->sanitize_ctx,
					     cfg->d3_debug_data_base_addr,
					     fwrt->dump.d3_debug_data,
					     cfg->d3_debug_data_length);
}
IWL_EXPORT_SYMBOL(iwl_fw_dbg_read_d3_debug_data);

+2 −0
Original line number Diff line number Diff line
@@ -124,11 +124,13 @@ struct fw_img {
 * @fw_paging_phys: page phy pointer
 * @fw_paging_block: pointer to the allocated block
 * @fw_paging_size: page size
 * @fw_offs: offset in the device
 */
struct iwl_fw_paging {
	dma_addr_t fw_paging_phys;
	struct page *fw_paging_block;
	u32 fw_paging_size;
	u32 fw_offs;
};

/**
+5 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
 * Copyright (C) 2017 Intel Deutschland GmbH
 * Copyright (C) 2019-2020 Intel Corporation
 * Copyright (C) 2019-2021 Intel Corporation
 */
#include "iwl-drv.h"
#include "runtime.h"
@@ -16,6 +16,8 @@
void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
			const struct iwl_fw *fw,
			const struct iwl_fw_runtime_ops *ops, void *ops_ctx,
			const struct iwl_dump_sanitize_ops *sanitize_ops,
			void *sanitize_ctx,
			struct dentry *dbgfs_dir)
{
	int i;
@@ -26,6 +28,8 @@ void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans,
	fwrt->dev = trans->dev;
	fwrt->dump.conf = FW_DBG_INVALID;
	fwrt->ops = ops;
	fwrt->sanitize_ops = sanitize_ops;
	fwrt->sanitize_ctx = sanitize_ctx;
	fwrt->ops_ctx = ops_ctx;
	for (i = 0; i < IWL_FW_RUNTIME_DUMP_WK_NUM; i++) {
		fwrt->dump.wks[i].idx = i;
+3 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
 * Copyright (C) 2012-2014, 2018-2019 Intel Corporation
 * Copyright (C) 2012-2014, 2018-2019, 2021 Intel Corporation
 * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
 * Copyright (C) 2016-2017 Intel Deutschland GmbH
 */
@@ -152,6 +152,7 @@ static int iwl_fill_paging_mem(struct iwl_fw_runtime *fwrt,
	memcpy(page_address(fwrt->fw_paging_db[0].fw_paging_block),
	       image->sec[sec_idx].data,
	       image->sec[sec_idx].len);
	fwrt->fw_paging_db[0].fw_offs = image->sec[sec_idx].offset;
	dma_sync_single_for_device(fwrt->trans->dev,
				   fwrt->fw_paging_db[0].fw_paging_phys,
				   fwrt->fw_paging_db[0].fw_paging_size,
@@ -197,6 +198,7 @@ static int iwl_fill_paging_mem(struct iwl_fw_runtime *fwrt,

		memcpy(page_address(block->fw_paging_block),
		       image->sec[sec_idx].data + offset, len);
		block->fw_offs = image->sec[sec_idx].offset + offset;
		dma_sync_single_for_device(fwrt->trans->dev,
					   block->fw_paging_phys,
					   block->fw_paging_size,
Loading