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?= <bernha...@mailbox.org>
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"

Reply via email to