[klibc] Bug#486557: cpio segfault

maximilian attems max at stro.at
Tue Jun 17 17:34:08 PDT 2008


On Tue, 17 Jun 2008, maximilian attems wrote:

> 
> > klibc cpio segfaults extracting various cpio files. It seems to work for
> > small files, but fail for larger ones, including the d-i root floppy
> > image.
> > 
> > For example:
> > 
> > joey at kodama:/tmp/empty>wget http://people.debian.org/~joeyh/d-i/images/20080401-09:01/floppy/root.img
> > joey at kodama:/tmp/empty>zcat root.img | sudo /usr/lib/klibc/bin/cpio -i
> > zsh: broken pipe         zcat root.img | 
> > zsh: segmentation fault  sudo /usr/lib/klibc/bin/cpio -i
> 
> right easy testcase.

ok so doublechecked that it is not a type issue.
right small files needs to be really small according to my tests.

but building klibc with debug aka
make V=1 DEBUG=y KLIBCOPTFLAGS='-g -Os -D DEBUG_MALLOC'
it seems that with gcc-4.3 doesn't get the sscanf() in cpio.c right

so thanks to hpa that patch got proposed

diff --git a/usr/utils/cpio.c b/usr/utils/cpio.c
index 8acfe6f..3df8927 100644
--- a/usr/utils/cpio.c
+++ b/usr/utils/cpio.c
@@ -82,19 +82,24 @@ int io_block_size = 512;
 
 struct new_cpio_header {
 	unsigned short c_magic;
-	unsigned long c_ino;
-	unsigned long c_mode;
-	unsigned long c_uid;
-	unsigned long c_gid;
-	unsigned long c_nlink;
-	unsigned long c_mtime;
-	unsigned long c_filesize;
-	long c_dev_maj;
-	long c_dev_min;
-	long c_rdev_maj;
-	long c_rdev_min;
-	unsigned long c_namesize;
-	unsigned long c_chksum;
+	union {
+		struct {
+			unsigned long c_ino;
+			unsigned long c_mode;
+			unsigned long c_uid;
+			unsigned long c_gid;
+			unsigned long c_nlink;
+			unsigned long c_mtime;
+			unsigned long c_filesize;
+			long c_dev_maj;
+			long c_dev_min;
+			long c_rdev_maj;
+			long c_rdev_min;
+			unsigned long c_namesize;
+			unsigned long c_chksum;
+		};
+		unsigned long c_hdr[13];
+	};
 	char *c_name;
 	char *c_tar_linkname;
 };
@@ -897,18 +902,17 @@ static void copyin_file(struct new_cpio_header *file_hdr, int in_file_des)
 
 static void read_in_new_ascii(struct new_cpio_header *file_hdr, int in_des)
 {
-	char ascii_header[112];
-
-	tape_buffered_read(ascii_header, in_des, 104L);
-	ascii_header[104] = '\0';
-	sscanf(ascii_header,
-	       "%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx%8lx",
-	       &file_hdr->c_ino, &file_hdr->c_mode, &file_hdr->c_uid,
-	       &file_hdr->c_gid, &file_hdr->c_nlink, &file_hdr->c_mtime,
-	       &file_hdr->c_filesize, &file_hdr->c_dev_maj,
-	       &file_hdr->c_dev_min, &file_hdr->c_rdev_maj,
-	       &file_hdr->c_rdev_min, &file_hdr->c_namesize,
-	       &file_hdr->c_chksum);
+	char ascii_header[112], *ah, hexbuf[9];
+	int i;
+
+	tape_buffered_read(ascii_header, in_des, 13*8);
+	ah = ascii_header;
+	hexbuf[8] = '\0';
+	for (i = 0; i < 13; i++) {
+		memcpy(hexbuf, ah, 8);
+		file_hdr->c_hdr[i] = strtoul(hexbuf, NULL, 16);
+		ah += 8;
+	}
 	/* Read file name from input.  */
 	if (file_hdr->c_name != NULL)
 		free(file_hdr->c_name);
 

but the memory corruption hitting that free seems to come from
another fishy culprit. this looks like a recently-allocated buffer 
overwriting the head of the free block following it.


-- 
maks



More information about the klibc mailing list