drm/amd/display: Add array index check for hdcp ddc access
authorjsg <jsg@openbsd.org>
Mon, 9 Sep 2024 08:49:00 +0000 (08:49 +0000)
committerjsg <jsg@openbsd.org>
Mon, 9 Sep 2024 08:49:00 +0000 (08:49 +0000)
From Hersen Wu
8b5ccf3d011969417be653b5a145c72dbd30472c in linux-6.6.y/6.6.50
4e70c0f5251c25885c31ee84a31f99a01f7cf50e in mainline linux

sys/dev/pci/drm/amd/display/modules/hdcp/hdcp_ddc.c

index 0f345a2..e4bb0c6 100644 (file)
@@ -158,11 +158,16 @@ static enum mod_hdcp_status read(struct mod_hdcp *hdcp,
        uint32_t cur_size = 0;
        uint32_t data_offset = 0;
 
-       if (msg_id == MOD_HDCP_MESSAGE_ID_INVALID) {
+       if (msg_id == MOD_HDCP_MESSAGE_ID_INVALID ||
+               msg_id >= MOD_HDCP_MESSAGE_ID_MAX)
                return MOD_HDCP_STATUS_DDC_FAILURE;
-       }
 
        if (is_dp_hdcp(hdcp)) {
+               int num_dpcd_addrs = sizeof(hdcp_dpcd_addrs) /
+                       sizeof(hdcp_dpcd_addrs[0]);
+               if (msg_id >= num_dpcd_addrs)
+                       return MOD_HDCP_STATUS_DDC_FAILURE;
+
                while (buf_len > 0) {
                        cur_size = MIN(buf_len, HDCP_MAX_AUX_TRANSACTION_SIZE);
                        success = hdcp->config.ddc.funcs.read_dpcd(hdcp->config.ddc.handle,
@@ -177,6 +182,11 @@ static enum mod_hdcp_status read(struct mod_hdcp *hdcp,
                        data_offset += cur_size;
                }
        } else {
+               int num_i2c_offsets = sizeof(hdcp_i2c_offsets) /
+                       sizeof(hdcp_i2c_offsets[0]);
+               if (msg_id >= num_i2c_offsets)
+                       return MOD_HDCP_STATUS_DDC_FAILURE;
+
                success = hdcp->config.ddc.funcs.read_i2c(
                                hdcp->config.ddc.handle,
                                HDCP_I2C_ADDR,
@@ -221,11 +231,16 @@ static enum mod_hdcp_status write(struct mod_hdcp *hdcp,
        uint32_t cur_size = 0;
        uint32_t data_offset = 0;
 
-       if (msg_id == MOD_HDCP_MESSAGE_ID_INVALID) {
+       if (msg_id == MOD_HDCP_MESSAGE_ID_INVALID ||
+               msg_id >= MOD_HDCP_MESSAGE_ID_MAX)
                return MOD_HDCP_STATUS_DDC_FAILURE;
-       }
 
        if (is_dp_hdcp(hdcp)) {
+               int num_dpcd_addrs = sizeof(hdcp_dpcd_addrs) /
+                       sizeof(hdcp_dpcd_addrs[0]);
+               if (msg_id >= num_dpcd_addrs)
+                       return MOD_HDCP_STATUS_DDC_FAILURE;
+
                while (buf_len > 0) {
                        cur_size = MIN(buf_len, HDCP_MAX_AUX_TRANSACTION_SIZE);
                        success = hdcp->config.ddc.funcs.write_dpcd(
@@ -241,6 +256,11 @@ static enum mod_hdcp_status write(struct mod_hdcp *hdcp,
                        data_offset += cur_size;
                }
        } else {
+               int num_i2c_offsets = sizeof(hdcp_i2c_offsets) /
+                       sizeof(hdcp_i2c_offsets[0]);
+               if (msg_id >= num_i2c_offsets)
+                       return MOD_HDCP_STATUS_DDC_FAILURE;
+
                hdcp->buf[0] = hdcp_i2c_offsets[msg_id];
                memmove(&hdcp->buf[1], buf, buf_len);
                success = hdcp->config.ddc.funcs.write_i2c(