diff options
author | Tomas Winkler <tomas.winkler@intel.com> | 2020-08-18 10:54:06 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-08-18 16:39:38 +0300 |
commit | 51072c0f5b5e98a035c6f63b83ba2afedbb7accd (patch) | |
tree | 949c0d68a7e399020a9a362cbdcd46ffa9b5e882 /drivers/misc/mei/hdcp/mei_hdcp.c | |
parent | dfe650be6f79fc69021a9b7a559d5aca1e2ef359 (diff) | |
download | linux-51072c0f5b5e98a035c6f63b83ba2afedbb7accd.tar.xz |
mei: hdcp: fix mei_hdcp_verify_mprime() input parameter
wired_cmd_repeater_auth_stream_req_in has a variable
length array at the end. we use struct_size() overflow
macro to determine the size for the allocation and sending
size.
This also fixes bug in case number of streams is > 0 in the original
submission. This bug was not triggered as the number of streams is
always one.
Fixes: c56967d674e3 (mei: hdcp: Replace one-element array with flexible-array member)
Fixes: 0a1af1b5c18d (misc/mei/hdcp: Verify M_prime)
Cc: <stable@vger.kernel.org> # v5.1+: c56967d674e3 (mei: hdcp: Replace one-element array with flexible-array member)
Signed-off-by: Tomas Winkler <tomas.winkler@intel.com>
Reviewed-by: Gustavo A. R. Silva <gustavoars@kernel.org>
Link: https://lore.kernel.org/r/20200818075406.2532605-1-tomas.winkler@intel.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/misc/mei/hdcp/mei_hdcp.c')
-rw-r--r-- | drivers/misc/mei/hdcp/mei_hdcp.c | 40 |
1 files changed, 24 insertions, 16 deletions
diff --git a/drivers/misc/mei/hdcp/mei_hdcp.c b/drivers/misc/mei/hdcp/mei_hdcp.c index d1d3e025ca0e..9ae9669e46ea 100644 --- a/drivers/misc/mei/hdcp/mei_hdcp.c +++ b/drivers/misc/mei/hdcp/mei_hdcp.c @@ -546,38 +546,46 @@ static int mei_hdcp_verify_mprime(struct device *dev, struct hdcp_port_data *data, struct hdcp2_rep_stream_ready *stream_ready) { - struct wired_cmd_repeater_auth_stream_req_in - verify_mprime_in = { { 0 } }; + struct wired_cmd_repeater_auth_stream_req_in *verify_mprime_in; struct wired_cmd_repeater_auth_stream_req_out verify_mprime_out = { { 0 } }; struct mei_cl_device *cldev; ssize_t byte; + size_t cmd_size; if (!dev || !stream_ready || !data) return -EINVAL; cldev = to_mei_cl_device(dev); - verify_mprime_in.header.api_version = HDCP_API_VERSION; - verify_mprime_in.header.command_id = WIRED_REPEATER_AUTH_STREAM_REQ; - verify_mprime_in.header.status = ME_HDCP_STATUS_SUCCESS; - verify_mprime_in.header.buffer_len = + cmd_size = struct_size(verify_mprime_in, streams, data->k); + if (cmd_size == SIZE_MAX) + return -EINVAL; + + verify_mprime_in = kzalloc(cmd_size, GFP_KERNEL); + if (!verify_mprime_in) + return -ENOMEM; + + verify_mprime_in->header.api_version = HDCP_API_VERSION; + verify_mprime_in->header.command_id = WIRED_REPEATER_AUTH_STREAM_REQ; + verify_mprime_in->header.status = ME_HDCP_STATUS_SUCCESS; + verify_mprime_in->header.buffer_len = WIRED_CMD_BUF_LEN_REPEATER_AUTH_STREAM_REQ_MIN_IN; - verify_mprime_in.port.integrated_port_type = data->port_type; - verify_mprime_in.port.physical_port = (u8)data->fw_ddi; - verify_mprime_in.port.attached_transcoder = (u8)data->fw_tc; + verify_mprime_in->port.integrated_port_type = data->port_type; + verify_mprime_in->port.physical_port = (u8)data->fw_ddi; + verify_mprime_in->port.attached_transcoder = (u8)data->fw_tc; + + memcpy(verify_mprime_in->m_prime, stream_ready->m_prime, HDCP_2_2_MPRIME_LEN); + drm_hdcp_cpu_to_be24(verify_mprime_in->seq_num_m, data->seq_num_m); - memcpy(verify_mprime_in.m_prime, stream_ready->m_prime, - HDCP_2_2_MPRIME_LEN); - drm_hdcp_cpu_to_be24(verify_mprime_in.seq_num_m, data->seq_num_m); - memcpy(verify_mprime_in.streams, data->streams, + memcpy(verify_mprime_in->streams, data->streams, array_size(data->k, sizeof(*data->streams))); - verify_mprime_in.k = cpu_to_be16(data->k); + verify_mprime_in->k = cpu_to_be16(data->k); - byte = mei_cldev_send(cldev, (u8 *)&verify_mprime_in, - sizeof(verify_mprime_in)); + byte = mei_cldev_send(cldev, (u8 *)verify_mprime_in, cmd_size); + kfree(verify_mprime_in); if (byte < 0) { dev_dbg(dev, "mei_cldev_send failed. %zd\n", byte); return byte; |