Hello all,
just tried to and could reproduce this crash on a Raspbian.
But because of the lack of debug symbols in Raspbian (or the
lack of knowledge where to find them) I tried a i386 Buster VM,
but there was no crash visible.
But a valgrind run shows following:
valgrind gpxlogger -f /GPX/trk.gpx
==16014== Memcheck, a memory error detector
==16014== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==16014== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==16014== Command: gpxlogger -f /GPX/trk.gpx
==16014==
==16014== Invalid write of size 1
==16014== at 0x4A88620: __strftime_internal (strftime_l.c:1433)
==16014== by 0x4A8A6B1: strftime_l (strftime_l.c:460)
==16014== by 0x4A8851A: strftime (strftime.c:25)
==16014== by 0x109A1A: main (gpxlogger.c:248)
==16014== Address 0x4da0084 is 0 bytes after a block of size 12 alloc'd
==16014== at 0x483356B: malloc (vg_replace_malloc.c:298)
==16014== by 0x483582C: realloc (vg_replace_malloc.c:785)
==16014== by 0x1099E6: main (gpxlogger.c:240)
==16014==
To the strftime function is a buffer given for which is memory
allocated in the size of the parameter "/GPX/trk.gpx" on the command line.
Also the strftime function takes a parameter fnamesize-1 for this memory.
If the buffer size is too small strftime returns 0
and the allocated buffer size should be increased.
Unfortunately this size parameter is increased before the strftime call.
Therefore we have just 12 bytes allocated
but tell strftime it is allowed to write to 1035 bytes.
Attached patch tries to move this addition below the strftime call.
Kind regards,
Bernhard
From 775532253ba4cade582866780ad9415491f6b94d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bernhard=20=C3=9Cbelacker?= <[email protected]>
Date: Tue, 18 Sep 2018 15:53:08 +0200
Subject: [PATCH] gpxlogger: Move buffer extension below the strftime call.
Bug-Debian: https://bugs.debian.org/909082
Last-Update: 2018-09-18
---
gpxlogger.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/gpxlogger.c b/gpxlogger.c
index fda37ff..bf1844e 100644
--- a/gpxlogger.c
+++ b/gpxlogger.c
@@ -233,7 +233,7 @@ int main(int argc, char **argv)
char *fname = NULL;
time_t t;
size_t s = 0;
- size_t fnamesize = strlen(optarg);
+ size_t fnamesize = strlen(optarg) + 1;
t = time(NULL);
while (s == 0) {
@@ -242,10 +242,11 @@ int main(int argc, char **argv)
syslog(LOG_ERR, "realloc failed.");
goto bailout;
} else {
- fnamesize += 1024;
fname = newfname;
}
s = strftime(fname, fnamesize-1, optarg, localtime(&t));
+ if (!s)
+ fnamesize += 1024;
}
fname[s] = '\0';;
logfile = fopen(fname, "w");
--
2.18.0
# Raspbian
apt update
apt install systemd-coredump mc
export PKG="gpsd-clients gpsd-dbg valgrind gdb"; apt install $PKG; apt-mark
auto $PKG
mkdir gpsd/orig -p
cd gpsd/orig
apt source gpsd
cd ../..
gpxlogger -f /GPXX/trk.gpx
Speicherzugriffsfehler (Speicherabzug geschrieben)
coredumpctl gdb
PID: 2088 (gpxlogger)
UID: 1001 (benutzer)
GID: 1001 (benutzer)
Signal: 11 (SEGV)
Timestamp: Tue 2018-09-18 15:18:56 CEST (9min ago)
Command Line: gpxlogger -f /GPXX/trk.gpx
Executable: /usr/bin/gpxlogger
Control Group: /user.slice/user-1001.slice/session-c2.scope
Unit: session-c2.scope
Slice: user-1001.slice
Session: c2
Owner UID: 1001 (benutzer)
Boot ID: 8be013eea88941bcabd05635419cdce7
Machine ID: 1ec87cb843e543a492b24a30f5a875c1
Hostname: raspberrypi
Storage:
/var/lib/systemd/coredump/core.gpxlogger.1001.8be013eea88941bcabd05635419cdce7.2088.1537276736000000000000.lz4
Message: Process 2088 (gpxlogger) of user 1001 dumped core.
Stack trace of thread 2088:
#0 0x00000000b6d5b404 __GI__IO_fwrite (libc.so.6)
#1 0x0000000000011c04 n/a (gpxlogger)
GNU gdb (Raspbian 7.12-6) 7.12.0.20161007-git
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "arm-linux-gnueabihf".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /usr/bin/gpxlogger...(no debugging symbols found)...done.
[New LWP 2088]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/arm-linux-gnueabihf/libthread_db.so.1".
Core was generated by `gpxlogger -f /GPXX/trk.gpx'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 __GI__IO_fwrite (buf=0x2264c, size=1, count=39, fp=0x0) at iofwrite.c:37
37 iofwrite.c: Datei oder Verzeichnis nicht gefunden.
(gdb) bt
#0 __GI__IO_fwrite (buf=0x2264c, size=1, count=39, fp=0x0) at iofwrite.c:37
#1 0x00011c04 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
-> Is there a dbgsym repository in Raspbian?
####################
####################
####################
# Buster VM
apt update
apt install systemd-coredump mc gpsd-clients gpsd-dbg valgrind gdb
apt build-dep gpsd
mkdir gpsd/orig -p
cd gpsd/orig
apt source gpsd
cd ../..
gpxlogger -f /GPX/trk.gpx
# -> no crash
valgrind gpxlogger -f /GPX/trk.gpx
==16014== Memcheck, a memory error detector
==16014== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==16014== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==16014== Command: gpxlogger -f /GPX/trk.gpx
==16014==
==16014== Invalid write of size 1
==16014== at 0x4A88620: __strftime_internal (strftime_l.c:1433)
==16014== by 0x4A8A6B1: strftime_l (strftime_l.c:460)
==16014== by 0x4A8851A: strftime (strftime.c:25)
==16014== by 0x109A1A: main (gpxlogger.c:248)
==16014== Address 0x4da0084 is 0 bytes after a block of size 12 alloc'd
==16014== at 0x483356B: malloc (vg_replace_malloc.c:298)
==16014== by 0x483582C: realloc (vg_replace_malloc.c:785)
==16014== by 0x1099E6: main (gpxlogger.c:240)
==16014==
...
gdb -q --args gpxlogger -f /GPX/trk.gpx
set height 0
set width 0
set pagination off
directory /home/benutzer/gpsd/orig/gpsd-3.17
b main:248
run
b strftime
b realloc
240 char *newfname = realloc(fname, fnamesize);
(gdb) print fnamesize
$4 = 12
248 s = strftime(fname, fnamesize-1, optarg,
localtime(&t));
(gdb) print fnamesize
$8 = 1036
(gdb) list 236
231 case 'f': /* Output file name. */
232 {
233 char *fname = NULL;
234 time_t t;
235 size_t s = 0;
236 size_t fnamesize = strlen(optarg);
237
238 t = time(NULL);
239 while (s == 0) {
240 char *newfname = realloc(fname, fnamesize);
241 if (newfname == NULL) {
242 syslog(LOG_ERR, "realloc failed.");
243 goto bailout;
244 } else {
245 fnamesize += 1024;
246 fname = newfname;
247 }
248 s = strftime(fname, fnamesize-1, optarg,
localtime(&t));
249 }
250 fname[s] = '\0';;
251 logfile = fopen(fname, "w");
252 if (logfile == NULL) {
253 syslog(LOG_ERR,
254 "Failed to open %s: %s, logging to stdout.",
255 fname, strerror(errno));
256 logfile = stdout;
257 }
258 bailout:
259 free(fname);
260 break;
261 }
cp orig try1 -a
cd try1/gpsd-3.17
git init
git add .
git commit -m "Initial commit"