Skip to content

staging: vc04_services: vchiq-mmal: harden MMAL message handling against firmware bugs#7296

Open
Sebasteuo wants to merge 4 commits intoraspberrypi:rpi-6.18.yfrom
Sebasteuo:fix/mmal-vchiq-security-6.18
Open

staging: vc04_services: vchiq-mmal: harden MMAL message handling against firmware bugs#7296
Sebasteuo wants to merge 4 commits intoraspberrypi:rpi-6.18.yfrom
Sebasteuo:fix/mmal-vchiq-security-6.18

Conversation

@Sebasteuo
Copy link
Copy Markdown

This series adds defensive bounds checks to the MMAL VCHIQ driver
to harden against potential firmware bugs or malformed responses
from the VideoCore GPU.

Patch 1/4: Validate client_component index in event_to_host_cb()
before using it as an array index into the 64-element component[]
array. A firmware bug returning an out-of-range value would cause
an OOB array access.

Patch 2/4: Add buffer size check in inline_receive() before
memcpy. The payload_in_message field (up to 128 bytes) is used
as the copy size without checking the destination buffer_size.

Patch 3/4: Prevent stack overflow in port_parameter_set() by
validating value_size against the 384-byte destination before
memcpy.

Patch 4/4: Fix integer underflow in port_parameter_get() where
a firmware reply size field is subtracted without minimum check,
potentially wrapping to ~4GB.

All checks use pr_err_ratelimited() and the patches are framed
as hardening rather than security fixes per Greg KH's guidance.

Found through manual source code auditing.

Reported-by: Sebastián Alba Vives sebasjosue84@gmail.com
Signed-off-by: Sebastián Alba Vives sebasjosue84@gmail.com

…_to_host_cb()

event_to_host_cb() uses msg->u.event_to_host.client_component as an
index into the instance->component[] array (size VCHIQ_MMAL_MAX_COMPONENTS
= 64) without bounds validation. While the kernel generally trusts the
hardware it is bound to, a bounds check here hardens the driver against
potential firmware bugs that could otherwise cause an uncontrolled
out-of-bounds array access and kernel crash.

Add a bounds check on comp_idx before using it as an array index and
move the component pointer assignment after the validation. Use
pr_err_ratelimited() to avoid log flooding. Note: this file does not
currently have access to a struct device, so dev_err() is not available.

Cc: stable@vger.kernel.org
Fixes: b18ee53 ("staging: bcm2835: Break MMAL support out from camera")
Signed-off-by: Sebastián Alba Vives <sebasjosue84@gmail.com>
…eceive()

inline_receive() copies payload data from a VCHIQ message into a
destination buffer using payload_in_message as the copy length, but
never validates that this length fits within the destination buffer
(msg_context->u.bulk.buffer->buffer_size).

While the caller validates payload_in_message <= MMAL_VC_SHORT_DATA
(128) to prevent overreading the source, the destination buffer may be
smaller than 128 bytes. This is inconsistent with bulk_receive() which
does check buffer_size before copying.

Add a bounds check against buffer_size and truncate the copy length if
it exceeds the destination capacity, matching the defensive pattern used
in bulk_receive(). Use pr_warn_ratelimited() for the truncation warning.

Cc: stable@vger.kernel.org
Fixes: b18ee53 ("staging: bcm2835: Break MMAL support out from camera")
Signed-off-by: Sebastián Alba Vives <sebasjosue84@gmail.com>
…rameter_set()

port_parameter_set() copies value_size bytes from the caller-supplied
value buffer into the stack-allocated struct mmal_msg's
port_parameter_set.value field, which is u32[96] (384 bytes). There is
no bounds check on value_size before the memcpy.

While current in-tree callers pass small fixed-size structures, the
function is exported via EXPORT_SYMBOL_GPL and accessible to any GPL
kernel module. A caller passing value_size > 384 would overflow the
stack-allocated mmal_msg structure.

Add a bounds check rejecting value_size larger than the value field.

Cc: stable@vger.kernel.org
Fixes: b18ee53 ("staging: bcm2835: Break MMAL support out from camera")
Signed-off-by: Sebastián Alba Vives <sebasjosue84@gmail.com>
…ameter_get()

port_parameter_get() subtracts 2 * sizeof(u32) from the VideoCore
firmware's reply size field to compute the parameter value size. If
the firmware returns a size smaller than 8, the subtraction wraps
around to a large value due to unsigned integer underflow.

The underflowed size is then used in a comparison that selects the
wrong copy path and stored back to the caller via *value_size,
propagating a bogus size to subsequent operations.

Add a minimum size check before the subtraction and return -EPROTO
if the reply is malformed.

Cc: stable@vger.kernel.org
Fixes: b18ee53 ("staging: bcm2835: Break MMAL support out from camera")
Signed-off-by: Sebastián Alba Vives <sebasjosue84@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant