summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/intel/iwlwifi/fw
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2021-10-17 12:40:11 +0300
committerLuca Coelho <luciano.coelho@intel.com>2021-10-22 10:48:59 +0300
commitfdb70083dd2886e45dc2575b8b21dbf63505c29b (patch)
treeac54a29b1f1a6ccfe23a4d1d04ebf51c4dfdada1 /drivers/net/wireless/intel/iwlwifi/fw
parent4634b176810400be041ea106f03e4f013ddabc1b (diff)
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: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Luca Coelho <luciano.coelho@intel.com> Link: https://lore.kernel.org/r/iwlwifi.20211017123741.360cc8fe55b1.Ie3bd3ece38043969f7e116e61a6ec1197a58d78b@changeid Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/fw')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/dbg.c44
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/img.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/init.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/paging.c4
-rw-r--r--drivers/net/wireless/intel/iwlwifi/fw/runtime.h5
6 files changed, 57 insertions, 5 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h
index d8b5870d6e9a..6ab5755beb53 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h
@@ -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
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
index b7f2f0662b82..a39013c401c9 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c
@@ -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);
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/img.h b/drivers/net/wireless/intel/iwlwifi/fw/img.h
index 21a206631b2f..6099d1edaff2 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/img.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/img.h
@@ -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;
};
/**
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/init.c b/drivers/net/wireless/intel/iwlwifi/fw/init.c
index 2ecec00db9da..566957ac4539 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/init.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/init.c
@@ -1,7 +1,7 @@
// 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;
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/paging.c b/drivers/net/wireless/intel/iwlwifi/fw/paging.c
index 4a8fe9641a32..58ca3849d1f3 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/paging.c
+++ b/drivers/net/wireless/intel/iwlwifi/fw/paging.c
@@ -1,6 +1,6 @@
// 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,
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
index 35af85a5430b..a569ce3c5e96 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h
@@ -105,6 +105,9 @@ struct iwl_fw_runtime {
const struct iwl_fw_runtime_ops *ops;
void *ops_ctx;
+ const struct iwl_dump_sanitize_ops *sanitize_ops;
+ void *sanitize_ctx;
+
/* Paging */
struct iwl_fw_paging fw_paging_db[NUM_OF_FW_PAGING_BLOCKS];
u16 num_of_paging_blk;
@@ -161,6 +164,8 @@ struct iwl_fw_runtime {
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);
static inline void iwl_fw_runtime_free(struct iwl_fw_runtime *fwrt)