Better kernel decompression.

committer: mfx <mfx> 978531885 +0000
This commit is contained in:
Markus F.X.J. Oberhumer
2001-01-03 14:24:45 +00:00
parent 597143df7f
commit 5ddec963d0
3 changed files with 69 additions and 23 deletions
+1 -1
View File
@@ -69,7 +69,7 @@ const int *PackElks8086::getFilters() const
// common util routines // common util routines
**************************************************************************/ **************************************************************************/
int PackElks8086::uncompressKernel() int PackElks8086::decompressKernel()
{ {
// not used // not used
return 0; return 0;
+66 -20
View File
@@ -129,9 +129,9 @@ int PackVmlinuzI386::readFileHeader()
} }
// read full kernel into obuf, gzip-uncompress into ibuf, // read full kernel into obuf[], gzip-decompress into ibuf[],
// return uncompressed size // return decompressed size
int PackVmlinuzI386::uncompressKernel() int PackVmlinuzI386::decompressKernel()
{ {
// read whole kernel image // read whole kernel image
obuf.alloc(file_size); obuf.alloc(file_size);
@@ -140,28 +140,77 @@ int PackVmlinuzI386::uncompressKernel()
checkAlreadyPacked(obuf + setup_size, UPX_MIN(file_size - setup_size, 1024)); checkAlreadyPacked(obuf + setup_size, UPX_MIN(file_size - setup_size, 1024));
// estimate gzip-uncompressed kernel size & alloc buffer
ibuf.alloc((file_size - setup_size) * 3);
for (int gzoff = setup_size; gzoff < file_size; gzoff++) for (int gzoff = setup_size; gzoff < file_size; gzoff++)
{ {
// find gzip header (2 bytes magic, 1 byte method "deflated") // find gzip header (2 bytes magic + 1 byte method "deflated")
int off = find(obuf + gzoff, file_size - gzoff, "\x1F\x8B\x08", 3); int off = find(obuf + gzoff, file_size - gzoff, "\x1F\x8B\x08", 3);
if (off < 0) if (off < 0)
break; break;
gzoff += off; gzoff += off;
// try to decompress if (gzoff + 256 >= file_size)
fi->seek(gzoff, SEEK_SET);
gzFile zf = gzdopen(fi->getFd(), "r");
if (zf == 0)
break; break;
int klen = gzread(zf, ibuf, ibuf.getSize()); // check gzip flag byte
if (klen <= file_size) unsigned char flags = obuf[gzoff + 3];
if ((flags & 0xe0) != 0) // reserved bits set
continue;
//printf("found gzip header at offset %d\n", gzoff);
// try to decompress
int klen;
int fd;
off_t fd_pos;
for (;;)
{
klen = -1;
fd = -1;
fd_pos = -1;
// open
fi->seek(gzoff, SEEK_SET);
fd = dup(fi->getFd());
if (fd < 0)
break;
gzFile zf = gzdopen(fd, "r");
if (zf == NULL)
break;
// estimate gzip-decompressed kernel size & alloc buffer
if (ibuf.getSize() == 0)
ibuf.alloc((file_size - gzoff) * 3);
// decompress
klen = gzread(zf, ibuf, ibuf.getSize());
fd_pos = lseek(fd, 0, SEEK_CUR);
gzclose(zf);
fd = -1;
if (klen != (int)ibuf.getSize())
break;
// realloc and try again
unsigned s = ibuf.getSize();
ibuf.free();
ibuf.alloc(3 * s / 2);
}
if (fd >= 0)
(void) close(fd);
if (klen <= 0)
continue; continue;
// FIXME: check for special magic bytes in ibuf ??? if (klen <= file_size - gzoff)
// FIXME: check for kernel architecture ??? continue;
// FIXME: check for special klen size, e.g. (klen & 0xfff) == 0 ???
if (opt->force > 0)
return klen;
// some checks
if (fd_pos != file_size)
{
//printf("fd_pos: %ld, file_size: %ld\n", (long)fd_pos, (long)file_size);
throwCantPack("trailing bytes after kernel image; use option `-f' to force packing");
}
// see /usr/src/linux/arch/i386/kernel/head.S:
if (memcmp(ibuf, "\xFC\xB8", 2) != 0)
throwCantPack("unrecognized kernel architecture; use option `-f' to force packing");
// FIXME: more checks for special magic bytes in ibuf ???
// FIXME: more checks for kernel architecture ???
return klen; return klen;
} }
@@ -171,12 +220,9 @@ int PackVmlinuzI386::uncompressKernel()
void PackVmlinuzI386::readKernel() void PackVmlinuzI386::readKernel()
{ {
int klen = uncompressKernel(); int klen = decompressKernel();
if (klen <= 0) if (klen <= 0)
throwCantPack("kernel decompression failed"); throwCantPack("kernel decompression failed");
if (klen >= (int) ibuf.getSize())
throwCantPack("kernel decompression failed -- too big; send a bug report");
//OutputFile::dump("kernel.img", ibuf, klen); //OutputFile::dump("kernel.img", ibuf, klen);
// copy the setup boot code // copy the setup boot code
+2 -2
View File
@@ -53,7 +53,7 @@ public:
protected: protected:
virtual int readFileHeader(); virtual int readFileHeader();
virtual int uncompressKernel(); virtual int decompressKernel();
virtual void readKernel(); virtual void readKernel();
virtual int buildLoader(const Filter *ft); virtual int buildLoader(const Filter *ft);
@@ -125,7 +125,7 @@ public:
virtual int canUnpack(); virtual int canUnpack();
protected: protected:
virtual int uncompressKernel(); virtual int decompressKernel();
virtual void readKernel(); virtual void readKernel();
virtual int buildLoader(const Filter *ft); virtual int buildLoader(const Filter *ft);