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

Commit 139b8214 authored by Taniya Das's avatar Taniya Das Committed by Gerrit - the friendly Code Review server
Browse files

clk: osm: Check for valid acd offset for input from debugfs



The user supplied acd offset is not verified to be within the acd register
range which could lead to out-of-bounds read/write. Fix the same by
checking the input and also make sure the acd base is present before the
read/write.

Change-Id: I9c0d9049d273633f6ef99593b1b45d98cc7c3827
Signed-off-by: default avatarTaniya Das <tdas@codeaurora.org>
parent 90076dbf
Loading
Loading
Loading
Loading
+28 −0
Original line number Diff line number Diff line
@@ -397,6 +397,7 @@ struct clk_osm {
	u32 acd_extint1_cfg;
	u32 acd_autoxfer_ctl;
	u32 acd_debugfs_addr;
	u32 acd_debugfs_addr_size;
	bool acd_init;
	bool secure_init;
	bool red_fsm_en;
@@ -1449,6 +1450,7 @@ static int clk_osm_resources_init(struct platform_device *pdev)
			return -ENOMEM;
		}
		pwrcl_clk.pbases[ACD_BASE] = pbase;
		pwrcl_clk.acd_debugfs_addr_size = resource_size(res);
		pwrcl_clk.vbases[ACD_BASE] = vbase;
		pwrcl_clk.acd_init = true;
	} else {
@@ -1466,6 +1468,7 @@ static int clk_osm_resources_init(struct platform_device *pdev)
			return -ENOMEM;
		}
		perfcl_clk.pbases[ACD_BASE] = pbase;
		perfcl_clk.acd_debugfs_addr_size = resource_size(res);
		perfcl_clk.vbases[ACD_BASE] = vbase;
		perfcl_clk.acd_init = true;
	} else {
@@ -3015,6 +3018,11 @@ static int debugfs_get_debug_reg(void *data, u64 *val)
{
	struct clk_osm *c = data;

	if (!c->pbases[ACD_BASE]) {
		pr_err("ACD base start not defined\n");
		return -EINVAL;
	}

	if (c->acd_debugfs_addr >= ACD_MASTER_ONLY_REG_ADDR)
		*val = readl_relaxed((char *)c->vbases[ACD_BASE] +
				     c->acd_debugfs_addr);
@@ -3027,6 +3035,11 @@ static int debugfs_set_debug_reg(void *data, u64 val)
{
	struct clk_osm *c = data;

	if (!c->pbases[ACD_BASE]) {
		pr_err("ACD base start not defined\n");
		return -EINVAL;
	}

	if (c->acd_debugfs_addr >= ACD_MASTER_ONLY_REG_ADDR)
		clk_osm_acd_master_write_reg(c, val, c->acd_debugfs_addr);
	else
@@ -3044,7 +3057,13 @@ static int debugfs_get_debug_reg_addr(void *data, u64 *val)
{
	struct clk_osm *c = data;

	if (!c->pbases[ACD_BASE]) {
		pr_err("ACD base start not defined\n");
		return -EINVAL;
	}

	*val = c->acd_debugfs_addr;

	return 0;
}

@@ -3052,7 +3071,16 @@ static int debugfs_set_debug_reg_addr(void *data, u64 val)
{
	struct clk_osm *c = data;

	if (!c->pbases[ACD_BASE]) {
		pr_err("ACD base start not defined\n");
		return -EINVAL;
	}

	if (val >= c->acd_debugfs_addr_size)
		return -EINVAL;

	c->acd_debugfs_addr = val;

	return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(debugfs_acd_debug_reg_addr_fops,
+27 −0
Original line number Diff line number Diff line
@@ -384,6 +384,7 @@ struct clk_osm {
	u32 acd_extint1_cfg;
	u32 acd_autoxfer_ctl;
	u32 acd_debugfs_addr;
	u32 acd_debugfs_addr_size;
	bool acd_init;
	bool secure_init;
	bool red_fsm_en;
@@ -1371,6 +1372,7 @@ static int clk_osm_resources_init(struct platform_device *pdev)
			return -ENOMEM;
		}
		pwrcl_clk.pbases[ACD_BASE] = pbase;
		pwrcl_clk.acd_debugfs_addr_size = resource_size(res);
		pwrcl_clk.vbases[ACD_BASE] = vbase;
		pwrcl_clk.acd_init = true;
	} else {
@@ -1388,6 +1390,7 @@ static int clk_osm_resources_init(struct platform_device *pdev)
			return -ENOMEM;
		}
		perfcl_clk.pbases[ACD_BASE] = pbase;
		perfcl_clk.acd_debugfs_addr_size = resource_size(res);
		perfcl_clk.vbases[ACD_BASE] = vbase;
		perfcl_clk.acd_init = true;
	} else {
@@ -2832,6 +2835,11 @@ static int debugfs_get_debug_reg(void *data, u64 *val)
{
	struct clk_osm *c = data;

	if (!c->pbases[ACD_BASE]) {
		pr_err("ACD base start not defined\n");
		return -EINVAL;
	}

	if (c->acd_debugfs_addr >= ACD_MASTER_ONLY_REG_ADDR)
		*val = readl_relaxed((char *)c->vbases[ACD_BASE] +
				     c->acd_debugfs_addr);
@@ -2844,6 +2852,11 @@ static int debugfs_set_debug_reg(void *data, u64 val)
{
	struct clk_osm *c = data;

	if (!c->pbases[ACD_BASE]) {
		pr_err("ACD base start not defined\n");
		return -EINVAL;
	}

	if (c->acd_debugfs_addr >= ACD_MASTER_ONLY_REG_ADDR)
		clk_osm_acd_master_write_reg(c, val, c->acd_debugfs_addr);
	else
@@ -2861,7 +2874,13 @@ static int debugfs_get_debug_reg_addr(void *data, u64 *val)
{
	struct clk_osm *c = data;

	if (!c->pbases[ACD_BASE]) {
		pr_err("ACD base start not defined\n");
		return -EINVAL;
	}

	*val = c->acd_debugfs_addr;

	return 0;
}

@@ -2869,6 +2888,14 @@ static int debugfs_set_debug_reg_addr(void *data, u64 val)
{
	struct clk_osm *c = data;

	if (!c->pbases[ACD_BASE]) {
		pr_err("ACD base start not defined\n");
		return -EINVAL;
	}

	if (val >= c->acd_debugfs_addr_size)
		return -EINVAL;

	c->acd_debugfs_addr = val;
	return 0;
}