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

Commit 127b461c authored by osaisruj's avatar osaisruj Committed by Nirmal Abraham
Browse files

disp: msm: dp: validate edid before dereferencing



Currently, when using custom edid from debugfs, the
extensions data inside the edid block is not validated
before dereferencing the extension block.

The fix adds a edid validation function to validate
any custom edids before accessing any members in the
edid block.

Change-Id: I65e596cd6743febd5d55d968908619ebd50bef29
Signed-off-by: default avatarosaisruj <osaisruj@codeaurora.org>
parent df61ff22
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -233,7 +233,7 @@ static ssize_t dp_debug_write_edid(struct file *file,
	edid = debug->edid;
bail:
	kfree(buf);
	debug->panel->set_edid(debug->panel, edid);
	debug->panel->set_edid(debug->panel, edid, debug->edid_size);

	/*
	 * print edid status as this code is executed
@@ -1580,7 +1580,7 @@ static void dp_debug_set_sim_mode(struct dp_debug_private *debug, bool sim)
		debug->dp_debug.sim_mode = false;
		debug->dp_debug.mst_hpd_sim = false;

		debug->panel->set_edid(debug->panel, 0);
		debug->panel->set_edid(debug->panel, NULL, 0);
		if (debug->edid) {
			devm_kfree(debug->dev, debug->edid);
			debug->edid = NULL;
+19 −2
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

#include "dp_panel.h"
#include <drm/drm_fixed.h>
#include <drm/drm_edid.h>

#define DP_KHZ_TO_HZ 1000
#define DP_PANEL_DEFAULT_BPP 24
@@ -1707,8 +1708,24 @@ static int dp_panel_set_default_link_params(struct dp_panel *dp_panel)

	return 0;
}
static int dp_panel_validate_edid(struct edid *edid, size_t edid_size)
{
	if (!edid || (edid_size < EDID_LENGTH))
		return false;

	if (EDID_LENGTH * (edid->extensions + 1) > edid_size) {
		pr_err("edid size does not match allocated.\n");
		return false;
	}
	if (!drm_edid_is_valid(edid)) {
		pr_err("invalid edid.\n");
		return false;
	}
	return true;
}

static int dp_panel_set_edid(struct dp_panel *dp_panel, u8 *edid)
static int dp_panel_set_edid(struct dp_panel *dp_panel, u8 *edid,
		size_t edid_size)
{
	struct dp_panel_private *panel;

@@ -1719,7 +1736,7 @@ static int dp_panel_set_edid(struct dp_panel *dp_panel, u8 *edid)

	panel = container_of(dp_panel, struct dp_panel_private, dp_panel);

	if (edid) {
	if (edid && dp_panel_validate_edid((struct edid *)edid, edid_size)) {
		dp_panel->edid_ctrl->edid = (struct edid *)edid;
		panel->custom_edid = true;
	} else {
+2 −2
Original line number Diff line number Diff line
/*
 * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -152,7 +152,7 @@ struct dp_panel {
	int (*get_modes)(struct dp_panel *dp_panel,
		struct drm_connector *connector, struct dp_display_mode *mode);
	void (*handle_sink_request)(struct dp_panel *dp_panel);
	int (*set_edid)(struct dp_panel *dp_panel, u8 *edid);
	int (*set_edid)(struct dp_panel *dp_panel, u8 *edid, size_t edid_size);
	int (*set_dpcd)(struct dp_panel *dp_panel, u8 *dpcd);
	int (*setup_hdr)(struct dp_panel *dp_panel,
		struct drm_msm_ext_hdr_metadata *hdr_meta);