Input: atmel_mxt_ts - zero terminate config firmware file
authorNick Dyer <nick.dyer@itdev.co.uk>
Fri, 27 Jul 2018 18:46:46 +0000 (11:46 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Fri, 27 Jul 2018 18:59:32 +0000 (11:59 -0700)
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>
drivers/input/touchscreen/atmel_mxt_ts.c

index 0ce126e..77387f8 100644 (file)
@@ -279,7 +279,7 @@ enum mxt_suspend_mode {
 
 /* Config update context */
 struct mxt_cfg {
-       const u8 *raw;
+       u8 *raw;
        size_t raw_size;
        off_t raw_pos;
 
@@ -1451,14 +1451,19 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw)
        u32 info_crc, config_crc, calculated_crc;
        u16 crc_start = 0;
 
-       cfg.raw = fw->data;
+       /* Make zero terminated copy of the OBP_RAW file */
+       cfg.raw = kmemdup_nul(fw->data, fw->size, GFP_KERNEL);
+       if (!cfg.raw)
+               return -ENOMEM;
+
        cfg.raw_size = fw->size;
 
        mxt_update_crc(data, MXT_COMMAND_REPORTALL, 1);
 
        if (strncmp(cfg.raw, MXT_CFG_MAGIC, strlen(MXT_CFG_MAGIC))) {
                dev_err(dev, "Unrecognised config file\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto release_raw;
        }
 
        cfg.raw_pos = strlen(MXT_CFG_MAGIC);
@@ -1470,7 +1475,8 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw)
                             &offset);
                if (ret != 1) {
                        dev_err(dev, "Bad format\n");
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       goto release_raw;
                }
 
                cfg.raw_pos += offset;
@@ -1478,26 +1484,30 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw)
 
        if (cfg.info.family_id != data->info->family_id) {
                dev_err(dev, "Family ID mismatch!\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto release_raw;
        }
 
        if (cfg.info.variant_id != data->info->variant_id) {
                dev_err(dev, "Variant ID mismatch!\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto release_raw;
        }
 
        /* Read CRCs */
        ret = sscanf(cfg.raw + cfg.raw_pos, "%x%n", &info_crc, &offset);
        if (ret != 1) {
                dev_err(dev, "Bad format: failed to parse Info CRC\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto release_raw;
        }
        cfg.raw_pos += offset;
 
        ret = sscanf(cfg.raw + cfg.raw_pos, "%x%n", &config_crc, &offset);
        if (ret != 1) {
                dev_err(dev, "Bad format: failed to parse Config CRC\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto release_raw;
        }
        cfg.raw_pos += offset;
 
@@ -1530,8 +1540,10 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw)
                        MXT_INFO_CHECKSUM_SIZE;
        cfg.mem_size = data->mem_size - cfg.start_ofs;
        cfg.mem = kzalloc(cfg.mem_size, GFP_KERNEL);
-       if (!cfg.mem)
-               return -ENOMEM;
+       if (!cfg.mem) {
+               ret = -ENOMEM;
+               goto release_raw;
+       }
 
        ret = mxt_prepare_cfg_mem(data, &cfg);
        if (ret)
@@ -1570,6 +1582,8 @@ static int mxt_update_cfg(struct mxt_data *data, const struct firmware *fw)
        /* T7 config may have changed */
        mxt_init_t7_power_cfg(data);
 
+release_raw:
+       kfree(cfg.raw);
 release_mem:
        kfree(cfg.mem);
        return ret;