summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStefan Fritsch <sf@cvs.openbsd.org>2023-04-30 17:16:37 +0000
committerStefan Fritsch <sf@cvs.openbsd.org>2023-04-30 17:16:37 +0000
commite31dbdb65fdfea19f60eb826a4214b2361558e74 (patch)
tree98b86434524756c2750c1f20c5630b4fed531d68
parentbdebf4c645a309c488f5cbfdd909f76c44d7117f (diff)
msdosfs: Never allocate clusters outside the volume
- Assert that usemap_alloc() and usemap_free() cluster number argument is valid. - In chainlength(), return 0 if cluster start is after the max cluster. - In chainlength(), cut the calculated cluster chain length at the max cluster. Adapted from FreeBSD commit 097a1d5fbb7990980f8f806c6878537c964adf32 ok miod@
-rw-r--r--sys/msdosfs/msdosfs_fat.c20
1 files changed, 15 insertions, 5 deletions
diff --git a/sys/msdosfs/msdosfs_fat.c b/sys/msdosfs/msdosfs_fat.c
index c15b6257d43..d31abf7d11d 100644
--- a/sys/msdosfs/msdosfs_fat.c
+++ b/sys/msdosfs/msdosfs_fat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: msdosfs_fat.c,v 1.34 2021/03/11 13:31:35 jsg Exp $ */
+/* $OpenBSD: msdosfs_fat.c,v 1.35 2023/04/30 17:16:36 sf Exp $ */
/* $NetBSD: msdosfs_fat.c,v 1.26 1997/10/17 11:24:02 ws Exp $ */
/*-
@@ -409,6 +409,7 @@ updatefats(struct msdosfsmount *pmp, struct buf *bp, uint32_t fatbn)
static __inline void
usemap_alloc(struct msdosfsmount *pmp, uint32_t cn)
{
+ KASSERT(cn <= pmp->pm_maxcluster);
pmp->pm_inusemap[cn / N_INUSEBITS] |= 1 << (cn % N_INUSEBITS);
pmp->pm_freeclustercount--;
@@ -417,6 +418,7 @@ usemap_alloc(struct msdosfsmount *pmp, uint32_t cn)
static __inline void
usemap_free(struct msdosfsmount *pmp, uint32_t cn)
{
+ KASSERT(cn <= pmp->pm_maxcluster);
pmp->pm_freeclustercount++;
pmp->pm_inusemap[cn / N_INUSEBITS] &= ~(1 << (cn % N_INUSEBITS));
@@ -644,6 +646,8 @@ chainlength(struct msdosfsmount *pmp, uint32_t start, uint32_t count)
u_int map;
uint32_t len;
+ if (start > pmp->pm_maxcluster)
+ return (0);
max_idx = pmp->pm_maxcluster / N_INUSEBITS;
idx = start / N_INUSEBITS;
start %= N_INUSEBITS;
@@ -651,11 +655,15 @@ chainlength(struct msdosfsmount *pmp, uint32_t start, uint32_t count)
map &= ~((1 << start) - 1);
if (map) {
len = ffs(map) - 1 - start;
- return (len > count ? count : len);
+ len = MIN(len, count);
+ len = MIN(len, pmp->pm_maxcluster - start + 1);
+ return (len);
}
len = N_INUSEBITS - start;
- if (len >= count)
- return (count);
+ if (len >= count) {
+ len = MIN(count, pmp->pm_maxcluster - start + 1);
+ return (len);
+ }
while (++idx <= max_idx) {
if (len >= count)
break;
@@ -665,7 +673,9 @@ chainlength(struct msdosfsmount *pmp, uint32_t start, uint32_t count)
}
len += N_INUSEBITS;
}
- return (len > count ? count : len);
+ len = MIN(len, count);
+ len = MIN(len, pmp->pm_maxcluster - start + 1);
+ return (len);
}
/*