diff --git a/sbin/fsck_msdos/boot.c b/sbin/fsck_msdos/boot.c index 77d57815b871..8632ce5d3dd0 100644 --- a/sbin/fsck_msdos/boot.c +++ b/sbin/fsck_msdos/boot.c @@ -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 #ifndef lint -__RCSID("$NetBSD: boot.c,v 1.15 2009/04/11 07:14:50 lukem Exp $"); +__RCSID("$NetBSD: boot.c,v 1.16 2014/07/07 19:04:37 christos Exp $"); #endif /* not lint */ #include #include +#include #include #include @@ -64,8 +64,16 @@ readboot(int dosfs, struct bootblock *boot) /* 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 *boot) } /* 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 *boot) 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))