[media] cec: always check all_device_types and features
authorHans Verkuil <hans.verkuil@cisco.com>
Mon, 18 Jul 2016 06:44:10 +0000 (03:44 -0300)
committerMauro Carvalho Chehab <mchehab@s-opensource.com>
Tue, 19 Jul 2016 16:27:46 +0000 (13:27 -0300)
Even when the adapter is configured for CEC 1.4, we still check and
use the CEC 2.0 parts of struct cec_log_addrs. Although these aren't
used in CEC messages, the information contained in them is still of
use in the CEC framework itself, so keep this information.

Also zero the unused trailing features[] data and unused logical address
data so the contents isn't random data.

Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
drivers/staging/media/cec/cec-adap.c

index 6fa3db5121382e66ca80e1a088e5c901a6d1d490..9fffddb7ac7e9b8f6d780c171de7155aa47745df 100644 (file)
@@ -1210,13 +1210,8 @@ int __cec_s_log_addrs(struct cec_adapter *adap,
                                return -EINVAL;
                        }
 
-       if (log_addrs->cec_version < CEC_OP_CEC_VERSION_2_0) {
-               memset(log_addrs->all_device_types, 0,
-                      sizeof(log_addrs->all_device_types));
-               memset(log_addrs->features, 0, sizeof(log_addrs->features));
-       }
-
        for (i = 0; i < log_addrs->num_log_addrs; i++) {
+               const u8 feature_sz = ARRAY_SIZE(log_addrs->features[0]);
                u8 *features = log_addrs->features[i];
                bool op_is_dev_features = false;
 
@@ -1245,21 +1240,19 @@ int __cec_s_log_addrs(struct cec_adapter *adap,
                        dprintk(1, "unknown logical address type\n");
                        return -EINVAL;
                }
-               if (log_addrs->cec_version < CEC_OP_CEC_VERSION_2_0)
-                       continue;
-
-               for (i = 0; i < ARRAY_SIZE(log_addrs->features[0]); i++) {
+               for (i = 0; i < feature_sz; i++) {
                        if ((features[i] & 0x80) == 0) {
                                if (op_is_dev_features)
                                        break;
                                op_is_dev_features = true;
                        }
                }
-               if (!op_is_dev_features ||
-                   i == ARRAY_SIZE(log_addrs->features[0])) {
+               if (!op_is_dev_features || i == feature_sz) {
                        dprintk(1, "malformed features\n");
                        return -EINVAL;
                }
+               /* Zero unused part of the feature array */
+               memset(features + i, 0, feature_sz - i);
        }
 
        if (log_addrs->cec_version >= CEC_OP_CEC_VERSION_2_0) {
@@ -1281,6 +1274,15 @@ int __cec_s_log_addrs(struct cec_adapter *adap,
                }
        }
 
+       /* Zero unused LAs */
+       for (i = log_addrs->num_log_addrs; i < CEC_MAX_LOG_ADDRS; i++) {
+               log_addrs->primary_device_type[i] = 0;
+               log_addrs->log_addr_type[i] = 0;
+               log_addrs->all_device_types[i] = 0;
+               memset(log_addrs->features[i], 0,
+                      sizeof(log_addrs->features[i]));
+       }
+
        log_addrs->log_addr_mask = adap->log_addrs.log_addr_mask;
        adap->log_addrs = *log_addrs;
        if (adap->phys_addr != CEC_PHYS_ADDR_INVALID)