Subject: fsck dumps core on corrupt inode size (+fix) Index: etc/fsck/pass1.c 2.11BSD Description: 'fsck' dumps core when the size field of an inode is corrupt. Repeat-By: Either have an errant disc controller/drive scribble a file system OR use 'adb' to poke the size field of an inode to value (1851875594 decimal is a "good" choice - it correspsonds to 067141 in the high order of the size and 060412 in the low order - "an" and "\na" respectively). Run 'fsck' on the file system and observe 'fsck' drop core. Fix: The problem can potentially occur on any file greater than 32mb in size. What is happening is that the number of blocks (specifically the low order of the number of blocks) in a file is calculated to be a negative number (within 16 bits). This allows entry with a negative block number into the loop which checks the number of "direct addresses". The fix was to turn both the "ndb" variable and loop counter into type daddr_t and use a register variable only if the block number is small (< NDADDR). Apply the patch below, recompile and install fsck. --------------------------------------------------------------------------- *** /usr/src/etc/fsck/pass1.c.old Mon Nov 18 16:35:44 1991 --- /usr/src/etc/fsck/pass1.c Thu Feb 27 11:06:07 1992 *************** *** 20,26 **** { register int j; register DINODE *dp; ! int ndb; struct inodesc idesc; register ino_t inumber; --- 20,26 ---- { register int j; register DINODE *dp; ! daddr_t ndb, lj; struct inodesc idesc; register ino_t inumber; *************** *** 85,91 **** continue; } } ! for (j = ndb; j < NDADDR; j++) if (dp->di_addr[j] != 0) { if (debug) printf("bad direct di_addr[%d]: %ld\n", --- 85,92 ---- continue; } } ! for (lj = ndb; lj < NDADDR; lj++) { ! j = lj; if (dp->di_addr[j] != 0) { if (debug) printf("bad direct di_addr[%d]: %ld\n", *************** *** 92,97 **** --- 93,99 ---- j, dp->di_addr[j]); goto unknown; } + } for (j = 0, ndb -= NDADDR; ndb > 0; j++) ndb /= NINDIR; for (; j < NIADDR; j++)