fsck.cramfs: Fix bus error on broken file system.

The utility fsck.cramfs is prone to a bus error on file systems for
big endian systems with non-standard header sizes. While calculating
the crc32 checksum, it does not properly handle a possible offset
for bootcodes, resulting in out of boundary access of mmap'ed area.

You can trigger the issue with the following commands:

$ mkdir -p cramfs-poc/root/subdir
$ cd cramfs-poc
$ mkfs.cramfs -p -N big root cramfs
$ echo -ne \\00\\x4c | dd of=cramfs bs=1 seek=518 count=2 conv=notrunc
$ fsck.cramfs cramfs

Signed-off-by: Tobias Stoeckmann <tobias@stoeckmann.org>
This commit is contained in:
Tobias Stoeckmann 2017-10-30 13:49:53 +01:00 committed by Karel Zak
parent 8175ed3d74
commit 7cb962c770
1 changed files with 7 additions and 6 deletions

View File

@ -220,23 +220,24 @@ static void test_crc(int start)
crc = crc32(0L, NULL, 0);
buf =
mmap(NULL, super.size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
mmap(NULL, start + super.size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if (buf == MAP_FAILED) {
buf =
mmap(NULL, super.size, PROT_READ | PROT_WRITE,
mmap(NULL, start + super.size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
if (buf != MAP_FAILED) {
if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
if (lseek(fd, start, SEEK_SET) == (off_t) -1)
err(FSCK_EX_ERROR, _("seek on %s failed"), filename);
if (read(fd, buf, super.size) != (ssize_t) super.size)
if (read(fd, (unsigned char *) buf + start, super.size) !=
(ssize_t) super.size)
err(FSCK_EX_ERROR, _("cannot read %s"), filename);
}
}
if (buf != MAP_FAILED) {
((struct cramfs_super *)((unsigned char *) buf + start))->fsid.crc =
crc32(0L, NULL, 0);
crc = crc32(crc, (unsigned char *) buf + start, super.size - start);
munmap(buf, super.size);
crc = crc32(crc, (unsigned char *) buf + start, super.size);
munmap(buf, start + super.size);
} else {
int retval;
size_t length = 0;