[PATCH] 2.4.0-ac11: small NTFS fixes

From: Anton Altaparmakov (aia21@cus.cam.ac.uk)
Date: Thu Jan 25 2001 - 18:17:49 EST


Alan,

Please apply attached ntfs patch for next 2.4.0-ac kernel release.

It fixes a long standing bug where values of lengths of runs were
considered unsigned when they are in fact signed numbers (both read and
write). Also it makes a correction to how negative mft_recordsizes are
handled.

Thanks go to Yuri Per <yuri@acronis.com> for the initial patch (which
required only a tiny modification).

Best regards,

        Anton

-- 
Anton Altaparmakov <aia21 at cam.ac.uk> (replace at with @)
Linux NTFS Maintainer
ICQ: 8561279 / WWW: http://www-stu.christs.cam.ac.uk/~aia21/

diff -ur linux-2.4.0-ac11-vanilla/fs/ntfs/inode.c linux/fs/ntfs/inode.c --- linux-2.4.0-ac11-vanilla/fs/ntfs/inode.c Wed Jan 24 23:23:46 2001 +++ linux/fs/ntfs/inode.c Thu Jan 25 23:42:52 2001 @@ -444,16 +444,16 @@ *ctype = 0; switch (type & 0xF) { case 1: - *length = NTFS_GETU8(*data); + *length = NTFS_GETS8(*data); break; case 2: - *length = NTFS_GETU16(*data); + *length = NTFS_GETS16(*data); break; case 3: - *length = NTFS_GETU24(*data); + *length = NTFS_GETS24(*data); break; case 4: - *length = NTFS_GETU32(*data); + *length = NTFS_GETS32(*data); break; /* Note: cases 5-8 are probably pointless to code, since how * many runs > 4GB of length are there? At the most, cases 5 @@ -463,6 +463,11 @@ ntfs_error("Can't decode run type field %x\n", type); return -1; } + if (*length < 0) + { + ntfs_error("Negative run length decoded\n"); + return -1; + } *data += (type & 0xF); switch (type & 0xF0) { case 0: @@ -704,13 +709,14 @@ if (offset + 8 > size) return -E2BIG; /* It might still fit, but this * simplifies testing. */ - if (len < 0x100) { + /* Run length is stored as signed number. */ + if (len <= 0x7F) { NTFS_PUTU8(rec + offset + 1, len); coffs = 1; - } else if (len < 0x10000) { + } else if (len < 0x7FFF) { NTFS_PUTU16(rec + offset + 1, len); coffs = 2; - } else if (len < 0x1000000) { + } else if (len < 0x7FFFFF) { NTFS_PUTU24(rec + offset + 1, len); coffs = 3; } else { @@ -720,21 +726,21 @@ *(rec + offset) |= coffs++; if (rl[i].cluster == MAX_CLUSTER_T) /* Compressed run. */ /* Nothing */; - else if (rclus > -0x80 && rclus < 0x7F) { + else if (rclus >= -0x80 && rclus <= 0x7F) { *(rec + offset) |= 0x10; NTFS_PUTS8(rec + offset + coffs, rclus); coffs += 1; - } else if(rclus > -0x8000 && rclus < 0x7FFF) { + } else if(rclus >= -0x8000 && rclus <= 0x7FFF) { *(rec + offset) |= 0x20; NTFS_PUTS16(rec + offset + coffs, rclus); coffs += 2; - } else if(rclus > -0x800000 && rclus < 0x7FFFFF) { + } else if(rclus >= -0x800000 && rclus <= 0x7FFFFF) { *(rec + offset) |= 0x30; NTFS_PUTS24(rec + offset + coffs, rclus); coffs += 3; } else #if 0 /* In case ntfs_cluster_t ever becomes 64bit. */ - if (rclus > -0x80000000LL && rclus < 0x7FFFFFFF) + if (rclus >= -0x80000000LL && rclus <= 0x7FFFFFFF) #endif { *(rec + offset) |= 0x40; @@ -742,16 +748,17 @@ coffs += 4; } #if 0 /* For 64-bit ntfs_cluster_t */ - else if (rclus > -0x8000000000 && rclus < 0x7FFFFFFFFF) { + else if (rclus >= -0x8000000000 && rclus <= 0x7FFFFFFFFF) { *(rec + offset) |= 0x50; NTFS_PUTS40(rec + offset + coffs, rclus); coffs += 5; - } else if (rclus > -0x800000000000 && rclus < 0x7FFFFFFFFFFF) { + } else if (rclus >= -0x800000000000 && + rclus <= 0x7FFFFFFFFFFF) { *(rec + offset) |= 0x60; NTFS_PUTS48(rec + offset + coffs, rclus); coffs += 6; - } else if (rclus > -0x80000000000000 && - rclus < 0x7FFFFFFFFFFFFF) { + } else if (rclus >= -0x80000000000000 && + rclus <= 0x7FFFFFFFFFFFFF) { *(rec + offset) |= 0x70; NTFS_PUTS56(rec + offset + coffs, rclus); coffs += 7; diff -ur linux-2.4.0-ac11-vanilla/fs/ntfs/super.c linux/fs/ntfs/super.c --- linux-2.4.0-ac11-vanilla/fs/ntfs/super.c Wed Jan 24 23:23:46 2001 +++ linux/fs/ntfs/super.c Thu Jan 25 23:52:43 2001 @@ -89,18 +89,19 @@ should be safe. */ vol->index_clusters_per_record = 1; } - /* In some cases, 0xF6 meant 1024 bytes. Other strange values have not - been observed */ - if (vol->mft_clusters_per_record < 0 && - vol->mft_clusters_per_record != -10) - ntfs_error("Unexpected data #4 in boot block\n"); - vol->clustersize = vol->blocksize << vol->clusterfactorbits; if (vol->mft_clusters_per_record > 0) vol->mft_recordsize = vol->clustersize * vol->mft_clusters_per_record; - else + else { + /* If mft_recordsize < clustersize then mft_clusters_per_record + = -log2(mft_recordsize) bytes. Mft_recordsize normaly equals + 1024 bytes, which is encoded as 0xF6. */ + if (vol->mft_clusters_per_record < -31 || + -9 < vol->mft_clusters_per_record) + ntfs_error("Unexpected data #4 in boot block\n"); vol->mft_recordsize = 1 << (-vol->mft_clusters_per_record); + } vol->index_recordsize = vol->clustersize * vol->index_clusters_per_record; /* FIXME: long long value */ - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Wed Jan 31 2001 - 21:00:23 EST