diff options
| author | Nick Dyer <nick.dyer@itdev.co.uk> | 2018-07-27 14:46:46 -0400 |
|---|---|---|
| committer | Dmitry Torokhov <dmitry.torokhov@gmail.com> | 2018-07-27 14:59:32 -0400 |
| commit | a4891f10583748933a9985fac7aa7c073cc59c85 (patch) | |
| tree | cddd2e3676e8b4d73a3013dc83cd729b4970ce86 /drivers/input | |
| parent | f865df7364c3be0aa1e6f708d246af97c134893f (diff) | |
Input: atmel_mxt_ts - zero terminate config firmware file
We use sscanf to parse the configuration file, so it's necessary to zero
terminate the configuration otherwise a truncated file can cause the
parser to run off into uninitialised memory.
Signed-off-by: Nick Dyer <nick.dyer@itdev.co.uk>
Signed-off-by: Dmitry Torokhov <dmitry.torokhov@gmail.com>
Diffstat (limited to 'drivers/input')
| -rw-r--r-- | drivers/input/touchscreen/atmel_mxt_ts.c | 34 |
1 files changed, 24 insertions, 10 deletions
diff --git a/drivers/input/touchscreen/atmel_mxt_ts.c b/drivers/input/touchscreen/atmel_mxt_ts.c index 0ce126e918f1..77387f896262 100644 --- a/drivers/input/touchscreen/atmel_mxt_ts.c +++ b/drivers/input/touchscreen/atmel_mxt_ts.c | |||
| @@ -279,7 +279,7 @@ enum mxt_suspend_mode { | |||
| 279 | 279 | ||
| 280 | /* Config update context */ | 280 | /* Config update context */ |
| 281 | struct mxt_cfg { | 281 | struct mxt_cfg { |
| 282 | const u8 *raw; | 282 | u8 *raw; |
| 283 | size_t raw_size; | 283 | size_t raw_size; |
| 284 | off_t raw_pos; | 284 | off_t raw_pos; |
| 285 | 285 | ||
| @@ -1451,14 +1451,19 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw) | |||
| 1451 | u32 info_crc, config_crc, calculated_crc; | 1451 | u32 info_crc, config_crc, calculated_crc; |
| 1452 | u16 crc_start = 0; | 1452 | u16 crc_start = 0; |
| 1453 | 1453 | ||
| 1454 | cfg.raw = fw->data; | 1454 | /* Make zero terminated copy of the OBP_RAW file */ |
| 1455 | cfg.raw = kmemdup_nul(fw->data, fw->size, GFP_KERNEL); | ||
| 1456 | if (!cfg.raw) | ||
| 1457 | return -ENOMEM; | ||
| 1458 | |||
| 1455 | cfg.raw_size = fw->size; | 1459 | cfg.raw_size = fw->size; |
| 1456 | 1460 | ||
| 1457 | mxt_update_crc(data, MXT_COMMAND_REPORTALL, 1); | 1461 | mxt_update_crc(data, MXT_COMMAND_REPORTALL, 1); |
| 1458 | 1462 | ||
| 1459 | if (strncmp(cfg.raw, MXT_CFG_MAGIC, strlen(MXT_CFG_MAGIC))) { | 1463 | if (strncmp(cfg.raw, MXT_CFG_MAGIC, strlen(MXT_CFG_MAGIC))) { |
| 1460 | dev_err(dev, "Unrecognised config file\n"); | 1464 | dev_err(dev, "Unrecognised config file\n"); |
| 1461 | return -EINVAL; | 1465 | ret = -EINVAL; |
| 1466 | goto release_raw; | ||
| 1462 | } | 1467 | } |
| 1463 | 1468 | ||
| 1464 | cfg.raw_pos = strlen(MXT_CFG_MAGIC); | 1469 | cfg.raw_pos = strlen(MXT_CFG_MAGIC); |
| @@ -1470,7 +1475,8 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw) | |||
| 1470 | &offset); | 1475 | &offset); |
| 1471 | if (ret != 1) { | 1476 | if (ret != 1) { |
| 1472 | dev_err(dev, "Bad format\n"); | 1477 | dev_err(dev, "Bad format\n"); |
| 1473 | return -EINVAL; | 1478 | ret = -EINVAL; |
| 1479 | goto release_raw; | ||
| 1474 | } | 1480 | } |
| 1475 | 1481 | ||
| 1476 | cfg.raw_pos += offset; | 1482 | cfg.raw_pos += offset; |
| @@ -1478,26 +1484,30 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw) | |||
| 1478 | 1484 | ||
| 1479 | if (cfg.info.family_id != data->info->family_id) { | 1485 | if (cfg.info.family_id != data->info->family_id) { |
| 1480 | dev_err(dev, "Family ID mismatch!\n"); | 1486 | dev_err(dev, "Family ID mismatch!\n"); |
| 1481 | return -EINVAL; | 1487 | ret = -EINVAL; |
| 1488 | goto release_raw; | ||
| 1482 | } | 1489 | } |
| 1483 | 1490 | ||
| 1484 | if (cfg.info.variant_id != data->info->variant_id) { | 1491 | if (cfg.info.variant_id != data->info->variant_id) { |
| 1485 | dev_err(dev, "Variant ID mismatch!\n"); | 1492 | dev_err(dev, "Variant ID mismatch!\n"); |
| 1486 | return -EINVAL; | 1493 | ret = -EINVAL; |
| 1494 | goto release_raw; | ||
| 1487 | } | 1495 | } |
| 1488 | 1496 | ||
| 1489 | /* Read CRCs */ | 1497 | /* Read CRCs */ |
| 1490 | ret = sscanf(cfg.raw + cfg.raw_pos, "%x%n", &info_crc, &offset); | 1498 | ret = sscanf(cfg.raw + cfg.raw_pos, "%x%n", &info_crc, &offset); |
| 1491 | if (ret != 1) { | 1499 | if (ret != 1) { |
| 1492 | dev_err(dev, "Bad format: failed to parse Info CRC\n"); | 1500 | dev_err(dev, "Bad format: failed to parse Info CRC\n"); |
| 1493 | return -EINVAL; | 1501 | ret = -EINVAL; |
| 1502 | goto release_raw; | ||
| 1494 | } | 1503 | } |
| 1495 | cfg.raw_pos += offset; | 1504 | cfg.raw_pos += offset; |
| 1496 | 1505 | ||
| 1497 | ret = sscanf(cfg.raw + cfg.raw_pos, "%x%n", &config_crc, &offset); | 1506 | ret = sscanf(cfg.raw + cfg.raw_pos, "%x%n", &config_crc, &offset); |
| 1498 | if (ret != 1) { | 1507 | if (ret != 1) { |
| 1499 | dev_err(dev, "Bad format: failed to parse Config CRC\n"); | 1508 | dev_err(dev, "Bad format: failed to parse Config CRC\n"); |
| 1500 | return -EINVAL; | 1509 | ret = -EINVAL; |
| 1510 | goto release_raw; | ||
| 1501 | } | 1511 | } |
| 1502 | cfg.raw_pos += offset; | 1512 | cfg.raw_pos += offset; |
| 1503 | 1513 | ||
| @@ -1530,8 +1540,10 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw) | |||
| 1530 | MXT_INFO_CHECKSUM_SIZE; | 1540 | MXT_INFO_CHECKSUM_SIZE; |
| 1531 | cfg.mem_size = data->mem_size - cfg.start_ofs; | 1541 | cfg.mem_size = data->mem_size - cfg.start_ofs; |
| 1532 | cfg.mem = kzalloc(cfg.mem_size, GFP_KERNEL); | 1542 | cfg.mem = kzalloc(cfg.mem_size, GFP_KERNEL); |
| 1533 | if (!cfg.mem) | 1543 | if (!cfg.mem) { |
| 1534 | return -ENOMEM; | 1544 | ret = -ENOMEM; |
| 1545 | goto release_raw; | ||
| 1546 | } | ||
| 1535 | 1547 | ||
| 1536 | ret = mxt_prepare_cfg_mem(data, &cfg); | 1548 | ret = mxt_prepare_cfg_mem(data, &cfg); |
| 1537 | if (ret) | 1549 | if (ret) |
| @@ -1570,6 +1582,8 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw) | |||
| 1570 | /* T7 config may have changed */ | 1582 | /* T7 config may have changed */ |
| 1571 | mxt_init_t7_power_cfg(data); | 1583 | mxt_init_t7_power_cfg(data); |
| 1572 | 1584 | ||
| 1585 | release_raw: | ||
| 1586 | kfree(cfg.raw); | ||
| 1573 | release_mem: | 1587 | release_mem: |
| 1574 | kfree(cfg.mem); | 1588 | kfree(cfg.mem); |
| 1575 | return ret; | 1589 | return ret; |
