Hi, fsck_msdos is prone to an infinite loop if cluster chains in the filesystem are infinite: FAT handles clusters as linked lists, and at worst this list can be cyclic.
Android included a fix from Samsung for this issue, with the commit b6ee08aadb580341a4d80943741b80de16a88b5d: https://android.googlesource.com/platform/external/fsck_msdos/+/b6ee08aadb580341a4d80943741b80de16a88b5d I disagree on it though. Instead of finding the offending cluster, their code randomly takes one of them. In revision 1.9, mickey@ fixed this issue almost 14 years ago. His fix was incomplete though, still leading to an infinite loop later on. But his fix made it possible to retrieve the length of the cyclic list up to the offending cluster. Therefore, my diff will stop the for-loop if it hits that length, spotting the offending cluster. The user can choose if the cluster chain should be removed or truncated _at the offending cluster_. Tobias Index: fat.c =================================================================== RCS file: /cvs/src/sbin/fsck_msdos/fat.c,v retrieving revision 1.21 diff -u -p -r1.21 fat.c --- fat.c 14 Jun 2014 12:33:07 -0000 1.21 +++ fat.c 14 Jun 2014 12:50:18 -0000 @@ -364,10 +364,10 @@ checkfat(struct bootblock *boot, struct 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) + if (fat[n].head != head || len-- < 2) break; if (n >= CLUST_EOFS) continue; @@ -381,6 +381,12 @@ checkfat(struct bootblock *boot, struct if (n < CLUST_FIRST || n >= boot->NumClusters) { pwarn("Cluster chain starting at %u ends with cluster out of range (%u)\n", head, n); + 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; }