]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
fsck.cramfs: print correct error on 32-bit systems
authorSamanta Navarro <ferivoz@riseup.net>
Fri, 20 Jan 2023 11:57:15 +0000 (11:57 +0000)
committerKarel Zak <kzak@redhat.com>
Mon, 23 Jan 2023 12:52:00 +0000 (13:52 +0100)
On 32-bit systems the file length check does not handle files correctly
which are larger than 4 GB. Use an unsigned long long which is already
in place for blkdev_get_size.

Proof of Concept:

- Prepare a file containing a CramFS
```
mkdir owo
mkfs.cramfs owo owo.iso
dd if=/dev/zero of=owo.iso bs=1 seek=4294967296 count=1 conv=notrunc
fsck.cramfs owo.iso
```

- Check the file
```
fsck.cramfs owo.iso
```

You will see: `fsck.cramfs: file length too short`
Better message is: `fsck.cramfs: file extends past end of filesystem`

Signed-off-by: Samanta Navarro <ferivoz@riseup.net>
disk-utils/fsck.cramfs.c

index 9b7e2a93b840ba623f555b17444c3f33e0ce189e..7503fae2fbb137c90bd06e61886eef8f56719eb8 100644 (file)
@@ -148,10 +148,10 @@ static int get_superblock_endianness(uint32_t magic)
        return -1;
 }
 
-static void test_super(int *start, size_t * length)
+static void test_super(int *start)
 {
        struct stat st;
-
+       unsigned long long length;
 
        fd = open(filename, O_RDONLY);
        if (fd < 0)
@@ -162,18 +162,16 @@ static void test_super(int *start, size_t * length)
                err(FSCK_EX_ERROR, _("stat of %s failed"), filename);
 
        if (S_ISBLK(st.st_mode)) {
-               unsigned long long bytes;
-               if (blkdev_get_size(fd, &bytes))
+               if (blkdev_get_size(fd, &length))
                        err(FSCK_EX_ERROR,
                            _("ioctl failed: unable to determine device size: %s"),
                            filename);
-               *length = bytes;
        } else if (S_ISREG(st.st_mode))
-               *length = st.st_size;
+               length = st.st_size;
        else
                errx(FSCK_EX_ERROR, _("not a block device or file: %s"), filename);
 
-       if (*length < sizeof(struct cramfs_super))
+       if (length < sizeof(struct cramfs_super))
                errx(FSCK_EX_UNCORRECTED, _("file length too short"));
 
        /* find superblock */
@@ -181,7 +179,7 @@ static void test_super(int *start, size_t * length)
                err(FSCK_EX_ERROR, _("cannot read %s"), filename);
        if (get_superblock_endianness(super.magic) != -1)
                *start = 0;
-       else if (*length >= (PAD_SIZE + sizeof(super))) {
+       else if (length >= (PAD_SIZE + sizeof(super))) {
                if (lseek(fd, PAD_SIZE, SEEK_SET) == (off_t) -1)
                        err(FSCK_EX_ERROR, _("seek on %s failed"), filename);
                if (read(fd, &super, sizeof(super)) != sizeof(super))
@@ -209,9 +207,9 @@ static void test_super(int *start, size_t * length)
        if (super.flags & CRAMFS_FLAG_FSID_VERSION_2) {
                if (super.fsid.files == 0)
                        errx(FSCK_EX_UNCORRECTED, _("zero file count"));
-               if (*length < super.size)
+               if (length < super.size)
                        errx(FSCK_EX_UNCORRECTED, _("file length too short"));
-               else if (*length > super.size)
+               else if (length > super.size)
                        warnx(_("file extends past end of filesystem"));
        } else
                warnx(_("old cramfs format"));
@@ -654,7 +652,6 @@ int main(int argc, char **argv)
 {
        int c;                  /* for getopt */
        int start = 0;
-       size_t length = 0;
 
        static const struct option longopts[] = {
                {"verbose",   no_argument,       NULL, 'v'},
@@ -705,7 +702,7 @@ int main(int argc, char **argv)
        }
        filename = argv[optind];
 
-       test_super(&start, &length);
+       test_super(&start);
        test_crc(start);
 
        if (opt_extract) {