catalinv-ncc opened a new issue, #19138:
URL: https://github.com/apache/nuttx/issues/19138
### Description / Steps to reproduce the issue
Description / Steps to reproduce the issue
# Impact
A malformed packet can trigger memory corruption in the kernel leading to a
system crash or potentially arbitrary code execution in the kernel.
# Description
The CAN driver for the CTU CAN FD IP Core connected to the NuttX device via
a PCI / PCI Express (PCIe) bus shows a lack of consideration for malformed
data, assuming the CAN frames are always correct.
```c
begin_packed_struct struct ctucanfd_frame_fmt_s
{
uint32_t dlc:4; /* DLC */
...
uint32_t [[[[rwcnt:5]]]]; /* Size without FRAME_FORMAT WORD */
...
uint32_t _reserved:4; /* Reserved */
} end_packed_struct;
begin_packed_struct struct ctucanfd_frame_s
{
struct ctucanfd_frame_fmt_s [[[[fmt]]]]; /* Frame format */
...
} end_packed_struct;
```
The size of `struct ctucanfd_frame_s` is 84 bytes, therefore, in the
following code snippet, the `buff` array used by the
`ctucanfd_chardev_receive()` has 21 `uint32_t` elements.
The code uses `ctucanfd_getreg()` to read the first four bytes from the CAN
bus line into the `ctucanfd_frame_s` structure (populates `fmt` structure
member). Immediately after, it uses the data read in `frame->fmt.rwcnt` without
validation in the `for` loop. The attacker controls the content, and `rwcnt`
structure member is 5 bits long therefore it can store a maximum value of
2<sup>5</sup> - 1 = 31. Since the length of the `buff` array is 21 elements and
attackers can write 10 `uint32_t` additional elements, they can cause a 40-byte
overflow of `buff` array. Note that the attacker can also control the content
retrieved in the overflowing bytes.
```c
/*****************************************************************************
* Name: ctucanfd_chardev_receive
* Description: Receive CAN frame
*****************************************************************************/
static void ctucanfd_chardev_receive(FAR struct ctucanfd_can_s *priv)
{
FAR struct can_dev_s *dev = (FAR struct can_dev_s *)priv;
FAR struct ctucanfd_frame_s *frame;
struct can_hdr_s hdr;
uint32_t buff[ [[[[sizeof(struct ctucanfd_frame_s) /
4]]]] ];
...
uint32_t regval = 0;
memset(&hdr, 0, sizeof(hdr));
....
/* We use a pointer to buffer to avoid an unaligned pointer compiler
errors */
frame = (struct ctucanfd_frame_s *)&buff;
/* RX buffer in automatic mode */ // NCC Group read the 4-byte "fmt"
element
[[[[buff[0] = ctucanfd_getreg(priv, CTUCANFD_RXDATA);]]]]
/* Read the rest of data */
for (i = 0; i < [[[[frame->fmt.rwcnt]]]]; i++) // NCC Group: uses the
size without checking
{
buff[i + 1] = ctucanfd_getreg(priv, CTUCANFD_RXDATA); // NCC Group
buffer overflow
}
```
# Recommendation
Ensure `frame->fmt.rwcnt` is 21 or less before it is used in the `for` loop.
### On which OS does this issue occur?
[OS: Linux]
### What is the version of your OS?
Ubuntu 24.04
### NuttX Version
master
### Issue Architecture
[Arch: all]
### Issue Area
[Area: Debugging], [Area: Drivers]
### Host information
N/A
### Verification
- [x] I have verified before submitting the report.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]