diff --git a/gpsd-cve-2025-67269.patch b/gpsd-cve-2025-67269.patch new file mode 100644 index 0000000..baa149c --- /dev/null +++ b/gpsd-cve-2025-67269.patch @@ -0,0 +1,194 @@ +commit c46d5119736af455835dd2dca304a8cb651d03b9 +Author: Gary E. Miller +Date: Wed Dec 3 19:04:03 2025 -0800 + + gpsd/packet.c: Fix integer underflow is malicious Navcom packet + + Causes DoS. Fix issue 358 + +diff --git a/gpsd/packet.c b/gpsd/packet.c +index f9a7db8d0..0c2350072 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 + } + + +commit 90f5558a8dc364bed8e2f3e2e4ecdd84f04dde46 +Author: Gary E. Miller +Date: Thu Dec 4 13:56:43 2025 -0800 + + gpsd/packet.c: Fix a logic hole in previous commit. + + Before your reject 0x103 and well as 0x03. Now only rejects, really, + when length less than 4. + +diff --git a/gpsd/packet.c b/gpsd/packet.c +index 0c2350072..99109e388 100644 +--- a/gpsd/packet.c ++++ b/gpsd/packet.c +@@ -1385,19 +1385,20 @@ static bool nextstate(struct gps_lexer_t *lexer, unsigned char c) + lexer->state = NAVCOM_ID; + break; + case NAVCOM_ID: +- /* 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); +- } ++ // Length LSB + lexer->length = c; + lexer->state = NAVCOM_LENGTH_1; + break; + case NAVCOM_LENGTH_1: +- // Length USB. Navcom allows payload length up to 65,531 ++ /* Length USB. Navcom allows payload length up to 32767 - 4 ++ * Navcom length includes command ID, length bytes. and checksum. ++ * More than just the payload length. ++ * Minimum 4 bytes */ + lexer->length += (c << 8); ++ if (4 >lexer->length ) { ++ // too short ++ return character_pushback(lexer, GROUND_STATE); ++ } + // don't count ID, length and checksum in payload length + lexer->length -= 4; + if (MAX_PACKET_LENGTH < lexer->length) { diff --git a/gpsd.spec b/gpsd.spec index 5dc75c5..62a4a31 100644 --- a/gpsd.spec +++ b/gpsd.spec @@ -27,6 +27,8 @@ Source11: gpsd.sysconfig # fix buffer overflow in NMEA2000 driver Patch1: gpsd-cve-2025-67268.patch +# fix integer underflow in handling of Navcom packets +Patch2: gpsd-cve-2025-67269.patch BuildRequires: gcc BuildRequires: dbus-devel