summaryrefslogtreecommitdiffstats
path: root/sys/gnu/fs/ext2fs/ext2_bmap.c
diff options
context:
space:
mode:
authorbde <bde@FreeBSD.org>1997-11-24 16:33:03 +0000
committerbde <bde@FreeBSD.org>1997-11-24 16:33:03 +0000
commitf48794b9f592747b49a561fac3392de4ae98657b (patch)
tree709ce072877f8755d18b58d51759ab3dc8b14eff /sys/gnu/fs/ext2fs/ext2_bmap.c
parent17589a04675b24622c64547b408d6243800feff0 (diff)
downloadFreeBSD-src-f48794b9f592747b49a561fac3392de4ae98657b.zip
FreeBSD-src-f48794b9f592747b49a561fac3392de4ae98657b.tar.gz
Fixed overflow in ufs_getblns(). For ufs on systems with 32-bit ints,
triple indirect blocks only worked for block sizes of 4K, since MNINDIR(ump)**3 overflows for larger block sizes (e.g., (8192/4)**3 = 2**33 > INT_MAX). This fix is not the obvious one of changing some types to 64 bits. It rearranges the code to avoid some unnecessary 64-bit calculations. Reviewed by: Kirk McKusick <mckusick@McKusick.COM>
Diffstat (limited to 'sys/gnu/fs/ext2fs/ext2_bmap.c')
-rw-r--r--sys/gnu/fs/ext2fs/ext2_bmap.c21
1 files changed, 14 insertions, 7 deletions
diff --git a/sys/gnu/fs/ext2fs/ext2_bmap.c b/sys/gnu/fs/ext2fs/ext2_bmap.c
index c85cc37..84df148 100644
--- a/sys/gnu/fs/ext2fs/ext2_bmap.c
+++ b/sys/gnu/fs/ext2fs/ext2_bmap.c
@@ -36,7 +36,7 @@
* SUCH DAMAGE.
*
* @(#)ufs_bmap.c 8.7 (Berkeley) 3/21/95
- * $Id: ufs_bmap.c,v 1.15 1997/03/09 06:10:31 mpp Exp $
+ * $Id: ufs_bmap.c,v 1.16 1997/09/02 20:06:56 bde Exp $
*/
#include <sys/param.h>
@@ -248,9 +248,10 @@ ufs_getlbns(vp, bn, ap, nump)
struct indir *ap;
int *nump;
{
- long metalbn, realbn;
+ long blockcnt, metalbn, realbn;
struct ufsmount *ump;
- int blockcnt, i, numlevels, off;
+ int i, numlevels, off;
+ int64_t qblockcnt;
ump = VFSTOUFS(vp->v_mount);
if (nump)
@@ -267,15 +268,21 @@ ufs_getlbns(vp, bn, ap, nump)
/*
* Determine the number of levels of indirection. After this loop
* is done, blockcnt indicates the number of data blocks possible
- * at the given level of indirection, and NIADDR - i is the number
+ * at the previous level of indirection, and NIADDR - i is the number
* of levels of indirection needed to locate the requested block.
*/
for (blockcnt = 1, i = NIADDR, bn -= NDADDR;; i--, bn -= blockcnt) {
if (i == 0)
return (EFBIG);
- blockcnt *= MNINDIR(ump);
- if (bn < blockcnt)
+ /*
+ * Use int64_t's here to avoid overflow for triple indirect
+ * blocks when longs have 32 bits and the block size is more
+ * than 4K.
+ */
+ qblockcnt = (int64_t)blockcnt * MNINDIR(ump);
+ if (bn < qblockcnt)
break;
+ blockcnt = qblockcnt;
}
/* Calculate the address of the first meta-block. */
@@ -299,7 +306,6 @@ ufs_getlbns(vp, bn, ap, nump)
if (metalbn == realbn)
break;
- blockcnt /= MNINDIR(ump);
off = (bn / blockcnt) % MNINDIR(ump);
++numlevels;
@@ -309,6 +315,7 @@ ufs_getlbns(vp, bn, ap, nump)
++ap;
metalbn -= -1 + off * blockcnt;
+ blockcnt /= MNINDIR(ump);
}
if (nump)
*nump = numlevels;
OpenPOWER on IntegriCloud