summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSakari Ailus <sakari.ailus@linux.intel.com>2023-07-29 20:59:25 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2023-09-13 09:48:38 +0200
commit636f4076188cc2e49f318fbf87cfb6bec1cbbe28 (patch)
tree3da83cf6d6eed1512904a828b6a3c5b1623ecaed
parent9734e4c0c470258c32b6aa5ea7ef8a86506c0909 (diff)
media: i2c: ccs: Check rules is non-NULL
commit 607bcc4213d998d051541d8f10b5bbb7d546c0be upstream. Fix the following smatch warning: drivers/media/i2c/ccs/ccs-data.c:524 ccs_data_parse_rules() warn: address of NULL pointer 'rules' The CCS static data rule parser does not check an if rule has been obtained before checking for other rule types (which depend on the if rule). In practice this means parsing invalid CCS static data could lead to dereferencing a NULL pointer. Reported-by: Hans Verkuil <hverkuil@xs4all.nl> Fixes: a6b396f410b1 ("media: ccs: Add CCS static data parser library") Cc: stable@vger.kernel.org # for 5.11 and up Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/media/i2c/ccs/ccs-data.c101
1 files changed, 56 insertions, 45 deletions
diff --git a/drivers/media/i2c/ccs/ccs-data.c b/drivers/media/i2c/ccs/ccs-data.c
index 45f2b2f55ec5..08400edf77ce 100644
--- a/drivers/media/i2c/ccs/ccs-data.c
+++ b/drivers/media/i2c/ccs/ccs-data.c
@@ -464,8 +464,7 @@ static int ccs_data_parse_rules(struct bin_container *bin,
rule_payload = __rule_type + 1;
rule_plen2 = rule_plen - sizeof(*__rule_type);
- switch (*__rule_type) {
- case CCS_DATA_BLOCK_RULE_ID_IF: {
+ if (*__rule_type == CCS_DATA_BLOCK_RULE_ID_IF) {
const struct __ccs_data_block_rule_if *__if_rules =
rule_payload;
const size_t __num_if_rules =
@@ -514,49 +513,61 @@ static int ccs_data_parse_rules(struct bin_container *bin,
rules->if_rules = if_rule;
rules->num_if_rules = __num_if_rules;
}
- break;
- }
- case CCS_DATA_BLOCK_RULE_ID_READ_ONLY_REGS:
- rval = ccs_data_parse_reg_rules(bin, &rules->read_only_regs,
- &rules->num_read_only_regs,
- rule_payload,
- rule_payload + rule_plen2,
- dev);
- if (rval)
- return rval;
- break;
- case CCS_DATA_BLOCK_RULE_ID_FFD:
- rval = ccs_data_parse_ffd(bin, &rules->frame_format,
- rule_payload,
- rule_payload + rule_plen2,
- dev);
- if (rval)
- return rval;
- break;
- case CCS_DATA_BLOCK_RULE_ID_MSR:
- rval = ccs_data_parse_reg_rules(bin,
- &rules->manufacturer_regs,
- &rules->num_manufacturer_regs,
- rule_payload,
- rule_payload + rule_plen2,
- dev);
- if (rval)
- return rval;
- break;
- case CCS_DATA_BLOCK_RULE_ID_PDAF_READOUT:
- rval = ccs_data_parse_pdaf_readout(bin,
- &rules->pdaf_readout,
- rule_payload,
- rule_payload + rule_plen2,
- dev);
- if (rval)
- return rval;
- break;
- default:
- dev_dbg(dev,
- "Don't know how to handle rule type %u!\n",
- *__rule_type);
- return -EINVAL;
+ } else {
+ /* Check there was an if rule before any other rules */
+ if (bin->base && !rules)
+ return -EINVAL;
+
+ switch (*__rule_type) {
+ case CCS_DATA_BLOCK_RULE_ID_READ_ONLY_REGS:
+ rval = ccs_data_parse_reg_rules(bin,
+ rules ?
+ &rules->read_only_regs : NULL,
+ rules ?
+ &rules->num_read_only_regs : NULL,
+ rule_payload,
+ rule_payload + rule_plen2,
+ dev);
+ if (rval)
+ return rval;
+ break;
+ case CCS_DATA_BLOCK_RULE_ID_FFD:
+ rval = ccs_data_parse_ffd(bin, rules ?
+ &rules->frame_format : NULL,
+ rule_payload,
+ rule_payload + rule_plen2,
+ dev);
+ if (rval)
+ return rval;
+ break;
+ case CCS_DATA_BLOCK_RULE_ID_MSR:
+ rval = ccs_data_parse_reg_rules(bin,
+ rules ?
+ &rules->manufacturer_regs : NULL,
+ rules ?
+ &rules->num_manufacturer_regs : NULL,
+ rule_payload,
+ rule_payload + rule_plen2,
+ dev);
+ if (rval)
+ return rval;
+ break;
+ case CCS_DATA_BLOCK_RULE_ID_PDAF_READOUT:
+ rval = ccs_data_parse_pdaf_readout(bin,
+ rules ?
+ &rules->pdaf_readout : NULL,
+ rule_payload,
+ rule_payload + rule_plen2,
+ dev);
+ if (rval)
+ return rval;
+ break;
+ default:
+ dev_dbg(dev,
+ "Don't know how to handle rule type %u!\n",
+ *__rule_type);
+ return -EINVAL;
+ }
}
__next_rule = __next_rule + rule_hlen + rule_plen;
}