From marck@woozle.rinet.ru  Wed Jul 30 11:31:41 2003
Return-Path: <marck@woozle.rinet.ru>
Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id 2460937B401
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 30 Jul 2003 11:31:41 -0700 (PDT)
Received: from woozle.rinet.ru (woozle.rinet.ru [195.54.192.68])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 3707643FA3
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 30 Jul 2003 11:31:40 -0700 (PDT)
	(envelope-from marck@woozle.rinet.ru)
Received: from woozle.rinet.ru (localhost [127.0.0.1])
	by woozle.rinet.ru (8.12.9/8.12.9) with ESMTP id h6UIVd4C015096
	for <FreeBSD-gnats-submit@freebsd.org>; Wed, 30 Jul 2003 22:31:39 +0400 (MSD)
	(envelope-from marck@woozle.rinet.ru)
Received: (from marck@localhost)
	by woozle.rinet.ru (8.12.9/8.12.9/Submit) id h6UIVdIe015095;
	Wed, 30 Jul 2003 22:31:39 +0400 (MSD)
Message-Id: <200307301831.h6UIVdIe015095@woozle.rinet.ru>
Date: Wed, 30 Jul 2003 22:31:39 +0400 (MSD)
From: Dmitry Morozovsky <marck@rinet.ru>
Reply-To: Dmitry Morozovsky <marck@rinet.ru>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: [patch] mount_mfs crashes RELENG_4 for tyny mfs
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         55078
>Category:       bin
>Synopsis:       [patch] mount_mfs crashes RELENG_4 for tyny mfs
>Confidential:   no
>Severity:       serious
>Priority:       medium
>Responsible:    yar
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Jul 30 11:40:09 PDT 2003
>Closed-Date:    Fri Aug 15 03:10:53 PDT 2003
>Last-Modified:  Fri Aug 15 03:10:53 PDT 2003
>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:

From: Yar Tikhiy <yar@FreeBSD.org>
To: freebsd-gnats-submit@FreeBSD.org, marck@rinet.ru
Cc:  
Subject: Re: bin/55078: [patch] mount_mfs crashes RELENG_4 for tyny mfs
Date: Thu, 31 Jul 2003 17:21:01 +0400

 As long as you have investigated the problem: Don't you think that
 the kernel code must be fixed to keep from crashing as well?  Of
 course, the kernel FS code can't handle all sorts of inconsistency,
 but if a particular check is easy enough, it should be implemented,
 to my mind.

From: Dmitry Morozovsky <marck@rinet.ru>
To: Yar Tikhiy <yar@FreeBSD.org>
Cc: freebsd-gnats-submit@FreeBSD.org
Subject: Re: bin/55078: [patch] mount_mfs crashes RELENG_4 for tyny mfs
Date: Thu, 31 Jul 2003 17:27:46 +0400 (MSD)

 On Thu, 31 Jul 2003, Yar Tikhiy wrote:
 
 YT> As long as you have investigated the problem: Don't you think that
 YT> the kernel code must be fixed to keep from crashing as well?  Of
 YT> course, the kernel FS code can't handle all sorts of inconsistency,
 YT> but if a particular check is easy enough, it should be implemented,
 YT> to my mind.
 
 Surely I think the kernel should be fixed as well; however, in this particular
 case, it seems to be intentional panic:
 
 /mnt: bad dir ino 2 at offset 0: mangled entry
 panic: ufs_dirbad: bad dir
 
 from ufs_lookup.c:641
 
 Also, I'm not ufs hacker, so I'm afraid can't fix this part of kernel myself;
 however, I'll be glad to help fixing.
 
 
 Sincerely,
 D.Marck                                     [DM5020, MCK-RIPE, DM3-RIPN]
 ------------------------------------------------------------------------
 *** Dmitry Morozovsky --- D.Marck --- Wild Woozle --- marck@rinet.ru ***
 ------------------------------------------------------------------------

From: Yar Tikhiy <yar@FreeBSD.org>
To: Dmitry Morozovsky <marck@rinet.ru>
Cc: FreeBSD-gnats-submit@FreeBSD.org
Subject: Re: bin/55078: [patch] mount_mfs crashes RELENG_4 for tyny mfs
Date: Fri, 1 Aug 2003 18:09:55 +0400

 BTW, is there a chance that this bug can exist in CURRENT as well?
 
 -- 
 Yar

From: Dmitry Morozovsky <marck@rinet.ru>
To: Yar Tikhiy <yar@FreeBSD.org>
Cc: FreeBSD-gnats-submit@FreeBSD.org
Subject: Re: bin/55078: [patch] mount_mfs crashes RELENG_4 for tyny mfs
Date: Fri, 1 Aug 2003 18:26:13 +0400 (MSD)

 On Fri, 1 Aug 2003, Yar Tikhiy wrote:
 
 YT> BTW, is there a chance that this bug can exist in CURRENT as well?
 
 possible, but chances are small I think. There's no fork in -CURRENT to mount
 md AFAIR, so this part of code should be rewritten from scratch.
 
 I cannot check this myself, unfortunately, because I have no -CURRENT
 machines and no spare hardware as well, for the moment.
 
 Sincerely,
 D.Marck                                     [DM5020, MCK-RIPE, DM3-RIPN]
 ------------------------------------------------------------------------
 *** Dmitry Morozovsky --- D.Marck --- Wild Woozle --- marck@rinet.ru ***
 ------------------------------------------------------------------------
State-Changed-From-To: open->analyzed 
State-Changed-By: yar 
State-Changed-When: Mon Aug 4 07:24:17 PDT 2003 
State-Changed-Why:  
The problem has been found to exist in both STABLE and CURRENT. 
The same solution seems to apply to both. 


Responsible-Changed-From-To: freebsd-bugs->yar 
Responsible-Changed-By: yar 
Responsible-Changed-When: Mon Aug 4 07:24:17 PDT 2003 
Responsible-Changed-Why:  
I'm taking this one. 

http://www.freebsd.org/cgi/query-pr.cgi?pr=55078 

From: Yar Tikhiy <yar@FreeBSD.org>
To: Dmitry Morozovsky <marck@rinet.ru>
Cc: FreeBSD-gnats-submit@FreeBSD.org
Subject: Re: bin/55078: [patch] mount_mfs crashes RELENG_4 for tyny mfs
Date: Mon, 4 Aug 2003 18:21:48 +0400

 As a matter of fact, the same bug does exist in CURRENT.  It can
 be triggered manually, using mdconfig(8) and newfs(8), or with
 mdmfs(8).  Since some FS structure sizes and locations have changed
 in UFS2, the minimum disk size that can be successfully newfs'ed
 without tweaking any options is 144 Kbytes.  Such a filesystem will
 cause panic upon creating a file on it.
 
 As for fixing the problem, I've found a more compact solution.
 Since the function alloc() is internal to newfs, we can just bail
 out right from it on errors.  The patch attached is against STABLE.
 Could you test it?  Thanks!
 
 -- 
 Yar
 
 --- mkfs.c.orig	Mon Aug  4 18:14:09 2003
 +++ mkfs.c	Mon Aug  4 18:14:19 2003
 @@ -1062,17 +1062,17 @@
  	    (char *)&acg);
  	if (acg.cg_magic != CG_MAGIC) {
  		printf("cg 0: bad magic number\n");
 -		return (0);
 +		exit(38);
  	}
  	if (acg.cg_cs.cs_nbfree == 0) {
  		printf("first cylinder group ran out of space\n");
 -		return (0);
 +		exit(39);
  	}
  	for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag)
  		if (isblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag))
  			goto goth;
  	printf("internal error: can't find block in cyl 0\n");
 -	return (0);
 +	exit(40);
  goth:
  	blkno = fragstoblks(&sblock, d);
  	clrblock(&sblock, cg_blksfree(&acg), blkno);

From: Dmitry Morozovsky <marck@rinet.ru>
To: Yar Tikhiy <yar@FreeBSD.org>
Cc: FreeBSD-gnats-submit@FreeBSD.org
Subject: Re: bin/55078: [patch] mount_mfs crashes RELENG_4 for tyny mfs
Date: Mon, 4 Aug 2003 19:37:10 +0400 (MSD)

 Yar,
 
 of course your solution works, as would any which kills incorrect mkfs insted
 of blind return ;-)
 
 
 Sincerely,
 D.Marck                                     [DM5020, MCK-RIPE, DM3-RIPN]
 ------------------------------------------------------------------------
 *** Dmitry Morozovsky --- D.Marck --- Wild Woozle --- marck@rinet.ru ***
 ------------------------------------------------------------------------
State-Changed-From-To: analyzed->closed 
State-Changed-By: yar 
State-Changed-When: Fri Aug 15 03:10:03 PDT 2003 
State-Changed-Why:  
This bug has been fixed in CURRENT and STABLE.  Thanks! 

http://www.freebsd.org/cgi/query-pr.cgi?pr=55078 
>Unformatted:
