Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Vince Kim and committed by
Dmitry Torokhov
a2c714e8 11772c9c

+40 -12
+40 -12
drivers/input/touchscreen/cyttsp4_core.c
··· 201 201 void *p; 202 202 int rc; 203 203 204 + if (si->si_ofs.test_ofs <= si->si_ofs.cydata_ofs) { 205 + dev_err(cd->dev, 206 + "%s: invalid offset test_ofs: %zu, cydata_ofs: %zu\n", 207 + __func__, si->si_ofs.test_ofs, si->si_ofs.cydata_ofs); 208 + return -EINVAL; 209 + } 210 + 204 211 si->si_ofs.cydata_size = si->si_ofs.test_ofs - si->si_ofs.cydata_ofs; 205 212 dev_dbg(cd->dev, "%s: cydata size: %zd\n", __func__, 206 213 si->si_ofs.cydata_size); 207 214 208 215 p = krealloc(si->si_ptrs.cydata, si->si_ofs.cydata_size, GFP_KERNEL); 209 216 if (p == NULL) { 210 - dev_err(cd->dev, "%s: fail alloc cydata memory\n", __func__); 217 + dev_err(cd->dev, "%s: failed to allocate cydata memory\n", 218 + __func__); 211 219 return -ENOMEM; 212 220 } 213 221 si->si_ptrs.cydata = p; ··· 278 270 void *p; 279 271 int rc; 280 272 273 + if (si->si_ofs.pcfg_ofs <= si->si_ofs.test_ofs) { 274 + dev_err(cd->dev, 275 + "%s: invalid offset pcfg_ofs: %zu, test_ofs: %zu\n", 276 + __func__, si->si_ofs.pcfg_ofs, si->si_ofs.test_ofs); 277 + return -EINVAL; 278 + } 279 + 281 280 si->si_ofs.test_size = si->si_ofs.pcfg_ofs - si->si_ofs.test_ofs; 282 281 283 282 p = krealloc(si->si_ptrs.test, si->si_ofs.test_size, GFP_KERNEL); 284 283 if (p == NULL) { 285 - dev_err(cd->dev, "%s: fail alloc test memory\n", __func__); 284 + dev_err(cd->dev, "%s: failed to allocate test memory\n", 285 + __func__); 286 286 return -ENOMEM; 287 287 } 288 288 si->si_ptrs.test = p; ··· 337 321 void *p; 338 322 int rc; 339 323 324 + if (si->si_ofs.opcfg_ofs <= si->si_ofs.pcfg_ofs) { 325 + dev_err(cd->dev, 326 + "%s: invalid offset opcfg_ofs: %zu, pcfg_ofs: %zu\n", 327 + __func__, si->si_ofs.opcfg_ofs, si->si_ofs.pcfg_ofs); 328 + return -EINVAL; 329 + } 330 + 340 331 si->si_ofs.pcfg_size = si->si_ofs.opcfg_ofs - si->si_ofs.pcfg_ofs; 341 332 342 333 p = krealloc(si->si_ptrs.pcfg, si->si_ofs.pcfg_size, GFP_KERNEL); 343 334 if (p == NULL) { 344 - rc = -ENOMEM; 345 - dev_err(cd->dev, "%s: fail alloc pcfg memory r=%d\n", 346 - __func__, rc); 347 - return rc; 335 + dev_err(cd->dev, "%s: failed to allocate pcfg memory\n", 336 + __func__); 337 + return -ENOMEM; 348 338 } 349 339 si->si_ptrs.pcfg = p; 350 340 ··· 389 367 void *p; 390 368 int rc; 391 369 370 + if (si->si_ofs.ddata_ofs <= si->si_ofs.opcfg_ofs) { 371 + dev_err(cd->dev, 372 + "%s: invalid offset ddata_ofs: %zu, opcfg_ofs: %zu\n", 373 + __func__, si->si_ofs.ddata_ofs, si->si_ofs.opcfg_ofs); 374 + return -EINVAL; 375 + } 376 + 392 377 si->si_ofs.opcfg_size = si->si_ofs.ddata_ofs - si->si_ofs.opcfg_ofs; 393 378 394 379 p = krealloc(si->si_ptrs.opcfg, si->si_ofs.opcfg_size, GFP_KERNEL); 395 380 if (p == NULL) { 396 - dev_err(cd->dev, "%s: fail alloc opcfg memory\n", __func__); 397 - rc = -ENOMEM; 398 - goto cyttsp4_si_get_opcfg_data_exit; 381 + dev_err(cd->dev, "%s: failed to allocate opcfg memory\n", 382 + __func__); 383 + return -ENOMEM; 399 384 } 400 385 si->si_ptrs.opcfg = p; 401 386 ··· 411 382 if (rc < 0) { 412 383 dev_err(cd->dev, "%s: fail read opcfg data r=%d\n", 413 384 __func__, rc); 414 - goto cyttsp4_si_get_opcfg_data_exit; 385 + return rc; 415 386 } 416 387 si->si_ofs.cmd_ofs = si->si_ptrs.opcfg->cmd_ofs; 417 388 si->si_ofs.rep_ofs = si->si_ptrs.opcfg->rep_ofs; ··· 476 447 cyttsp4_pr_buf(cd->dev, cd->pr_buf, (u8 *)si->si_ptrs.opcfg, 477 448 si->si_ofs.opcfg_size, "sysinfo_opcfg_data"); 478 449 479 - cyttsp4_si_get_opcfg_data_exit: 480 - return rc; 450 + return 0; 481 451 } 482 452 483 453 static int cyttsp4_si_get_ddata(struct cyttsp4 *cd)