From 0b39291ea2a1b5695830d5496bad3ea79c83c108 Mon Sep 17 00:00:00 2001 From: David Malone Date: Tue, 11 Apr 2006 14:45:42 +0000 Subject: [PATCH] Dump keeps a bitmap of the state of various inodes, which is sized to match the number of inodes on the disk. If we find a directory entry with a crazy inode number in it, don't look beyond the end of the bitmap to find that inode's state. Instead skip that directory entry and print a warning. Reviewed by: iedowse MFC after: 3 weeks --- sbin/dump/traverse.c | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/sbin/dump/traverse.c b/sbin/dump/traverse.c index 878f400c0d96..b05e7a6a62a5 100644 --- a/sbin/dump/traverse.c +++ b/sbin/dump/traverse.c @@ -74,10 +74,10 @@ union dinode { #define HASSUBDIRS 0x2 static int dirindir(ino_t ino, ufs2_daddr_t blkno, int level, long *size, - long *tapesize, int nodump); + long *tapesize, int nodump, ino_t maxino); static void dmpindir(ino_t ino, ufs2_daddr_t blk, int level, off_t *size); static int searchdir(ino_t ino, ufs2_daddr_t blkno, long size, long filesize, - long *tapesize, int nodump); + long *tapesize, int nodump, ino_t maxino); static long blockest(union dinode *dp); /* @@ -190,6 +190,11 @@ mapfiles(ino_t maxino, long *tapesize) (dp = getino(ino, &mode)) == NULL || (mode & IFMT) == 0) continue; + if (ino >= maxino) { + msg("Skipping inode %d >= maxino %d\n", + ino, maxino); + continue; + } /* * Everything must go in usedinomap so that a check * for "in dumpdirmap but not in usedinomap" to detect @@ -277,7 +282,7 @@ mapdirs(ino_t maxino, long *tapesize) if (DIP(&di, di_db[i]) != 0) ret |= searchdir(ino, DIP(&di, di_db[i]), (long)sblksize(sblock, DIP(&di, di_size), - i), filesize, tapesize, nodump); + i), filesize, tapesize, nodump, maxino); if (ret & HASDUMPEDFILE) filesize = 0; else @@ -287,7 +292,7 @@ mapdirs(ino_t maxino, long *tapesize) if (DIP(&di, di_ib[i]) == 0) continue; ret |= dirindir(ino, DIP(&di, di_ib[i]), i, &filesize, - tapesize, nodump); + tapesize, nodump, maxino); } if (ret & HASDUMPEDFILE) { SETINO(ino, dumpinomap); @@ -320,7 +325,8 @@ dirindir( int ind_level, long *filesize, long *tapesize, - int nodump) + int nodump, + ino_t maxino) { union { ufs1_daddr_t ufs1[MAXBSIZE / sizeof(ufs1_daddr_t)]; @@ -338,7 +344,7 @@ dirindir( blkno = idblk.ufs2[i]; if (blkno != 0) ret |= searchdir(ino, blkno, sblock->fs_bsize, - *filesize, tapesize, nodump); + *filesize, tapesize, nodump, maxino); if (ret & HASDUMPEDFILE) *filesize = 0; else @@ -354,7 +360,7 @@ dirindir( blkno = idblk.ufs2[i]; if (blkno != 0) ret |= dirindir(ino, blkno, ind_level, filesize, - tapesize, nodump); + tapesize, nodump, maxino); } return (ret); } @@ -371,7 +377,8 @@ searchdir( long size, long filesize, long *tapesize, - int nodump) + int nodump, + ino_t maxino) { int mode; struct direct *dp; @@ -393,6 +400,11 @@ searchdir( loc += dp->d_reclen; if (dp->d_ino == 0) continue; + if (dp->d_ino >= maxino) { + msg("corrupted directory entry, d_ino %d >= %d\n", + dp->d_ino, maxino); + break; + } if (dp->d_name[0] == '.') { if (dp->d_name[1] == '\0') continue;