Subject: gpsd: SEGV when receiving short aivdm message type 26
Package: gpsd
Version: 2.95-7
Severity: important
Tags: patch
The gps daemon, when connected to public ais source, is crashing every week or
so.
I traced back the segment violation to a unsigned size being assigned a
negative value, leading to a call to memcpy with an insane value.
You can reproduce this with a simple:
echo '!AIVDM,1,1,,A,J=IJuwOmoTt,2*3F' | gpsdecode
SIGSEGV
(gdb) bt
#0 0xb75e2d5c in memcpy () from /lib/i686/cmov/libc.so.6
#1 0xb66a972b in aivdm_decode (buf=0x868e76c "!AIVDM,1,1,,A,J=IJuwOmoTt,2*3F",
buflen=31, ais_contexts=0x86e70f8,
ais=0x86e4c38) at driver_aivdm.c:810
...
(gdb) up
(gdb) display ais->type
5: ais->type = 26
(gdb) display ais->repeat
6: ais->repeat = 0
(gdb) display ais->mmsi
7: ais->mmsi = 899071485
(gdb) display ais->type
8: ais->type = 26
(gdb) display ais_context->bitlen
9: ais_context->bitlen = 64
(gdb) display ais->type26.addressed
10: ais->type26.addressed = true
(gdb) display ais->type26.structured
11: ais->type26.structured = true
(gdb) display ais->type26.dest_mmsi
12: ais->type26.dest_mmsi = 1031246784
(gdb) display ais->type26.app_id
13: ais->type26.app_id = 0
(gdb) display ais->type26.bitcount
14: ais->type26.bitcount = 4294967284
(gdb) display (ais->type26.bitcount + 7) / 8
15: (ais->type26.bitcount + 7) / 8 = 536870911
(gdb)display 60 + 16*ais->type26.structured
17: 60 + 16 * ais->type26.structured = 76
Message type 25 is checking bitlen is not too small before assigning
bitcount, after testing addressed and structured.
Attached is a 2 lines patch that adds such a test for type 26 messages.
After patching
echo '!AIVDM,1,1,,A,J=IJuwOmoTt,2*3F' | gpsdecode -D 2
yields
gpsdecode: AIVDM payload is 64 bits, 8 chars: 68d65af7f7f5de4f
gpsdecode: AIVDM message type 26, MMSI 899071485:
gpsdecode: AIVDM message type 26 too short for mode.
instead of
Segment violation
-- System Information:
Debian Release: squeeze/sid
APT prefers testing
APT policy: (500, 'testing')
Architecture: i386 (i686)
Kernel: Linux 2.6.32-5-686 (SMP w/2 CPU cores)
Locale: LANG=en_GB.utf8, LC_CTYPE=en_GB.utf8 (charmap=UTF-8)
Shell: /bin/sh linked to /bin/dash
Subject: Fixes SEGV on reception of short aivdm type 26 message
Author: Nirgal Vourgère <[email protected]>
Description: gpsd is crashing when receiving some messages such as
!AIVDM,1,1,,A,J=IJuwOmoTt,2*3F
because unsigned value ais->type26.bitcount is sometimes assigned
a negative value.
TODO (see http://dep.debian.net/deps/dep3/):
Bug-Debian: http://bugs.debian.org/500000
Last-Update: 2010-11-14
Forwarded: <no|not-needed|url proving that it has been forwarded>
Reviewed-By: <name and email of someone who approved the patch>
Index: gpsd-2.95/driver_aivdm.c
===================================================================
--- gpsd-2.95.orig/driver_aivdm.c
+++ gpsd-2.95/driver_aivdm.c
@@ -802,6 +802,10 @@
}
ais->type26.addressed = (bool)UBITS(38, 1);
ais->type26.structured = (bool)UBITS(39, 1);
+ if (ais_context->bitlen < 40 + 16*ais->type26.structured + 30*ais->type26.addressed + 20) {
+ gpsd_report(LOG_WARN, "AIVDM message type 26 too short for mode.\n");
+ return false;
+ }
if (ais->type26.addressed)
ais->type26.dest_mmsi = UBITS(40, 30);
if (ais->type26.structured)