Silently fix up the estimated next free cluster number from the fsinfo

sector, instead of failing the whole mount if it is garbage.  Fields
in the fsinfo sector are only advisory, so there are better sanity
checks than this, and we already silently fix up the only other advisory
field in the fsinfo (the free cluster count).

This wasn't handled quite right in rev.1.92, 1.117, or in NetBSD.  1.92
also failed the whole mount for the non-garbage magic value 0xffffffff
1.117 fixed this well enough in practice since garbage values shouldn't
occur in practice, but left the error handling larger and more convoluted
than necessary.  Now we handle the magic value as a special case of
fixing up all out of bounds values.

Also fix up the estimated next free cluster number when there is no
fsinfo sector.  We were using 0, but CLUST_FIRST is safer.

Approved by:	re (kensmith)
This commit is contained in:
Bruce Evans 2007-08-05 12:58:34 +00:00
parent 6bbb5a106c
commit 8d61a735c6

View File

@ -649,7 +649,10 @@ mountmsdosfs(struct vnode *devvp, struct mount *mp, struct thread *td)
bp = NULL;
/*
* Check FSInfo.
* Check the fsinfo sector if we have one. Silently fix up our
* in-core copy of fp->fsinxtfree if it is unknown (0xffffffff)
* or too large. Ignore fp->fsinfree for now, since we need to
* read the entire FAT anyway to fill the inuse map.
*/
if (pmp->pm_fsinfo) {
struct fsinfo *fp;
@ -662,7 +665,7 @@ mountmsdosfs(struct vnode *devvp, struct mount *mp, struct thread *td)
&& !bcmp(fp->fsisig2, "rrAa", 4)
&& !bcmp(fp->fsisig3, "\0\0\125\252", 4)) {
pmp->pm_nxtfree = getulong(fp->fsinxtfree);
if (pmp->pm_nxtfree == 0xffffffff)
if (pmp->pm_nxtfree > pmp->pm_maxcluster)
pmp->pm_nxtfree = CLUST_FIRST;
} else
pmp->pm_fsinfo = 0;
@ -671,15 +674,14 @@ mountmsdosfs(struct vnode *devvp, struct mount *mp, struct thread *td)
}
/*
* Check and validate (or perhaps invalidate?) the fsinfo structure?
* Finish initializing pmp->pm_nxtfree (just in case the first few
* sectors aren't properly reserved in the FAT). This completes
* the fixup for fp->fsinxtfree, and fixes up the zero-initialized
* value if there is no fsinfo. We will use pmp->pm_nxtfree
* internally even if there is no fsinfo.
*/
if (pmp->pm_fsinfo && pmp->pm_nxtfree > pmp->pm_maxcluster) {
printf(
"Next free cluster in FSInfo (%lu) exceeds maxcluster (%lu)\n",
pmp->pm_nxtfree, pmp->pm_maxcluster);
error = EINVAL;
goto error_exit;
}
if (pmp->pm_nxtfree < CLUST_FIRST)
pmp->pm_nxtfree = CLUST_FIRST;
/*
* Allocate memory for the bitmap of allocated clusters, and then