When there is an error while doing copy to local, tolocal()-> run_err()
leads to a segmentation fault, as there is possible bug of calling vfprintf
twice without va_start()/va_end() for the second vfprintf call.
The similar coding issue is discussed here in this link too
https://sourceware.org/bugzilla/show_bug.cgi?id=366

Issue is reproducible in 64bit:
rcp: ELF 64-bit LSB  executable, x86-64, version 1 (SYSV), dynamically
linked (uses shared libs), for GNU/Linux 2.6.34, not stripped

Backtrace/GDB output:
Core was generated by `rcp 10.0.01 /tmp/file.txt /tmp/file.txt'.
Program terminated with signal 11, Segmentation fault.
#0  0x000000393d047ec7 in _IO_vfprintf_internal (s=<optimized out>,
    format=<optimized out>, ap=<optimized out>) at vfprintf.c:1655
1655    vfprintf.c: No such file or directory.
(gdb) bt
#0  0x000000393d047ec7 in _IO_vfprintf_internal (s=<optimized out>,
    format=<optimized out>, ap=<optimized out>) at vfprintf.c:1655
#1  0x000000393d04b311 in buffered_vfprintf (
    s=s@entry=0x393d3a5060 <_IO_2_1_stderr_>,
    format=format@entry=0x40abf9 "%s: %s", args=args@entry=0x7fff6c1e6758)
    at vfprintf.c:2351
#2  0x000000393d04647e in _IO_vfprintf_internal (
    s=0x393d3a5060 <_IO_2_1_stderr_>, format=format@entry=0x40abf9 "%s: %s",
    ap=ap@entry=0x7fff6c1e6758) at vfprintf.c:1307
#3  0x000000000040245b in run_err (fmt=fmt@entry=0x40abf9 "%s: %s")
    at rcp.c:1116
#4  0x00000000004033bd in sink (argc=<optimized out>, argv=<optimized out>)
    at rcp.c:986
#5  0x0000000000403cdf in tolocal (argc=30, argc@entry=2,
argv=0x7fff6c1e8b10)
    at rcp.c:509
#6  0x0000000000401ec1 in main (argc=2, argv=0x7fff6c1e8b10) at rcp.c:344


Proposed Patch for the Fix:
--- inetutils-1.9.1-orig/src/rcp.c      2015-09-12 02:28:28.126920410 -0700
+++ inetutils-1.9.1-new/src/rcp.c       2015-09-12 06:54:28.884362307 -0700
@@ -1097,9 +1097,10 @@
 run_err (const char *fmt, ...)
 {
   static FILE *fp;
-  va_list ap;
+  va_list ap, ap2;

   va_start (ap, fmt);
+  va_copy (ap2, ap);

   ++errs;
   if (fp == NULL && !(fp = fdopen (rem, "w")))
@@ -1113,11 +1114,12 @@
   if (!iamremote)
     {
       fprintf (stderr, "%s: ", program_invocation_name);
-      vfprintf (stderr, fmt, ap);
+      vfprintf (stderr, fmt, ap2);
       fprintf (stderr, "\n");
     }

   va_end (ap);
+  va_end (ap2);
 }

Signing off.
-Antony Rheneus

Reply via email to