Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!uunet!seismo!husc6!think!ames!oliveb!jerry From: jerry@oliveb.UUCP (Jerry F Aguirre) Newsgroups: comp.bugs.4bsd Subject: Large files cause fsck to dump core Message-ID: <2191@oliveb.UUCP> Date: Tue, 21-Jul-87 16:57:12 EDT Article-I.D.: oliveb.2191 Posted: Tue Jul 21 16:57:12 1987 Date-Received: Thu, 23-Jul-87 04:45:58 EDT Organization: Olivetti ATC; Cupertino, Ca Lines: 85 Keywords: 4.3BSD fsck core howmany types.h param.h Subject: Large files cause fsck to dump core Index: include/sys/types.h include/sys/param.h 4.3BSD Description: The macros defined for "howmany" and "roundup" use the classic formula (size+(blksize-1))/blksize. Unfortunately doing the addition first can overflow a long into a negative number. The resulting number of data blocks is negative and this confuses programs. In our case fsck(8) began getting a segmentation violation while checking one of our file systems. When a dump and restore failed to eliminate the problem the fsck core dump was examined. Debugging showed that howmany was returning a negative value later used as an index. This happened when checking an inode containing a user file of logical size 2147475800 (actually a "sparse" file using 32K). Repeat-By: Compile and run the following code to create a file with a large logical size. (Don't worry, it only uses 24K of real file space): main() { int fd; fd = creat("bigfile", 0777); lseek(fd, 0X7ffffe00L, 0); write(fd, "\n", 1); } Then run fsck on the file system. It will get a segmentation violation when it uses the negative value returned from "howmany" as an index. Fix: The following patches will correct the overflow problem. Install them and then recompile fsck. It will now check a file system containing the previously created large file without core dumping. *** /usr/include/sys/types.h.orig Wed Jun 4 23:30:46 1986 --- /usr/include/sys/types.h Mon Jul 6 19:28:58 1987 *************** *** 59,65 **** typedef long fd_mask; #define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ #ifndef howmany ! #define howmany(x, y) (((x)+((y)-1))/(y)) #endif typedef struct fd_set { --- 59,65 ---- typedef long fd_mask; #define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */ #ifndef howmany ! #define howmany(x, y) (((x)/(y))+(((x)%(y))?1:0)) #endif typedef struct fd_set { *** /usr/include/sys/param.h.orig Wed Jun 4 23:26:08 1986 --- /usr/include/sys/param.h Mon Jul 6 17:51:09 1987 *************** *** 175,183 **** * Macros for counting and rounding. */ #ifndef howmany ! #define howmany(x, y) (((x)+((y)-1))/(y)) #endif ! #define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) /* * Maximum size of hostname recognized and stored in the kernel. --- 175,183 ---- * Macros for counting and rounding. */ #ifndef howmany ! #define howmany(x, y) (((x)/(y))+(((x)%(y))?1:0)) #endif ! #define roundup(x, y) ((((x)/(y))+(((x)%(y))?1:0))*(y)) /* * Maximum size of hostname recognized and stored in the kernel.