summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHauke Mehrtens2026-06-12 22:34:46 +0000
committerHauke Mehrtens2026-06-18 00:23:17 +0000
commitfda611d2751ea7e10bd16de8e55d498beca35f09 (patch)
tree3e7b4d4e7c6437d910773769b0ce3f4d04f449e2
parent041b2fd279ed12b460ae6a4e86c0e11b96a1b830 (diff)
downloadopenwrt-fda611d2751ea7e10bd16de8e55d498beca35f09.tar.gz
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/23821 Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
-rw-r--r--package/network/services/ead/src/ead.c7
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);