Subject: bin/30627: cpio (from pax) uses freed resources. Both the pkgsrc and base version
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: None <lars.nordlund@hem.utfors.se>
List: netbsd-bugs
Date: 06/28/2005 19:36:00
>Number: 30627
>Category: bin
>Synopsis: cpio (from pax) uses freed resources. Both the pkgsrc and base version
>Confidential: no
>Severity: critical
>Priority: medium
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Tue Jun 28 19:36:00 +0000 2005
>Originator: Lars Nordlund
>Release: NetBSD-current, pkgsrc-current
>Organization:
>Environment:
Linux is Fedora Core 2 test 3.
Linux lagavulin.nordlund 2.6.5-1.327smp #1 SMP Sun Apr 18 05:15:53 EDT 2004 i686 i686 i386 GNU/Linux
NetBSD ardbeg 3.99.7 NetBSD 3.99.7 (ARDBEG) #6: Sun Jun 26 11:45:06 CEST 2005 lars@ardbeg:/home/lars/tmp/obj_alpha/sys/arch/alpha/compile/ARDBEG alpha
>Description:
'cpio' from pkgsrc is broken on Linux. Sometimes it dumps core, sometimes it just says it can not find the file '<random junk chars>'.
When running pkgsrc on Linux, one is supposed to bootstrap it with 'pkgsrc/bootstrap/bootstrap'. This script will build a couple of tools which are needed for operation of pkgsrc on alien platforms like Linux. One of the tools is 'cpio' from the package pkgsrc/archivers/pax. This package is just a copy of src/usr/pax. The patch is against the pkgsrc version but should be trivial to adapt for the base version.
Perhaps should the pkgsrc version of pax be updated. There has been some fixes in the base system that perhaps should be available for people bootstrapping pkgsrc on foreign systems.
>How-To-Repeat:
I can not repeat the problem on NetBSD. It seems that the referenced memory is not reused quickly enough to cause a crash, or something. On Linux however, it is easily spotted by using cpio to copy a file tree. Like this for example:
find /usr/pkgsrc | cpio -pdum /tmp
Unfortunately I do not have a suitable printout handy right now.
>Fix:
This patch fixes cpio on the Linux box I have available.
Index: cpio.c
===================================================================
RCS file: /cvsroot/pkgsrc/archivers/pax/files/cpio.c,v
retrieving revision 1.4
diff -u -r1.4 cpio.c
--- cpio.c 21 Aug 2004 03:28:56 -0000 1.4
+++ cpio.c 28 Jun 2005 19:23:09 -0000
@@ -143,7 +143,7 @@
{
arcn->skip = 0;
arcn->pat = NULL;
- arcn->org_name = arcn->name;
+ (void)strlcpy(arcn->org_name, arcn->name, PAXPATHLEN);
switch(arcn->sb.st_mode & C_IFMT) {
case C_ISFIFO:
arcn->type = PAX_FIF;
Index: ftree.c
===================================================================
RCS file: /cvsroot/pkgsrc/archivers/pax/files/ftree.c,v
retrieving revision 1.8
diff -u -r1.8 ftree.c
--- ftree.c 21 Aug 2004 04:20:50 -0000 1.8
+++ ftree.c 28 Jun 2005 19:23:10 -0000
@@ -774,7 +774,7 @@
* copy file name, set file name length
*/
arcn->nlen = strlcpy(arcn->name, ftent->fts_path, sizeof(arcn->name));
- arcn->org_name = ftent->fts_path;
+ (void)strlcpy(arcn->org_name, ftent->fts_path, PAXPATHLEN);
if (strcmp(NM_CPIO, argv0) == 0) {
/*
* cpio does *not* descend directories listed in the
Index: pax.h
===================================================================
RCS file: /cvsroot/pkgsrc/archivers/pax/files/pax.h,v
retrieving revision 1.8
diff -u -r1.8 pax.h
--- pax.h 21 Aug 2004 03:28:56 -0000 1.8
+++ pax.h 28 Jun 2005 19:23:10 -0000
@@ -115,7 +115,7 @@
char name[PAXPATHLEN+1]; /* file name */
int ln_nlen; /* link name length */
char ln_name[PAXPATHLEN+1]; /* name to link to (if any) */
- char *org_name; /* orig name in file system */
+ char org_name[PAXPATHLEN+1]; /* orig name in file system */
char *tmp_name; /* tmp name used to restore */
PATTERN *pat; /* ptr to pattern match (if any) */
struct stat sb; /* stat buffer see stat(2) */
Index: tar.c
===================================================================
RCS file: /cvsroot/pkgsrc/archivers/pax/files/tar.c,v
retrieving revision 1.9
diff -u -r1.9 tar.c
--- tar.c 21 Aug 2004 03:28:56 -0000 1.9
+++ tar.c 28 Jun 2005 19:23:10 -0000
@@ -479,7 +479,7 @@
if (tar_id(buf, BLKMULT) < 0)
return(-1);
memset(arcn, 0, sizeof(*arcn));
- arcn->org_name = arcn->name;
+ (void)strlcpy(arcn->org_name, arcn->name, PAXPATHLEN);
arcn->pat = NULL;
arcn->sb.st_nlink = 1;
@@ -835,7 +835,7 @@
return(-1);
memset(arcn, 0, sizeof(*arcn));
- arcn->org_name = arcn->name;
+ (void)strlcpy(arcn->org_name, arcn->name, PAXPATHLEN);
arcn->pat = NULL;
arcn->sb.st_nlink = 1;
hd = (HD_USTAR *)buf;