XueDugu opened a new issue, #18515:
URL: https://github.com/apache/nuttx/issues/18515
### Description / Steps to reproduce the issue
In arch/arm/src/nrf91/nrf91_modem_sock.c, nrf91_usrsock_ioctl_handler()
trusts the arglen field of a
USRSOCK_REQUEST_IOCTL message and copies req->arglen bytes from the
request payload into the fixed-size
usrsock->out buffer without validating either the actual request length or
the destination capacity:
ack = (struct usrsock_message_datareq_ack_s *)usrsock->out;
memcpy(ack + 1, req + 1, req->arglen);
Because arglen is derived from untrusted input, a process able to submit a
crafted usrsock ioctl request can
trigger:
1. an out-of-bounds read from the input buffer when arglen exceeds the
number of bytes actually present after
the request header; and
2. an out-of-bounds write into g_usrsock.out when arglen exceeds the
remaining space after the ack header.
The copied data is later returned through nrf91_usrsock_send_dack(), so
the first case can disclose memory
beyond the received request, while the second case can corrupt adjacent
fields in struct nrf91_usrsock_s.
Vulnerability details
usrsock_request() copies request data into g_usrsock.in and passes the
resulting byte count (len) to
nrf91_usrsock_ioctl_handler(). The handler immediately casts the buffer
and dereferences request fields without
first verifying that the full header is present, and it does not check
that req->arglen fits either the received
request or the fixed-size output buffer.
Relevant code path:
static int nrf91_usrsock_ioctl_handler(struct nrf91_usrsock_s *usrsock,
const void *data, size_t len)
{
const struct usrsock_request_ioctl_s *req = data;
struct usrsock_message_datareq_ack_s *ack = NULL;
int ret = 0;
ack = (struct usrsock_message_datareq_ack_s *)usrsock->out;
memcpy(ack + 1, req + 1, req->arglen);
ret = nrf91_usrsock_ioctl(req->usockid,
req->cmd,
(unsigned long)(ack + 1));
return nrf91_usrsock_send_dack(usrsock, ack, req->head.xid, ret,
req->arglen, req->arglen);
}
Missing validations:
1. len >= sizeof(*req) before reading req->...
2. req->arglen <= len - sizeof(*req) to ensure the payload is fully present
3. req->arglen <= NRF91_USRSOCK_BUFSIZE - sizeof(*ack) to ensure the
destination buffer is large enough
Issue 1: Out-of-bounds read
If req->arglen > len - sizeof(*req), memcpy() reads past the end of the
received request buffer. Because the
handler later sends a data ack using the same arglen value, this can
disclose memory adjacent to g_usrsock.in.
Issue 2: Out-of-bounds write
g_usrsock.out is fixed at NRF91_USRSOCK_BUFSIZE (4096 bytes). Since ack
points to the start of this buffer, the
maximum safe copy size is:
NRF91_USRSOCK_BUFSIZE - sizeof(struct usrsock_message_datareq_ack_s)
If req->arglen exceeds this limit, memcpy() writes past g_usrsock.out and
corrupts adjacent fields in struct
nrf91_usrsock_s.
Steps to reproduce
1. Build and run NuttX on an nRF91 target with the modem/usrsock path
enabled.
2. Obtain the ability to submit a USRSOCK_REQUEST_IOCTL message to the
usrsock interface.
3. For the OOB read case, send a request whose arglen is larger than the
number of bytes actually supplied after
struct usrsock_request_ioctl_s.
4. For the OOB write case, send a request whose arglen is larger than
NRF91_USRSOCK_BUFSIZE - sizeof(struct
usrsock_message_datareq_ack_s); for example, 0xffff.
5. Observe memory disclosure in the returned data ack and/or corruption of
adjacent fields in struct
nrf91_usrsock_s.
Suggested fix
static int nrf91_usrsock_ioctl_handler(struct nrf91_usrsock_s *usrsock,
const void *data, size_t len)
{
const struct usrsock_request_ioctl_s *req = data;
struct usrsock_message_datareq_ack_s *ack;
int ret;
if (len < sizeof(*req))
{
return -EINVAL;
}
if (req->arglen > len - sizeof(*req))
{
return -EINVAL;
}
ack = (struct usrsock_message_datareq_ack_s *)usrsock->out;
if (req->arglen > NRF91_USRSOCK_BUFSIZE - sizeof(*ack))
{
return -EINVAL;
}
memcpy(ack + 1, req + 1, req->arglen);
ret = nrf91_usrsock_ioctl(req->usockid, req->cmd,
(unsigned long)(ack + 1));
return nrf91_usrsock_send_dack(usrsock, ack, req->head.xid, ret,
req->arglen, req->arglen);
}
Impact
A local actor able to submit crafted usrsock ioctl requests can trigger
out-of-bounds reads and writes in the
nRF91 usrsock handler. This can lead to memory disclosure, corruption of
adjacent usrsock state, denial of
service, and potentially further exploitation depending on build
configuration and runtime memory layout.
### On which OS does this issue occur?
[OS: Windows], [OS: Linux]
### What is the version of your OS?
Ubuntu 22.04.5 LTS
### NuttX Version
master
### Issue Architecture
[Arch: arm]
### Issue Area
[Area: Networking]
### Host information
This is a source-level vulnerability in
`arch/arm/src/nrf91/nrf91_modem_sock.c` and is not dependent on a
host-specific build environment. Confirmed by code inspection on Apache
NuttX `master` and `nuttx-12.12.0`.
### 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]