diff options
author | Vince Kim <vince.k.kim@gmail.com> | 2017-10-31 11:33:40 -0700 |
---|---|---|
committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2017-11-03 12:45:22 -0700 |
commit | a2c714e8cb538406d61e321c627b55ed5362991e (patch) | |
tree | 964e518713b0235dc23948ff6ac2f1ac0c86e063 /drivers/input | |
parent | 11772c9c185735e244731e23b1983d5c7ab03c80 (diff) |
Input: cyttsp4 - avoid overflows when calculating memory sizes
There are several places to perform subtraction to calculate buffer
size such as:
si->si_ofs.cydata_size = si->si_ofs.test_ofs - si->si_ofs.cydata_ofs;
...
p = krealloc(si->si_ptrs.cydata, si->si_ofs.cydata_size, GFP_KERNEL);
Actually, data types of above variables during subtraction are size_t, so
it is unsigned. That means if second operand(si->si_ofs.cydata_ofs) is
greater than the first operand(si->si_ofs.test_ofs), then resulting
si->si_ofs.cydata_size could result in an unsigned integer wrap which is
not desirable.
The proper way to correct this problem is to perform a test of both
operands to avoid having unsigned wrap.
Signed-off-by: Vince Kim <vince.k.kim@gmail.com>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input')
-rw-r--r-- | drivers/input/touchscreen/cyttsp4_core.c | 52 |
1 files changed, 40 insertions, 12 deletions
diff --git a/drivers/input/touchscreen/cyttsp4_core.c b/drivers/input/touchscreen/cyttsp4_core.c index e7710397e0ad..727c3232517c 100644 --- a/drivers/input/touchscreen/cyttsp4_core.c +++ b/drivers/input/touchscreen/cyttsp4_core.c @@ -201,13 +201,21 @@ static int cyttsp4_si_get_cydata(struct cyttsp4 *cd) void *p; int rc; + if (si->si_ofs.test_ofs <= si->si_ofs.cydata_ofs) { + dev_err(cd->dev, + "%s: invalid offset test_ofs: %zu, cydata_ofs: %zu\n", + __func__, si->si_ofs.test_ofs, si->si_ofs.cydata_ofs); + return -EINVAL; + } + si->si_ofs.cydata_size = si->si_ofs.test_ofs - si->si_ofs.cydata_ofs; dev_dbg(cd->dev, "%s: cydata size: %zd\n", __func__, si->si_ofs.cydata_size); p = krealloc(si->si_ptrs.cydata, si->si_ofs.cydata_size, GFP_KERNEL); if (p == NULL) { - dev_err(cd->dev, "%s: fail alloc cydata memory\n", __func__); + dev_err(cd->dev, "%s: failed to allocate cydata memory\n", + __func__); return -ENOMEM; } si->si_ptrs.cydata = p; @@ -270,11 +278,19 @@ static int cyttsp4_si_get_test_data(struct cyttsp4 *cd) void *p; int rc; + if (si->si_ofs.pcfg_ofs <= si->si_ofs.test_ofs) { + dev_err(cd->dev, + "%s: invalid offset pcfg_ofs: %zu, test_ofs: %zu\n", + __func__, si->si_ofs.pcfg_ofs, si->si_ofs.test_ofs); + return -EINVAL; + } + si->si_ofs.test_size = si->si_ofs.pcfg_ofs - si->si_ofs.test_ofs; p = krealloc(si->si_ptrs.test, si->si_ofs.test_size, GFP_KERNEL); if (p == NULL) { - dev_err(cd->dev, "%s: fail alloc test memory\n", __func__); + dev_err(cd->dev, "%s: failed to allocate test memory\n", + __func__); return -ENOMEM; } si->si_ptrs.test = p; @@ -321,14 +337,20 @@ static int cyttsp4_si_get_pcfg_data(struct cyttsp4 *cd) void *p; int rc; + if (si->si_ofs.opcfg_ofs <= si->si_ofs.pcfg_ofs) { + dev_err(cd->dev, + "%s: invalid offset opcfg_ofs: %zu, pcfg_ofs: %zu\n", + __func__, si->si_ofs.opcfg_ofs, si->si_ofs.pcfg_ofs); + return -EINVAL; + } + si->si_ofs.pcfg_size = si->si_ofs.opcfg_ofs - si->si_ofs.pcfg_ofs; p = krealloc(si->si_ptrs.pcfg, si->si_ofs.pcfg_size, GFP_KERNEL); if (p == NULL) { - rc = -ENOMEM; - dev_err(cd->dev, "%s: fail alloc pcfg memory r=%d\n", - __func__, rc); - return rc; + dev_err(cd->dev, "%s: failed to allocate pcfg memory\n", + __func__); + return -ENOMEM; } si->si_ptrs.pcfg = p; @@ -367,13 +389,20 @@ static int cyttsp4_si_get_opcfg_data(struct cyttsp4 *cd) void *p; int rc; + if (si->si_ofs.ddata_ofs <= si->si_ofs.opcfg_ofs) { + dev_err(cd->dev, + "%s: invalid offset ddata_ofs: %zu, opcfg_ofs: %zu\n", + __func__, si->si_ofs.ddata_ofs, si->si_ofs.opcfg_ofs); + return -EINVAL; + } + si->si_ofs.opcfg_size = si->si_ofs.ddata_ofs - si->si_ofs.opcfg_ofs; p = krealloc(si->si_ptrs.opcfg, si->si_ofs.opcfg_size, GFP_KERNEL); if (p == NULL) { - dev_err(cd->dev, "%s: fail alloc opcfg memory\n", __func__); - rc = -ENOMEM; - goto cyttsp4_si_get_opcfg_data_exit; + dev_err(cd->dev, "%s: failed to allocate opcfg memory\n", + __func__); + return -ENOMEM; } si->si_ptrs.opcfg = p; @@ -382,7 +411,7 @@ static int cyttsp4_si_get_opcfg_data(struct cyttsp4 *cd) if (rc < 0) { dev_err(cd->dev, "%s: fail read opcfg data r=%d\n", __func__, rc); - goto cyttsp4_si_get_opcfg_data_exit; + return rc; } si->si_ofs.cmd_ofs = si->si_ptrs.opcfg->cmd_ofs; si->si_ofs.rep_ofs = si->si_ptrs.opcfg->rep_ofs; @@ -447,8 +476,7 @@ static int cyttsp4_si_get_opcfg_data(struct cyttsp4 *cd) cyttsp4_pr_buf(cd->dev, cd->pr_buf, (u8 *)si->si_ptrs.opcfg, si->si_ofs.opcfg_size, "sysinfo_opcfg_data"); -cyttsp4_si_get_opcfg_data_exit: - return rc; + return 0; } static int cyttsp4_si_get_ddata(struct cyttsp4 *cd) |