summaryrefslogtreecommitdiff
path: root/sbin
diff options
context:
space:
mode:
authorTobias Stoeckmann <tobias@cvs.openbsd.org>2014-06-14 19:32:26 +0000
committerTobias Stoeckmann <tobias@cvs.openbsd.org>2014-06-14 19:32:26 +0000
commit321435a0d7839129d214171ffae5b703308b535e (patch)
treeb3442fadfb720505e9e0cc3e2b2c937a998b21fa /sbin
parent9a98ef3eab2c8772ca49e2c4a5ad66b6502ede13 (diff)
Avoid infinite loop if cluster chain is a cyclic list.
Inspired by Android's commit b6ee08aadb580341a4d80943741b80de16a88b5d, but fixing the actually offending cluster, not a random one. ok krw@
Diffstat (limited to 'sbin')
-rw-r--r--sbin/fsck_msdos/fat.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/sbin/fsck_msdos/fat.c b/sbin/fsck_msdos/fat.c
index 701e7cc1efd..f6233ceaa24 100644
--- a/sbin/fsck_msdos/fat.c
+++ b/sbin/fsck_msdos/fat.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fat.c,v 1.21 2014/06/14 12:33:07 tobias Exp $ */
+/* $OpenBSD: fat.c,v 1.22 2014/06/14 19:32:25 tobias Exp $ */
/* $NetBSD: fat.c,v 1.8 1997/10/17 11:19:53 ws Exp $ */
/*
@@ -364,11 +364,13 @@ checkfat(struct bootblock *boot, struct fatEntry *fat)
continue;
/* follow the chain to its end (hopefully) */
- for (p = head;
+ for (len = fat[head].length, p = head;
(n = fat[p].next) >= CLUST_FIRST && n < boot->NumClusters;
- p = n)
- if (fat[n].head != head)
+ p = n) {
+ /* len is always off by one due to n assignment */
+ if (fat[n].head != head || len-- < 2)
break;
+ }
if (n >= CLUST_EOFS)
continue;
@@ -384,6 +386,12 @@ checkfat(struct bootblock *boot, struct fatEntry *fat)
ret |= tryclear(boot, fat, head, &fat[p].next);
continue;
}
+ if (head == fat[n].head) {
+ pwarn("Cluster chain starting at %u loops at cluster %u\n",
+ head, p);
+ ret |= tryclear(boot, fat, head, &fat[p].next);
+ continue;
+ }
pwarn("Cluster chains starting at %u and %u are linked at cluster %u\n",
head, fat[n].head, n);
conf = tryclear(boot, fat, head, &fat[p].next);