Article View: net.bugs.4bsd
Article #1704ncheck botches even the 1st indirect block in a directory
From: Jay Lepreau
Date: Tue, 21 Oct 1986 08:23
Date: Tue, 21 Oct 1986 08:23
120 lines
3555 bytes
3555 bytes
Index: etc/ncheck.c 4.3BSD Fix
Description:
bmap() only pretends to handle one indirect block, which is
enough in practise. However, a typo caused it to not to work
at all for indirect blocks, leading to core dumps. Instead
of reading the indirect block, it read block i-NDADDR and
grabbed bogus block numbers out of it.
Repeat-By:
Well, this was awhile ago, but if on a 4k filesys you have a
directory longer than 13*4096 == 53248, ncheck will blow up.
Fix:
The first way is to fix the typo, resulting in the same code as in dcheck.c:
383c383
< bread(fsbtodb(&sblock, gip->di_ib[i]), (char *)ibuf, sizeof(ibuf));
---
> bread(fsbtodb(&sblock, gip->di_ib[0]), (char *)ibuf, sizeof(ibuf));
The second way, which is mostly a waste of time but I actually tested
it, is to fix it "right" by lifting and hacking the indirect code from
the standalone sys.c. Here it is in case someone has directories larger
than, lessee, is it some 4 million chars on a 4k fs? Anyway, big.
*** /tmp/,RCSt1028034 Tue Oct 21 01:47:26 1986
--- /tmp/,RCSt2028034 Tue Oct 21 01:47:27 1986
***************
*** 369,385 ****
daddr_t
! bmap(i)
! int i;
{
! daddr_t ibuf[MAXNINDIR];
! if(i < NDADDR)
! return(gip->di_db[i]);
! i -= NDADDR;
! if(i > NINDIR(&sblock)) {
! fprintf(stderr, "ncheck: %u - huge directory\n", ino);
! return((daddr_t)0);
}
! bread(fsbtodb(&sblock, gip->di_ib[i]), (char *)ibuf, sizeof(ibuf));
! return(ibuf[i]);
}
--- 369,440 ----
+ /*
+ * Swiped from standalone sys.c.
+ */
+ #define NBUFS 4
+ char b[NBUFS][MAXBSIZE];
+ daddr_t blknos[NBUFS];
+
daddr_t
! bmap(bn)
! register daddr_t bn;
{
! register int j;
! int i, sh;
! daddr_t nb, *bap;
! if (bn < 0) {
! fprintf(stderr, "ncheck: bn %d negative\n", bn);
! return ((daddr_t)0);
}
!
! /*
! * blocks 0..NDADDR are direct blocks
! */
! if(bn < NDADDR)
! return(gip->di_db[bn]);
!
! /*
! * addresses NIADDR have single and double indirect blocks.
! * the first step is to determine how many levels of indirection.
! */
! sh = 1;
! bn -= NDADDR;
! for (j = NIADDR; j > 0; j--) {
! sh *= NINDIR(&sblock);
! if (bn < sh)
! break;
! bn -= sh;
! }
! if (j == 0) {
! printf("ncheck: bn %ld ovf, ino %u\n", bn, ino);
! return ((daddr_t)0);
! }
!
! /*
! * fetch the first indirect block address from the inode
! */
! nb = gip->di_ib[NIADDR - j];
! if (nb == 0) {
! printf("ncheck: bn %ld void1, ino %u\n", bn, ino);
! return ((daddr_t)0);
! }
!
! /*
! * fetch through the indirect blocks
! */
! for (; j <= NIADDR; j++) {
! if (blknos[j] != nb) {
! bread(fsbtodb(&sblock, nb), b[j], sblock.fs_bsize);
! blknos[j] = nb;
! }
! bap = (daddr_t *)b[j];
! sh /= NINDIR(&sblock);
! i = (bn / sh) % NINDIR(&sblock);
! nb = bap[i];
! if(nb == 0) {
! printf("ncheck: bn %ld void2, ino %u\n", bn, ino);
! return ((daddr_t)0);
! }
! }
! return (nb);
}
Technical Details
Message-ID:
<3965@utah-cs.UUCP>Path:
arc1-ca.pugleaf.net!utzoo!watmath!clyde!caip!rutgers!husc6!seismo!ut-sally!utah-cs!lepreauShow Full Headers
Complete Article Headers
Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: arc1-ca.pugleaf.net!utzoo!watmath!clyde!caip!rutgers!husc6!seismo!ut-sally!utah-cs!lepreau From: lepreau@utah-cs.UUCP (Jay Lepreau) Newsgroups: net.bugs.4bsd Subject: ncheck botches even the 1st indirect block in a directory Message-ID: <3965@utah-cs.UUCP> Date: Tue, 21-Oct-86 04:23:34 EDT Article-I.D.: utah-cs.3965 Posted: Tue Oct 21 04:23:34 1986 Date-Received: Wed, 22-Oct-86 03:58:00 EDT Organization: University of Utah CS Dept Lines: 120