Bug 651

Summary: cp: Segmentation fault on free()
Product: Busybox Reporter: Jiri J. <jirij.jabb>
Component: OtherAssignee: unassigned
Status: RESOLVED FIXED    
Severity: normal CC: busybox-cvs
Priority: P3    
Version: unspecified   
Target Milestone: ---   
Hardware: PC   
OS: Linux   
Host: Target:
Build:
Attachments: Fix

Description Jiri J. 2009-10-07 16:24:24 UTC
There are several cases when this segfault occurs, it all boils down to the only free() call (since it happens even without FEATURE_CP_LONG_OPTIONS) in coreutils/cp.c:
<snip>
        if (copy_file(*argv, dest, flags) < 0) {
                status = EXIT_FAILURE;
        }
        free((void*)dest);
        if (*++argv == last) {
                break;
        }
</snip>

The backtrace isn't much useful even with maximum debug support I was able to get:

$ gdb ./busybox_unstripped
GNU gdb 6.8-debian
Copyright (C) 2008 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 "i486-linux-gnu"...
(gdb) run cp README delme
Starting program: /home/user/busybox/busybox_unstripped cp README delme

Program received signal SIGSEGV, Segmentation fault.
0x080eccd6 in free ()
(gdb) bt full
#0  0x080eccd6 in free ()
No symbol table info available.
#1  0x00000005 in ?? ()
No symbol table info available.
#2  0x000081a4 in ?? ()
No symbol table info available.
#3  0x0810d600 in ?? ()
No symbol table info available.
#4  0x00000000 in ?? ()
No symbol table info available.
(gdb)


Several observations:
  - it doesn't happen on something like
      cd /lib
      mkdir modules_test
      cp -r modules/* modules_test/.
  - it happens upon creating the destination file/directory
    (ie. without the "mkdir" step in previous example)
      cd /lib
      cp -r modules/ modules_test
    note: seems I can't reproduce it on any dir,
          just the "modules" dir in /lib segfaults
  - it happens on file overwrite, not only creation
    (ie. "cp README delme" several times in a row)
    so I believe it has nothing to do with this, looks more like
    a source/destination parsing problem

And the important thing - this bug was introduced with 48f116198d53, I suspect the part with free((void*)dest):
<snip>
                }
+               free((void*)dest);
                if (*++argv == last) {
-                       /* possibly leaking dest... */
                        break;
                }
-               free((void*)dest);
        }
</snip>

Tested on dcd27abcc (2009-10-05).
Comment 1 Denys Vlasenko 2009-10-07 23:51:57 UTC
Created attachment 685 [details]
Fix

Fixed with the attached patch. Sorry...