Skip to content

Commit

Permalink
clk: osm: Check for valid acd offset for input from debugfs
Browse files Browse the repository at this point in the history
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: Taniya Das <tdas@codeaurora.org>
  • Loading branch information
Taniya Das authored and Gerrit - the friendly Code Review server committed Aug 28, 2017
1 parent 90076db commit 139b821
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 0 deletions.
28 changes: 28 additions & 0 deletions drivers/clk/msm/clock-osm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand All @@ -3044,15 +3057,30 @@ 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;
}

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,
Expand Down
27 changes: 27 additions & 0 deletions drivers/clk/qcom/clk-cpu-osm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
Expand Down Expand Up @@ -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);
Expand All @@ -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
Expand All @@ -2861,14 +2874,28 @@ 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;
}

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;
}
Expand Down

0 comments on commit 139b821

Please sign in to comment.