summaryrefslogtreecommitdiff
path: root/sys/msdosfs
diff options
context:
space:
mode:
authorTom Cosgrove <tom@cvs.openbsd.org>2005-03-01 14:29:02 +0000
committerTom Cosgrove <tom@cvs.openbsd.org>2005-03-01 14:29:02 +0000
commit7c8c5063457b3715b746ca8c368fd262203ef5ed (patch)
tree0a3537a7e931c911d03086644607ef5e1d0f30a0 /sys/msdosfs
parente177759a416ea6ef09860382e66d9a3afc94a7fe (diff)
Fix an integer overflow that prevented us from reading files >= 2 GB
from MS-DOS filesystems. Assistance otto@; thanks. "looks ok" krw@; ok derradt@.
Diffstat (limited to 'sys/msdosfs')
-rw-r--r--sys/msdosfs/msdosfs_vnops.c20
1 files changed, 14 insertions, 6 deletions
diff --git a/sys/msdosfs/msdosfs_vnops.c b/sys/msdosfs/msdosfs_vnops.c
index 9fa6dad1c6a..a05abf62425 100644
--- a/sys/msdosfs/msdosfs_vnops.c
+++ b/sys/msdosfs/msdosfs_vnops.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: msdosfs_vnops.c,v 1.50 2005/03/01 14:24:33 tom Exp $ */
+/* $OpenBSD: msdosfs_vnops.c,v 1.51 2005/03/01 14:29:01 tom Exp $ */
/* $NetBSD: msdosfs_vnops.c,v 1.63 1997/10/17 11:24:19 ws Exp $ */
/*-
@@ -425,10 +425,10 @@ msdosfs_read(v)
struct ucred *a_cred;
} */ *ap = v;
int error = 0;
- int diff;
+ uint32_t diff;
int blsize;
int isadir;
- long n;
+ uint32_t n;
long on;
daddr_t lbn;
daddr_t rablock;
@@ -449,14 +449,22 @@ msdosfs_read(v)
isadir = dep->de_Attributes & ATTR_DIRECTORY;
do {
+ if (uio->uio_offset >= dep->de_FileSize)
+ return (0);
+
lbn = de_cluster(pmp, uio->uio_offset);
on = uio->uio_offset & pmp->pm_crbomask;
n = min((uint32_t) (pmp->pm_bpcluster - on), uio->uio_resid);
- diff = dep->de_FileSize - uio->uio_offset;
- if (diff <= 0)
- return (0);
+
+ /*
+ * de_FileSize is uint32_t, and we know that uio_offset <
+ * de_FileSize, so uio->uio_offset < 2^32. Therefore
+ * the cast to uint32_t on the next line is safe.
+ */
+ diff = dep->de_FileSize - (uint32_t)uio->uio_offset;
if (diff < n)
n = diff;
+
/* convert cluster # to block # if a directory */
if (isadir) {
error = pcbmap(dep, lbn, &lbn, 0, &blsize);