An integer underflow vulnerability exists in the `nextstate()` function in `gpsd/packet.c` of gpsd versions prior to commit `ffa1d6f40bca0b035fc7f5e563160ebb67199da7`. When parsing a NAVCOM packet, the payload length is calculated using `lexer->length = (size_t)c - 4` without checking if the input byte `c` is less than 4. This results in an unsigned integer underflow, setting `lexer->length` to a very large value (near `SIZE_MAX`). The parser then enters a loop attempting to consume this massive number of bytes, causing 100% CPU utilization and a Denial of Service (DoS) condition.
GPSD, a daemon for handling GPS data, is vulnerable to a Denial of Service (DoS) attack due to an integer underflow in its NAVCOM packet parsing. This flaw allows an attacker to send a crafted packet, causing the service to consume 100% CPU and become unresponsive, effectively shutting down GPS data processing.
Step 1: Packet Injection: An attacker crafts a malicious NAVCOM packet. The critical aspect of this packet is a byte value (c) in a specific position that, when subtracted by 4, results in an underflow.
Step 2: Vulnerable Function Call: The crafted packet is sent to the gpsd service, triggering the nextstate() function in gpsd/packet.c to process the NAVCOM packet.
Step 3: Length Calculation: Inside nextstate(), the vulnerable line lexer->length = (size_t)c - 4 is executed. Because c is less than 4, an underflow occurs.
Step 4: Length Overwrite: The underflow sets lexer->length to a very large value, effectively representing a huge payload size.
Step 5: Parsing Loop: The parser enters a loop, attempting to read and process the payload based on the inflated lexer->length value.
Step 6: CPU Exhaustion: The loop consumes excessive CPU resources as it tries to read a massive amount of data that doesn't exist, leading to 100% CPU utilization.
Step 7: Denial of Service: The gpsd service becomes unresponsive, effectively denying service to legitimate GPS data consumers.
The vulnerability lies within the nextstate() function in gpsd/packet.c. The code calculates the payload length using lexer->length = (size_t)c - 4 without validating that c is greater than or equal to 4. If c is less than 4, an integer underflow occurs, resulting in lexer->length being set to a very large value (close to SIZE_MAX). The subsequent parsing loop attempts to read a massive amount of data, leading to excessive CPU usage and a DoS. The root cause is a missing bounds check on the input byte c before performing the subtraction, allowing for an uncontrolled value to be used in the length calculation. This is not a buffer overflow directly, but the resulting large length value causes the parser to attempt to read far beyond the intended boundaries, effectively leading to a similar outcome.