Commit 00a33be4 authored by Gao, Fred's avatar Gao, Fred Committed by Zhenyu Wang
Browse files

drm/i915/gvt: Add valid length check for MI variable commands



Add valid length check for the commands with variable length.

v2: remove the macro definition. (Zhenyu)
v3: refine the LRI command. (Zhenyu)

Reviewed-by: default avatarZhenyu Wang <zhenyuw@linux.intel.com>
Signed-off-by: default avatarGao, Fred <fred.gao@intel.com>
Signed-off-by: default avatarZhenyu Wang <zhenyuw@linux.intel.com>
parent 1e2adc0d
Loading
Loading
Loading
Loading
+52 −0
Original line number Diff line number Diff line
@@ -374,6 +374,9 @@ typedef int (*parser_cmd_handler)(struct parser_exec_state *s);
#define ADDR_FIX_4(x1, x2, x3, x4)	(ADDR_FIX_1(x1) | ADDR_FIX_3(x2, x3, x4))
#define ADDR_FIX_5(x1, x2, x3, x4, x5)  (ADDR_FIX_1(x1) | ADDR_FIX_4(x2, x3, x4, x5))

#define DWORD_FIELD(dword, end, start) \
	FIELD_GET(GENMASK(end, start), cmd_val(s, dword))

#define OP_LENGTH_BIAS 2
#define CMD_LEN(value)  (value + OP_LENGTH_BIAS)

@@ -960,6 +963,18 @@ static int cmd_handler_lri(struct parser_exec_state *s)
	int i, ret = 0;
	int cmd_len = cmd_length(s);
	struct intel_gvt *gvt = s->vgpu->gvt;
	u32 valid_len = CMD_LEN(1);

	/*
	 * Official intel docs are somewhat sloppy , check the definition of
	 * MI_LOAD_REGISTER_IMM.
	 */
	#define MAX_VALID_LEN 127
	if ((cmd_len < valid_len) || (cmd_len > MAX_VALID_LEN)) {
		gvt_err("len is not valid:  len=%u  valid_len=%u\n",
			cmd_len, valid_len);
		return -EFAULT;
	}

	for (i = 1; i < cmd_len; i += 2) {
		if (IS_BROADWELL(gvt->dev_priv) && s->ring_id != RCS0) {
@@ -1391,6 +1406,15 @@ static int cmd_handler_mi_display_flip(struct parser_exec_state *s)
	int ret;
	int i;
	int len = cmd_length(s);
	u32 valid_len = CMD_LEN(1);

	/* Flip Type == Stereo 3D Flip */
	if (DWORD_FIELD(2, 1, 0) == 2)
		valid_len++;
	ret = gvt_check_valid_cmd_length(cmd_length(s),
			valid_len);
	if (ret)
		return ret;

	ret = decode_mi_display_flip(s, &info);
	if (ret) {
@@ -1510,12 +1534,21 @@ static int cmd_handler_mi_store_data_imm(struct parser_exec_state *s)
	int op_size = (cmd_length(s) - 3) * sizeof(u32);
	int core_id = (cmd_val(s, 2) & (1 << 0)) ? 1 : 0;
	unsigned long gma, gma_low, gma_high;
	u32 valid_len = CMD_LEN(2);
	int ret = 0;

	/* check ppggt */
	if (!(cmd_val(s, 0) & (1 << 22)))
		return 0;

	/* check if QWORD */
	if (DWORD_FIELD(0, 21, 21))
		valid_len++;
	ret = gvt_check_valid_cmd_length(cmd_length(s),
			valid_len);
	if (ret)
		return ret;

	gma = cmd_val(s, 2) & GENMASK(31, 2);

	if (gmadr_bytes == 8) {
@@ -1558,11 +1591,20 @@ static int cmd_handler_mi_op_2f(struct parser_exec_state *s)
	int op_size = (1 << ((cmd_val(s, 0) & GENMASK(20, 19)) >> 19)) *
			sizeof(u32);
	unsigned long gma, gma_high;
	u32 valid_len = CMD_LEN(1);
	int ret = 0;

	if (!(cmd_val(s, 0) & (1 << 22)))
		return ret;

	/* check if QWORD */
	if (DWORD_FIELD(0, 20, 19) == 1)
		valid_len += 8;
	ret = gvt_check_valid_cmd_length(cmd_length(s),
			valid_len);
	if (ret)
		return ret;

	gma = cmd_val(s, 1) & GENMASK(31, 2);
	if (gmadr_bytes == 8) {
		gma_high = cmd_val(s, 2) & GENMASK(15, 0);
@@ -1600,6 +1642,16 @@ static int cmd_handler_mi_flush_dw(struct parser_exec_state *s)
	bool index_mode = false;
	int ret = 0;
	u32 hws_pga, val;
	u32 valid_len = CMD_LEN(2);

	ret = gvt_check_valid_cmd_length(cmd_length(s),
			valid_len);
	if (ret) {
		/* Check again for Qword */
		ret = gvt_check_valid_cmd_length(cmd_length(s),
			++valid_len);
		return ret;
	}

	/* Check post-sync and ppgtt bit */
	if (((cmd_val(s, 0) >> 14) & 0x3) && (cmd_val(s, 1) & (1 << 2))) {