Module Name: src Committed By: mlelstv Date: Tue May 3 18:17:29 UTC 2016
Modified Files: src/sys/fs/msdosfs: msdosfs_fat.c Log Message: Validate FAT entries to avoid some panics caused by a corrupted FAT. Also print FAT write errors when mount is synchronous (-o sync). This reveals problems caused by a write protected disklabel on sector 1. To generate a diff of this commit: cvs rdiff -u -r1.29 -r1.30 src/sys/fs/msdosfs/msdosfs_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/sys/fs/msdosfs/msdosfs_fat.c diff -u src/sys/fs/msdosfs/msdosfs_fat.c:1.29 src/sys/fs/msdosfs/msdosfs_fat.c:1.30 --- src/sys/fs/msdosfs/msdosfs_fat.c:1.29 Sat Mar 28 19:24:05 2015 +++ src/sys/fs/msdosfs/msdosfs_fat.c Tue May 3 18:17:28 2016 @@ -1,4 +1,4 @@ -/* $NetBSD: msdosfs_fat.c,v 1.29 2015/03/28 19:24:05 maxv Exp $ */ +/* $NetBSD: msdosfs_fat.c,v 1.30 2016/05/03 18:17:28 mlelstv Exp $ */ /*- * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank. @@ -52,7 +52,7 @@ #endif #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: msdosfs_fat.c,v 1.29 2015/03/28 19:24:05 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: msdosfs_fat.c,v 1.30 2016/05/03 18:17:28 mlelstv Exp $"); /* * kernel include files. @@ -273,6 +273,18 @@ pcbmap(struct denode *dep, u_long findcn */ if (cn >= (CLUST_RSRVD & pmp->pm_fatmask)) goto hiteof; + + /* + * Also stop when cluster is not in the filesystem + */ + if (cn < CLUST_FIRST || cn > pmp->pm_maxcluster) { + DPRINTF(("%s(cn, %lu not in %lu..%lu)\n", __func__, + cn, CLUST_FIRST, pmp->pm_maxcluster)); + if (bp) + brelse(bp, 0); + return (EINVAL); + } + byteoffset = FATOFS(pmp, cn); fatblock(pmp, byteoffset, &bn, &bsize, &bo); if (bn != bp_bn) { @@ -383,7 +395,7 @@ fc_purge(struct denode *dep, u_int frcn) void updatefats(struct msdosfsmount *pmp, struct buf *bp, u_long fatbn) { - int i; + int i, error; struct buf *bpn; DPRINTF(("%s(pmp %p, bp %p, fatbn %lu)\n", __func__, pmp, bp, fatbn)); @@ -448,9 +460,12 @@ updatefats(struct msdosfsmount *pmp, str bpn = getblk(pmp->pm_devvp, de_bn2kb(pmp, fatbn), bp->b_bcount, 0, 0); memcpy(bpn->b_data, bp->b_data, bp->b_bcount); - if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT) - bwrite(bpn); - else + if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT) { + error = bwrite(bpn); + if (error) + printf("%s: copy FAT %d (error=%d)\n", + __func__, i, error); + } else bdwrite(bpn); } } @@ -458,9 +473,12 @@ updatefats(struct msdosfsmount *pmp, str /* * Write out the first (or current) FAT last. */ - if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT) - bwrite(bp); - else + if (pmp->pm_flags & MSDOSFSMNT_WAITONFAT) { + error = bwrite(bp); + if (error) + printf("%s: write FAT (error=%d)\n", + __func__, error); + } else bdwrite(bp); /* * Maybe update fsinfo sector here?