bin/55078: [patch] mount_mfs crashes RELENG_4 for tyny mfs

Dmitry Morozovsky marck at rinet.ru
Wed Jul 30 11:40:12 PDT 2003


>Number:         55078
>Category:       bin
>Synopsis:       [patch] mount_mfs crashes RELENG_4 for tyny mfs
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Jul 30 11:40:09 PDT 2003
>Closed-Date:
>Last-Modified:
>Originator:     Dmitry Morozovsky
>Release:        FreeBSD 4-STABLE i386
>Organization:
Cronyx Plus LLC (RiNet ISP)
>Environment:
System: FreeBSD 4-STABLE 


>Description:

for restricted jail environment, it's useful to make jail filesystem nodev just
to be safe; the most useful way to make jail's /dev is mfs of minimal size.
It's possible to crash RELENG_4 system that way, as mount_mfs doesn't check it
can successfully allocate inodes for root directory, etc.

Problem is RELENG_4-specific.


---
#0  dumpsys () at /usr/src/sys/kern/kern_shutdown.c:487
487             if (dumping++) {
(kgdb) bt
#0  dumpsys () at /usr/src/sys/kern/kern_shutdown.c:487
#1  0xc013a148 in boot (howto=256) at /usr/src/sys/kern/kern_shutdown.c:316
#2  0xc013a57c in poweroff_wait (junk=0xc01f6847, howto=-1047158784) at /usr/src/sys/kern/kern_shutdown.c:595
#3  0xc01a01e2 in ufs_dirbad (ip=0xc1986400, offset=0, how=0xc01f67f0 "mangled entry") at /usr/src/sys/ufs/ufs/ufs_lookup.c:641
#4  0xc019f9eb in ufs_lookup (ap=0xc5778db8) at /usr/src/sys/ufs/ufs/ufs_lookup.c:291
#5  0xc01a4ad9 in ufs_vnoperate (ap=0xc5778db8) at /usr/src/sys/ufs/ufs/ufs_vnops.c:2376
#6  0xc016436a in vfs_cache_lookup (ap=0xc5778e10) at vnode_if.h:77
#7  0xc01a4ad9 in ufs_vnoperate (ap=0xc5778e10) at /usr/src/sys/ufs/ufs/ufs_vnops.c:2376
#8  0xc016735d in lookup (ndp=0xc5778e8c) at vnode_if.h:52
#9  0xc0166e48 in namei (ndp=0xc5778e8c) at /usr/src/sys/kern/vfs_lookup.c:153
#10 0xc016cb75 in stat (p=0xc4718c20, uap=0xc5778f80) at /usr/src/sys/kern/vfs_syscalls.c:1787
#11 0xc01d7749 in syscall2 (frame={tf_fs = 47, tf_es = 47, tf_ds = 47, tf_edi = -1077937536, tf_esi = -1077937344, 
      tf_ebp = -1077937440, tf_isp = -982020140, tf_ebx = 251860, tf_edx = -1077937348, tf_ecx = 1059584793, tf_eax = 188, 
      tf_trapno = 12, tf_err = 2, tf_eip = 671739816, tf_cs = 31, tf_eflags = 663, tf_esp = -1077937628, tf_ss = 47})
    at /usr/src/sys/i386/i386/trap.c:1175
#12 0xc01cb775 in Xint0x80_syscall ()
#13 0x804891e in ?? ()
(kgdb) 

>How-To-Repeat:

mount_mfs -s 128 -i 256 swap /mnt

[notice 'first cylinder group ran out of space']

touch /mnt/1

>Fix:

Add checks in mount_mfs:

Index: sbin/newfs/mkfs.c
===================================================================
RCS file: /home/ncvs/src/sbin/newfs/mkfs.c,v
retrieving revision 1.29.2.6
diff -u -r1.29.2.6 mkfs.c
--- mkfs.c	21 Sep 2001 19:15:21 -0000	1.29.2.6
+++ mkfs.c	30 Jul 2003 18:23:40 -0000
@@ -148,7 +148,7 @@
 long	calcipg();
 static int charsperline();
 void clrblock __P((struct fs *, unsigned char *, int));
-void fsinit __P((time_t));
+int fsinit __P((time_t));
 void initcg __P((int, time_t));
 int isblock __P((struct fs *, unsigned char *, int));
 void iput __P((struct dinode *, ino_t));
@@ -728,7 +728,8 @@
 	 * Now construct the initial file system,
 	 * then write out the super-block.
 	 */
-	fsinit(utime);
+	if (fsinit(utime) == -1)
+		exit(1);
 	sblock.fs_time = utime;
 	wtfs((int)SBOFF / sectorsize, sbsize, (char *)&sblock);
 	for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize)
@@ -968,7 +969,7 @@
 #endif
 char buf[MAXBSIZE];
 
-void
+int
 fsinit(utime)
 	time_t utime;
 {
@@ -1001,6 +1002,8 @@
 	node.di_nlink = 2;
 	node.di_size = sblock.fs_bsize;
 	node.di_db[0] = alloc(node.di_size, node.di_mode);
+	if (node.di_db[0] == 0)
+		return -1;
 	node.di_blocks = btodb(fragroundup(&sblock, node.di_size));
 	wtfs(fsbtodb(&sblock, node.di_db[0]), node.di_size, buf);
 	iput(&node, LOSTFOUNDINO);
@@ -1018,9 +1021,12 @@
 	else
 		node.di_size = makedir(root_dir, PREDEFDIR);
 	node.di_db[0] = alloc(sblock.fs_fsize, node.di_mode);
+	if (node.di_db[0] == 0)
+		return -1;
 	node.di_blocks = btodb(fragroundup(&sblock, node.di_size));
 	wtfs(fsbtodb(&sblock, node.di_db[0]), sblock.fs_fsize, buf);
 	iput(&node, ROOTINO);
+	return 0;
 }
 
 /*
>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list