diff options
| author | Hauke Mehrtens | 2026-06-12 22:34:46 +0000 |
|---|---|---|
| committer | Hauke Mehrtens | 2026-07-20 00:07:27 +0000 |
| commit | 3944c026aa7cd27222ce334df72d2bcb6be86b9c (patch) | |
| tree | b74f89385a7a566bc80044bd00f135fbcb4630d0 | |
| parent | 818f69638719b3a4cfb92b6ea999ce0bfe15b086 (diff) | |
ead: fix integer underflow in handle_send_a()
handle_send_a() computed the SRP "A" parameter length as
len = ntohl(msg->len) - sizeof(struct ead_msg_number);
sizeof(struct ead_msg_number) is 1, and the subtraction is evaluated in
unsigned arithmetic. A packet with msg->len == 0 therefore wraps the
result to a huge value which, assigned to the signed int len, becomes -1.
The following bounds check is signed:
if (len > MAXPARAMLEN + 1)
return false;
so -1 passes, and memcpy(A.data, number->data, len) runs with len cast to
size_t (~SIZE_MAX) against the 257-byte abuf, crashing the daemon.
Neither parse_message() nor handle_packet() validate msg->len (only the
captured packet length), so an unauthenticated attacker on the local
segment can reach this path and crash ead with a single crafted packet.
Validate the claimed length in unsigned arithmetic before the subtraction
and bound it on both sides. Doing the upper-bound check unsigned as well
also closes a 32-bit-only variant where sizeof(ead_packet) + msg->len
overflows in handle_packet(), letting a large msg->len reach the same
negative-len path.
Link: https://github.com/openwrt/openwrt/security/advisories/GHSA-9558-77jp-g3fw
Reported-by: @Vasco0x4
Assisted-by: Claude:claude-opus-4-8
(cherry picked from commit 63c0767f3d02f7b10b0f0b5293366bd059a08ca5)
Link: https://github.com/openwrt/openwrt/pull/24298
Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
| -rw-r--r-- | package/network/services/ead/src/ead.c | 7 |
1 files changed, 5 insertions, 2 deletions
diff --git a/package/network/services/ead/src/ead.c b/package/network/services/ead/src/ead.c index ad97c543c5..b065b4100a 100644 --- a/package/network/services/ead/src/ead.c +++ b/package/network/services/ead/src/ead.c @@ -428,11 +428,14 @@ handle_send_a(struct ead_packet *pkt, int len, int *nstate) { struct ead_msg *msg = &pkt->msg; struct ead_msg_number *number = EAD_DATA(msg, number); - len = ntohl(msg->len) - sizeof(struct ead_msg_number); + uint32_t msg_len = ntohl(msg->len); - if (len > MAXPARAMLEN + 1) + if (msg_len < sizeof(struct ead_msg_number) || + msg_len - sizeof(struct ead_msg_number) > MAXPARAMLEN + 1) return false; + len = msg_len - sizeof(struct ead_msg_number); + A.len = len; A.data = abuf; memcpy(A.data, number->data, len); |