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

Commit a2c714e8 authored by Vince Kim's avatar Vince Kim Committed by Dmitry Torokhov
Browse files

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: default avatarVince Kim <vince.k.kim@gmail.com>
Signed-off-by: default avatarDmitry Torokhov <dmitry.torokhov@gmail.com>
parent 11772c9c
Loading
Loading
Loading
Loading
+40 −12
Original line number Original line Diff line number Diff line
@@ -201,13 +201,21 @@ static int cyttsp4_si_get_cydata(struct cyttsp4 *cd)
	void *p;
	void *p;
	int rc;
	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;
	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__,
	dev_dbg(cd->dev, "%s: cydata size: %zd\n", __func__,
			si->si_ofs.cydata_size);
			si->si_ofs.cydata_size);


	p = krealloc(si->si_ptrs.cydata, si->si_ofs.cydata_size, GFP_KERNEL);
	p = krealloc(si->si_ptrs.cydata, si->si_ofs.cydata_size, GFP_KERNEL);
	if (p == NULL) {
	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;
		return -ENOMEM;
	}
	}
	si->si_ptrs.cydata = p;
	si->si_ptrs.cydata = p;
@@ -270,11 +278,19 @@ static int cyttsp4_si_get_test_data(struct cyttsp4 *cd)
	void *p;
	void *p;
	int rc;
	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;
	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);
	p = krealloc(si->si_ptrs.test, si->si_ofs.test_size, GFP_KERNEL);
	if (p == NULL) {
	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;
		return -ENOMEM;
	}
	}
	si->si_ptrs.test = p;
	si->si_ptrs.test = p;
@@ -321,14 +337,20 @@ static int cyttsp4_si_get_pcfg_data(struct cyttsp4 *cd)
	void *p;
	void *p;
	int rc;
	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;
	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);
	p = krealloc(si->si_ptrs.pcfg, si->si_ofs.pcfg_size, GFP_KERNEL);
	if (p == NULL) {
	if (p == NULL) {
		rc = -ENOMEM;
		dev_err(cd->dev, "%s: failed to allocate pcfg memory\n",
		dev_err(cd->dev, "%s: fail alloc pcfg memory r=%d\n",
			__func__);
			__func__, rc);
		return -ENOMEM;
		return rc;
	}
	}
	si->si_ptrs.pcfg = p;
	si->si_ptrs.pcfg = p;


@@ -367,13 +389,20 @@ static int cyttsp4_si_get_opcfg_data(struct cyttsp4 *cd)
	void *p;
	void *p;
	int rc;
	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;
	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);
	p = krealloc(si->si_ptrs.opcfg, si->si_ofs.opcfg_size, GFP_KERNEL);
	if (p == NULL) {
	if (p == NULL) {
		dev_err(cd->dev, "%s: fail alloc opcfg memory\n", __func__);
		dev_err(cd->dev, "%s: failed to allocate opcfg memory\n",
		rc = -ENOMEM;
			__func__);
		goto cyttsp4_si_get_opcfg_data_exit;
		return -ENOMEM;
	}
	}
	si->si_ptrs.opcfg = p;
	si->si_ptrs.opcfg = p;


@@ -382,7 +411,7 @@ static int cyttsp4_si_get_opcfg_data(struct cyttsp4 *cd)
	if (rc < 0) {
	if (rc < 0) {
		dev_err(cd->dev, "%s: fail read opcfg data r=%d\n",
		dev_err(cd->dev, "%s: fail read opcfg data r=%d\n",
			__func__, rc);
			__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.cmd_ofs = si->si_ptrs.opcfg->cmd_ofs;
	si->si_ofs.rep_ofs = si->si_ptrs.opcfg->rep_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,
	cyttsp4_pr_buf(cd->dev, cd->pr_buf, (u8 *)si->si_ptrs.opcfg,
		si->si_ofs.opcfg_size, "sysinfo_opcfg_data");
		si->si_ofs.opcfg_size, "sysinfo_opcfg_data");


cyttsp4_si_get_opcfg_data_exit:
	return 0;
	return rc;
}
}


static int cyttsp4_si_get_ddata(struct cyttsp4 *cd)
static int cyttsp4_si_get_ddata(struct cyttsp4 *cd)