gpsd: patch CVE-2025-67269

Details: https://nvd.nist.gov/vuln/detail/CVE-2025-67269

Backport the patch that is referenced by the NVD advisory.

Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
Signed-off-by: Anuj Mittal <anuj.mittal@oss.qualcomm.com>
This commit is contained in:
Gyorgy Sarvari
2026-02-02 22:13:54 +01:00
committed by Anuj Mittal
parent 4b7fc39111
commit f6226c4b84
2 changed files with 159 additions and 0 deletions
@@ -0,0 +1,158 @@
From 5c8490b32eb8e8d78e054851300cdebefd1c2e5a Mon Sep 17 00:00:00 2001
From: "Gary E. Miller" <gem@rellim.com>
Date: Wed, 3 Dec 2025 19:04:03 -0800
Subject: [PATCH] gpsd/packet.c: Fix integer underflow is malicious Navcom
packet
Causes DoS. Fix issue 358
CVE: CVE-2025-67269
Upstream-Status: Backport [https://gitlab.com/gpsd/gpsd/-/commit/ffa1d6f40bca0b035fc7f5e563160ebb67199da7]
Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
---
gpsd/packet.c | 64 ++++++++++++++++++++++++++++++++++++++-------------
1 file changed, 48 insertions(+), 16 deletions(-)
diff --git a/gpsd/packet.c b/gpsd/packet.c
index f9a7db8..0c23500 100644
--- a/gpsd/packet.c
+++ b/gpsd/packet.c
@@ -1141,18 +1141,22 @@ static bool nextstate(struct gps_lexer_t *lexer, unsigned char c)
#endif // SIRF_ENABLE || SKYTRAQ_ENABLE
#ifdef SIRF_ENABLE
case SIRF_LEADER_2:
- // first part of length
- lexer->length = (size_t) (c << 8);
+ // first part of length, MSB
+ lexer->length = (c & 0x7f) << 8;
+ if (lexer->length > MAX_PACKET_LENGTH) {
+ lexer->length = 0;
+ return character_pushback(lexer, GROUND_STATE);
+ } // else
lexer->state = SIRF_LENGTH_1;
break;
case SIRF_LENGTH_1:
// second part of length
lexer->length += c + 2;
- if (lexer->length <= MAX_PACKET_LENGTH) {
- lexer->state = SIRF_PAYLOAD;
- } else {
+ if (lexer->length > MAX_PACKET_LENGTH) {
+ lexer->length = 0;
return character_pushback(lexer, GROUND_STATE);
- }
+ } // else
+ lexer->state = SIRF_PAYLOAD;
break;
case SIRF_PAYLOAD:
if (0 == --lexer->length) {
@@ -1194,6 +1198,7 @@ static bool nextstate(struct gps_lexer_t *lexer, unsigned char c)
return character_pushback(lexer, GROUND_STATE);
}
if (MAX_PACKET_LENGTH < lexer->length) {
+ lexer->length = 0;
return character_pushback(lexer, GROUND_STATE);
}
lexer->state = SKY_PAYLOAD;
@@ -1376,14 +1381,29 @@ static bool nextstate(struct gps_lexer_t *lexer, unsigned char c)
}
break;
case NAVCOM_LEADER_3:
+ // command ID
lexer->state = NAVCOM_ID;
break;
case NAVCOM_ID:
- lexer->length = (size_t)c - 4;
+ /* Length LSB
+ * Navcom length includes command ID, length bytes. and checksum.
+ * So for more than just the payload length.
+ * Minimum 4 bytes */
+ if (4 > c) {
+ return character_pushback(lexer, GROUND_STATE);
+ }
+ lexer->length = c;
lexer->state = NAVCOM_LENGTH_1;
break;
case NAVCOM_LENGTH_1:
+ // Length USB. Navcom allows payload length up to 65,531
lexer->length += (c << 8);
+ // don't count ID, length and checksum in payload length
+ lexer->length -= 4;
+ if (MAX_PACKET_LENGTH < lexer->length) {
+ lexer->length = 0;
+ return character_pushback(lexer, GROUND_STATE);
+ } // else
lexer->state = NAVCOM_LENGTH_2;
break;
case NAVCOM_LENGTH_2:
@@ -1510,11 +1530,11 @@ static bool nextstate(struct gps_lexer_t *lexer, unsigned char c)
lexer->length += 2; // checksum
// 10 bytes is the length of the Zodiac header
// no idea what Zodiac max length really is
- if ((MAX_PACKET_LENGTH - 10) >= lexer->length) {
- lexer->state = ZODIAC_PAYLOAD;
- } else {
+ if ((MAX_PACKET_LENGTH - 10) < lexer->length) {
+ lexer->length = 0;
return character_pushback(lexer, GROUND_STATE);
- }
+ } // else
+ lexer->state = ZODIAC_PAYLOAD;
break;
case ZODIAC_PAYLOAD:
if (0 == --lexer->length) {
@@ -1549,6 +1569,7 @@ static bool nextstate(struct gps_lexer_t *lexer, unsigned char c)
lexer->state = UBX_LENGTH_2;
} else {
// bad length
+ lexer->length = 0;
return character_pushback(lexer, GROUND_STATE);
}
break;
@@ -1604,6 +1625,7 @@ static bool nextstate(struct gps_lexer_t *lexer, unsigned char c)
lexer->length += (c << 8);
if (MAX_PACKET_LENGTH <= lexer->length) {
// bad length
+ lexer->length = 0;
return character_pushback(lexer, GROUND_STATE);
} // else
@@ -1841,16 +1863,16 @@ static bool nextstate(struct gps_lexer_t *lexer, unsigned char c)
lexer->state = GEOSTAR_MESSAGE_ID_2;
break;
case GEOSTAR_MESSAGE_ID_2:
- lexer->length = (size_t)c * 4;
+ lexer->length = c * 4;
lexer->state = GEOSTAR_LENGTH_1;
break;
case GEOSTAR_LENGTH_1:
lexer->length += (c << 8) * 4;
- if (MAX_PACKET_LENGTH >= lexer->length) {
- lexer->state = GEOSTAR_LENGTH_2;
- } else {
+ if (MAX_PACKET_LENGTH < lexer->length) {
+ lexer->length = 0;
return character_pushback(lexer, GROUND_STATE);
- }
+ } // else
+ lexer->state = GEOSTAR_LENGTH_2;
break;
case GEOSTAR_LENGTH_2:
lexer->state = GEOSTAR_PAYLOAD;
@@ -2160,6 +2182,16 @@ static bool nextstate(struct gps_lexer_t *lexer, unsigned char c)
#endif // STASH_ENABLE
}
+ /* Catch length overflow. Should not happen.
+ * length is size_t, so underflow looks like overflow too. */
+ if (MAX_PACKET_LENGTH <= lexer->length) {
+ GPSD_LOG(LOG_WARN, &lexer->errout,
+ "Too long: %zu state %u %s c x%x\n",
+ lexer->length, lexer->state, state_table[lexer->state], c);
+ // exit(255);
+ lexer->length = 0;
+ return character_pushback(lexer, GROUND_STATE);
+ }
return true; // no pushback
}
@@ -10,6 +10,7 @@ HOMEPAGE = "https://gpsd.io/"
SRC_URI = "${SAVANNAH_GNU_MIRROR}/${BPN}/${BP}.tar.gz \
file://gpsd.init \
file://CVE-2025-67268.patch \
file://CVE-2025-67269.patch \
"
SRC_URI[sha256sum] = "dc7e465968c1540e61bc57c7586d6a57a0047212a014efdad348f907bc2e0990"