user/4606: cpio/pax is not 64 bit arch friendly

classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

user/4606: cpio/pax is not 64 bit arch friendly

Peter J. Philipp
>Number:         4606
>Category:       user
>Synopsis:       CRC in CPIO must be 32 bits, not so on 64 bit archs
>Confidential:   yes
>Severity:       serious
>Priority:       medium
>Responsible:    bugs
>State:          open
>Quarter:        
>Keywords:      
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Mon Nov 07 22:50:01 GMT 2005
>Closed-Date:
>Last-Modified:
>Originator:     Peter Philipp
>Release:        
>Organization:
net
>Environment:
       
        System      : OpenBSD 3.8
        Architecture: OpenBSD.amd64
        Machine     : amd64
>Description:
        If you got a file large enough the CRC in cpio/pax on 32 bit
architectures will wrap around when the checksum consumed more than 32 bits.
However on 64 bit architectures it doesn't wrap around because the crc was
declared as an unsigned long and on 64 bit architectures that makes this value
32 bits longer.  Because of the extra length the checksum does not fit into
the cpio archive field and a cpio will blow up because of this.  Here is
an example:

#  cpio -o -C 16384 < test.list > test.output
cpio: Sv4cpio header field is too small for file triton/usr/src.tgz
# ls -l triton/usr/src.tgz
-rw-r--r--  1 root  wheel  134792489 Nov  4 14:01 triton/usr/src.tgz

The place where this blew up was in file cpio.c, function vcpio_wr() when it
called ul_asc() on line 718.  

Now I created a patch for the CRC problem but the problem remains that
other structures are probably also out of wack (due to the unsigned long
declaration) and it could blow up at other times.

With the patch however it may be possible now to create / extract cpio's
between 32 bit and 64 bit architectures and not get CRC problems.

>How-To-Repeat:
        See description.
>Fix:
? cpio.cat1
? pax.cat1
? pax.patch
? tar.cat1
Index: buf_subs.c
===================================================================
RCS file: /cvs/src/bin/pax/buf_subs.c,v
retrieving revision 1.20
diff -u -r1.20 buf_subs.c
--- buf_subs.c 16 Apr 2004 22:50:23 -0000 1.20
+++ buf_subs.c 7 Nov 2005 22:10:10 -0000
@@ -677,7 +677,7 @@
  int rem;
  int sz = MINFBSZ;
  struct stat sb;
- u_long crc = 0L;
+ u_int32_t crc = 0L;
 
  /*
  * pass the blocksize of the file being written to the write routine,
Index: file_subs.c
===================================================================
RCS file: /cvs/src/bin/pax/file_subs.c,v
retrieving revision 1.29
diff -u -r1.29 file_subs.c
--- file_subs.c 25 Apr 2005 19:39:52 -0000 1.29
+++ file_subs.c 7 Nov 2005 22:10:13 -0000
@@ -1037,7 +1037,7 @@
  int res;
  off_t cpcnt = 0L;
  u_long size;
- unsigned long crc = 0L;
+ u_int32_t crc = 0L;
  char tbuf[FILEBLK];
  struct stat sb;
 
Index: pax.h
===================================================================
RCS file: /cvs/src/bin/pax/pax.h,v
retrieving revision 1.16
diff -u -r1.16 pax.h
--- pax.h 20 Oct 2003 06:22:27 -0000 1.16
+++ pax.h 7 Nov 2005 22:10:13 -0000
@@ -111,7 +111,7 @@
  /* IMPORTANT. The st_size field does */
  /* not always indicate the amount of */
  /* data following the header. */
- u_long crc; /* file crc */
+ u_int32_t crc; /* file crc */
  int type; /* type of file node */
 #define PAX_DIR 1 /* directory */
 #define PAX_CHR 2 /* character device */


>Release-Note:
>Audit-Trail:
>Unformatted:

Reply | Threaded
Open this post in threaded view
|

Re: user/4606: cpio/pax is not 64 bit arch friendly

Otto Moerbeek
The following reply was made to PR user/4606; it has been noted by GNATS.

From: Otto Moerbeek <[hidden email]>
To: [hidden email]
Cc: [hidden email]
Subject: Re: user/4606: cpio/pax is not 64 bit arch friendly
Date: Wed, 9 Nov 2005 08:33:19 +0100 (CET)

 On Mon, 7 Nov 2005, [hidden email] wrote:
 
 > >Number:         4606
 > >Category:       user
 > >Synopsis:       CRC in CPIO must be 32 bits, not so on 64 bit archs
 
 Your fix looks right. The cpio header has room for a n 8 bytes crc, but
 it is encoded in hex. Other formats do not use crc, so they are not affected.
 
 Two small nits inline
 
 > - u_long crc = 0L;
 > + u_int32_t crc = 0L;
 
 That should be 0
 
 > - unsigned long crc = 0L;
 > + u_int32_t crc = 0L;
 
 Again.
 
  -Otto