Commit 7c890fd5 authored by Lucas Segarra Fernandez's avatar Lucas Segarra Fernandez Committed by Aichun Shi
Browse files

crypto: qat - validate slices count returned by FW

mainline inclusion
from mainline-v6.10-rc1
commit 483fd65ce29317044d1d00757e3fd23503b6b04c
category: feature
bugzilla: https://gitee.com/openeuler/intel-kernel/issues/I9SBWE
CVE: N/A
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=483fd65ce29317044d1d00757e3fd23503b6b04c



-------------------------------------

The function adf_send_admin_tl_start() enables the telemetry (TL)
feature on a QAT device by sending the ICP_QAT_FW_TL_START message to
the firmware. This triggers the FW to start writing TL data to a DMA
buffer in memory and returns an array containing the number of
accelerators of each type (slices) supported by this HW.
The pointer to this array is stored in the adf_tl_hw_data data
structure called slice_cnt.

The array slice_cnt is then used in the function tl_print_dev_data()
to report in debugfs only statistics about the supported accelerators.
An incorrect value of the elements in slice_cnt might lead to an out
of bounds memory read.
At the moment, there isn't an implementation of FW that returns a wrong
value, but for robustness validate the slice count array returned by FW.

Intel-SIG: commit 483fd65ce293 crypto: qat - validate slices count returned by FW
Backport to support QAT live migration for in-tree driver

Fixes: 69e7649f7cc2 ("crypto: qat - add support for device telemetry")
Signed-off-by: default avatarLucas Segarra Fernandez <lucas.segarra.fernandez@intel.com>
Reviewed-by: default avatarDamian Muszynski <damian.muszynski@intel.com>
Reviewed-by: default avatarGiovanni Cabiddu <giovanni.cabiddu@intel.com>
Signed-off-by: default avatarHerbert Xu <herbert@gondor.apana.org.au>
[ Aichun Shi: amend commit log ]
Signed-off-by: default avatarAichun Shi <aichun.shi@intel.com>
parent 2106bafa
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -149,5 +149,6 @@ void adf_gen4_init_tl_data(struct adf_tl_hw_data *tl_data)
	tl_data->sl_exec_counters = sl_exec_counters;
	tl_data->rp_counters = rp_counters;
	tl_data->num_rp_counters = ARRAY_SIZE(rp_counters);
	tl_data->max_sl_cnt = ADF_GEN4_TL_MAX_SLICES_PER_TYPE;
}
EXPORT_SYMBOL_GPL(adf_gen4_init_tl_data);
+21 −0
Original line number Diff line number Diff line
@@ -41,6 +41,20 @@ static int validate_tl_data(struct adf_tl_hw_data *tl_data)
	return 0;
}

static int validate_tl_slice_counters(struct icp_qat_fw_init_admin_slice_cnt *slice_count,
				      u8 max_slices_per_type)
{
	u8 *sl_counter = (u8 *)slice_count;
	int i;

	for (i = 0; i < ADF_TL_SL_CNT_COUNT; i++) {
		if (sl_counter[i] > max_slices_per_type)
			return -EINVAL;
	}

	return 0;
}

static int adf_tl_alloc_mem(struct adf_accel_dev *accel_dev)
{
	struct adf_tl_hw_data *tl_data = &GET_TL_DATA(accel_dev);
@@ -214,6 +228,13 @@ int adf_tl_run(struct adf_accel_dev *accel_dev, int state)
		return ret;
	}

	ret = validate_tl_slice_counters(&telemetry->slice_cnt, tl_data->max_sl_cnt);
	if (ret) {
		dev_err(dev, "invalid value returned by FW\n");
		adf_send_admin_tl_stop(accel_dev);
		return ret;
	}

	telemetry->hbuffs = state;
	atomic_set(&telemetry->state, state);

+1 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ struct adf_tl_hw_data {
	u8 num_dev_counters;
	u8 num_rp_counters;
	u8 max_rp;
	u8 max_sl_cnt;
};

struct adf_telemetry {