Module Name: src Committed By: tls Date: Sun Aug 10 06:52:54 UTC 2014
Modified Files: src/sbin/fsck_msdos [tls-earlyentropy]: boot.c check.c dir.c fat.c Log Message: Rebase. To generate a diff of this commit: cvs rdiff -u -r1.15 -r1.15.22.1 src/sbin/fsck_msdos/boot.c cvs rdiff -u -r1.18 -r1.18.22.1 src/sbin/fsck_msdos/check.c cvs rdiff -u -r1.25 -r1.25.20.1 src/sbin/fsck_msdos/dir.c cvs rdiff -u -r1.24 -r1.24.6.1 src/sbin/fsck_msdos/fat.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sbin/fsck_msdos/boot.c diff -u src/sbin/fsck_msdos/boot.c:1.15 src/sbin/fsck_msdos/boot.c:1.15.22.1 --- src/sbin/fsck_msdos/boot.c:1.15 Sat Apr 11 07:14:50 2009 +++ src/sbin/fsck_msdos/boot.c Sun Aug 10 06:52:54 2014 @@ -1,4 +1,3 @@ -/* $NetBSD: boot.c,v 1.15 2009/04/11 07:14:50 lukem Exp $ */ /* * Copyright (C) 1995, 1997 Wolfgang Solfrank @@ -28,11 +27,12 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: boot.c,v 1.15 2009/04/11 07:14:50 lukem Exp $"); +__RCSID("$NetBSD: boot.c,v 1.15.22.1 2014/08/10 06:52:54 tls Exp $"); #endif /* not lint */ #include <stdlib.h> #include <string.h> +#include <strings.h> #include <stdio.h> #include <unistd.h> @@ -64,8 +64,16 @@ readboot(int dosfs, struct bootblock *bo /* decode bios parameter block */ boot->BytesPerSec = block[11] + (block[12] << 8); boot->SecPerClust = block[13]; + if (boot->SecPerClust == 0 || popcount(boot->SecPerClust) != 1) { + pfatal("Invalid cluster size: %u\n", boot->SecPerClust); + return FSFATAL; + } boot->ResSectors = block[14] + (block[15] << 8); boot->FATs = block[16]; + if (boot->FATs == 0) { + pfatal("Invalid number of FATs: %u\n", boot->FATs); + return FSFATAL; + } boot->RootDirEnts = block[17] + (block[18] << 8); boot->Sectors = block[19] + (block[20] << 8); boot->Media = block[21]; @@ -171,6 +179,10 @@ readboot(int dosfs, struct bootblock *bo } /* Check backup FSInfo? XXX */ } + if (boot->FATsecs == 0) { + pfatal("Invalid number of FAT sectors: %u\n", boot->FATsecs); + return FSFATAL; + } boot->ClusterOffset = (boot->RootDirEnts * 32 + boot->BytesPerSec - 1) / boot->BytesPerSec @@ -193,6 +205,12 @@ readboot(int dosfs, struct bootblock *bo boot->NumSectors = boot->HugeSectors; boot->NumClusters = (boot->NumSectors - boot->ClusterOffset) / boot->SecPerClust; + if (boot->ClusterOffset > boot->NumSectors) { + pfatal("Cluster offset too large (%u clusters)\n", + boot->ClusterOffset); + return FSFATAL; + } + if (boot->flags&FAT32) boot->ClustMask = CLUST32_MASK; else if (boot->NumClusters < (CLUST_RSRVD&CLUST12_MASK)) Index: src/sbin/fsck_msdos/check.c diff -u src/sbin/fsck_msdos/check.c:1.18 src/sbin/fsck_msdos/check.c:1.18.22.1 --- src/sbin/fsck_msdos/check.c:1.18 Sat Apr 11 07:14:50 2009 +++ src/sbin/fsck_msdos/check.c Sun Aug 10 06:52:54 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: check.c,v 1.18 2009/04/11 07:14:50 lukem Exp $ */ +/* $NetBSD: check.c,v 1.18.22.1 2014/08/10 06:52:54 tls Exp $ */ /* * Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank @@ -28,7 +28,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: check.c,v 1.18 2009/04/11 07:14:50 lukem Exp $"); +__RCSID("$NetBSD: check.c,v 1.18.22.1 2014/08/10 06:52:54 tls Exp $"); #endif /* not lint */ #include <stdlib.h> @@ -135,7 +135,7 @@ checkfilesys(const char *filename) goto out; /* now write the FATs */ - if (mod & FSFATMOD) { + if (mod & (FSFATMOD|FSFIXFAT)) { if (ask(1, "Update FATs")) { mod |= writefat(dosfs, &boot, fat, mod & FSFIXFAT); if (mod & FSFATAL) Index: src/sbin/fsck_msdos/dir.c diff -u src/sbin/fsck_msdos/dir.c:1.25 src/sbin/fsck_msdos/dir.c:1.25.20.1 --- src/sbin/fsck_msdos/dir.c:1.25 Sun Feb 20 21:42:50 2011 +++ src/sbin/fsck_msdos/dir.c Sun Aug 10 06:52:54 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: dir.c,v 1.25 2011/02/20 21:42:50 christos Exp $ */ +/* $NetBSD: dir.c,v 1.25.20.1 2014/08/10 06:52:54 tls Exp $ */ /* * Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank @@ -30,7 +30,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: dir.c,v 1.25 2011/02/20 21:42:50 christos Exp $"); +__RCSID("$NetBSD: dir.c,v 1.25.20.1 2014/08/10 06:52:54 tls Exp $"); #endif /* not lint */ #include <stdio.h> @@ -420,12 +420,14 @@ checksize(struct bootblock *boot, struct fullpath(dir)); if (ask(1, "Drop superfluous clusters")) { cl_t cl; - u_int32_t sz = 0; + u_int32_t sz, len; - for (cl = dir->head; (sz += boot->ClusterSize) < dir->size;) + for (cl = dir->head, len = sz = 0; + (sz += boot->ClusterSize) < dir->size; len++) cl = fat[cl].next; clearchain(boot, fat, fat[cl].next); fat[cl].next = CLUST_EOF; + fat[dir->head].length = len; return FSFATMOD; } else return FSERROR; Index: src/sbin/fsck_msdos/fat.c diff -u src/sbin/fsck_msdos/fat.c:1.24 src/sbin/fsck_msdos/fat.c:1.24.6.1 --- src/sbin/fsck_msdos/fat.c:1.24 Thu Jan 17 16:45:48 2013 +++ src/sbin/fsck_msdos/fat.c Sun Aug 10 06:52:54 2014 @@ -1,4 +1,4 @@ -/* $NetBSD: fat.c,v 1.24 2013/01/17 16:45:48 jakllsch Exp $ */ +/* $NetBSD: fat.c,v 1.24.6.1 2014/08/10 06:52:54 tls Exp $ */ /* * Copyright (C) 1995, 1996, 1997 Wolfgang Solfrank @@ -28,7 +28,7 @@ #include <sys/cdefs.h> #ifndef lint -__RCSID("$NetBSD: fat.c,v 1.24 2013/01/17 16:45:48 jakllsch Exp $"); +__RCSID("$NetBSD: fat.c,v 1.24.6.1 2014/08/10 06:52:54 tls Exp $"); #endif /* not lint */ #include <stdlib.h> @@ -355,7 +355,15 @@ tryclear(struct bootblock *boot, struct clearchain(boot, fat, head); return FSFATMOD; } else if (ask(0, "Truncate")) { + uint32_t len; + cl_t p; + + for (p = head, len = 0; + p >= CLUST_FIRST && p < boot->NumClusters; + p = fat[p].next, len++) + continue; *truncp = CLUST_EOF; + fat[head].length = len; return FSFATMOD; } else return FSERROR; @@ -384,7 +392,8 @@ checkfat(struct bootblock *boot, struct /* follow the chain and mark all clusters on the way */ for (len = 0, p = head; - p >= CLUST_FIRST && p < boot->NumClusters; + p >= CLUST_FIRST && p < boot->NumClusters && + fat[p].head != head; p = fat[p].next) { fat[p].head = head; len++; @@ -405,10 +414,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; @@ -416,14 +425,20 @@ checkfat(struct bootblock *boot, struct if (n == CLUST_FREE || n >= CLUST_RSRVD) { pwarn("Cluster chain starting at %u ends with cluster marked %s\n", head, rsrvdcltype(n)); +clear: ret |= tryclear(boot, fat, head, &fat[p].next); continue; } 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; + head, n); + goto clear; + } + if (head == fat[n].head) { + pwarn("Cluster chain starting at %u loops at cluster %u\n", + + head, p); + goto clear; } pwarn("Cluster chains starting at %u and %u are linked at cluster %u\n", head, fat[n].head, n); @@ -540,13 +555,15 @@ writefat(int fs, struct bootblock *boot, default: if (fat[cl].next == CLUST_FREE) boot->NumFree++; - if (cl + 1 < boot->NumClusters - && fat[cl + 1].next == CLUST_FREE) - boot->NumFree++; *p++ = (u_char)fat[cl].next; - *p++ = (u_char)((fat[cl].next >> 8) & 0xf) - |(u_char)(fat[cl+1].next << 4); - *p++ = (u_char)(fat[++cl].next >> 4); + *p = (u_char)((fat[cl].next >> 8) & 0xf); + cl++; + if (cl >= boot->NumClusters) + break; + if (fat[cl].next == CLUST_FREE) + boot->NumFree++; + *p++ |= (u_char)(fat[cl + 1].next << 4); + *p++ = (u_char)(fat[cl + 1].next >> 4); break; } }