Bug 138367 - [tmpfs] [panic] 'panic: Assertion pages > 0 failed' when running regression/tmpfs
Summary: [tmpfs] [panic] 'panic: Assertion pages > 0 failed' when running regression/t...
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 8.0-BETA3
Hardware: Any Any
: Normal Affects Only Me
Assignee: Jaakko Heinonen
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2009-08-31 02:20 UTC by Rebecca Cran
Modified: 2012-02-07 18:09 UTC (History)
0 users

See Also:


Attachments
tmpfs-intoverflow.patch.txt (3.80 KB, text/plain; charset=utf-8)
2009-10-03 10:21 UTC, Gleb Kurtsou
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Rebecca Cran freebsd_committer freebsd_triage 2009-08-31 02:20:04 UTC
When running 'make regress' in tools/regression/tmpfs the following panic occurs:

panic: Assertion pages > 0 failed at /usr/src/sys/modules/tmpfs/../../fs/tmpfs/tmpfs_vfsops.c:246

(kgdb) bt
#0  doadump () at pcpu.h:246
#1  0xc08801de in boot (howto=260) at /usr/src/sys/kern/kern_shutdown.c:416
#2  0xc08804b2 in panic (fmt=Variable "fmt" is not available.
) at /usr/src/sys/kern/kern_shutdown.c:579
#3  0xc4de9385 in tmpfs_mount (mp=0xc4966000) at /usr/src/sys/modules/tmpfs/../../fs/tmpfs/tmpfs_vfsops.c:246
#4  0xc09097c2 in vfs_donmount (td=0xc497b000, fsflags=0, fsoptions=0xc4c4f100) at /usr/src/sys/kern/vfs_mount.c:984
#5  0xc090aec5 in nmount (td=0xc497b000, uap=0xe6b60cf8) at /usr/src/sys/kern/vfs_mount.c:420
#6  0xc0bb0143 in syscall (frame=0xe6b60d38) at /usr/src/sys/i386/i386/trap.c:1071
#7  0xc0b929b0 in Xint0x80_syscall () at /usr/src/sys/i386/i386/exception.s:261
#8  0x00000033 in ?? ()
Previous frame inner to this frame (corrupt stack?)

How-To-Repeat: run 'make regress' in /usr/src/tools/regression/tmpfs
Comment 1 Mark Linimon freebsd_committer freebsd_triage 2009-08-31 04:59:14 UTC
Responsible Changed
From-To: freebsd-bugs->freebsd-fs

Over to maintainer(s).
Comment 2 Gleb Kurtsou 2009-10-03 10:21:08 UTC
I wasn't able to trigger it on amd64, but there were several integer
overflow bugs.

Besides there was inconsistency in setting max values. Max pages was set
to SIZE_MAX (if no value provided by user), but max file size depended
on available swap/memory at the moment of mounting filesystem. I've set
max file size to 4GB (of memory limit set by user). It can be changed to
uint64_t max, but using 4GB seems to be sufficient limit to prevent
resource exhaustion.

Would you try this patch, I have no i386 system running to test it.
Comment 3 Jaakko Heinonen freebsd_committer freebsd_triage 2010-01-16 10:31:57 UTC
State Changed
From-To: open->feedback

The reported panic should not occur after r201773. Can you confirm? 


Comment 4 Jaakko Heinonen freebsd_committer freebsd_triage 2010-01-16 10:31:57 UTC
Responsible Changed
From-To: freebsd-fs->jh

I'll try to look at the other issues raised by Gleb Kurtsou.
Comment 5 Rebecca Cran freebsd_committer freebsd_triage 2010-01-16 11:37:17 UTC
Sorry for the delay in replying. I only managed to cause the panic
once, and was unable to reproduce the crash when I tried again later.

-- 
Bruce Cran
Comment 6 dfilter service freebsd_committer freebsd_triage 2010-01-20 16:56:36 UTC
Author: jh
Date: Wed Jan 20 16:56:20 2010
New Revision: 202708
URL: http://svn.freebsd.org/changeset/base/202708

Log:
  - Change the type of nodes_max to u_int and use "%u" format string to
    convert its value. [1]
  - Set default tm_nodes_max to min(pages + 3, UINT32_MAX). It's more
    reasonable than the old four nodes per page (with page size 4096) because
    non-empty regular files always use at least one page. This fixes possible
    overflow in the calculation. [2]
  - Don't allow more than tm_nodes_max nodes allocated in tmpfs_alloc_node().
  
  PR:		kern/138367
  Suggested by:	bde [1], Gleb Kurtsou [2]
  Approved by:	trasz (mentor)

Modified:
  head/sys/fs/tmpfs/tmpfs_subr.c
  head/sys/fs/tmpfs/tmpfs_vfsops.c

Modified: head/sys/fs/tmpfs/tmpfs_subr.c
==============================================================================
--- head/sys/fs/tmpfs/tmpfs_subr.c	Wed Jan 20 16:50:13 2010	(r202707)
+++ head/sys/fs/tmpfs/tmpfs_subr.c	Wed Jan 20 16:56:20 2010	(r202708)
@@ -93,7 +93,7 @@ tmpfs_alloc_node(struct tmpfs_mount *tmp
 	MPASS(IFF(type == VLNK, target != NULL));
 	MPASS(IFF(type == VBLK || type == VCHR, rdev != VNOVAL));
 
-	if (tmp->tm_nodes_inuse > tmp->tm_nodes_max)
+	if (tmp->tm_nodes_inuse >= tmp->tm_nodes_max)
 		return (ENOSPC);
 
 	nnode = (struct tmpfs_node *)uma_zalloc_arg(

Modified: head/sys/fs/tmpfs/tmpfs_vfsops.c
==============================================================================
--- head/sys/fs/tmpfs/tmpfs_vfsops.c	Wed Jan 20 16:50:13 2010	(r202707)
+++ head/sys/fs/tmpfs/tmpfs_vfsops.c	Wed Jan 20 16:56:20 2010	(r202708)
@@ -182,10 +182,10 @@ tmpfs_mount(struct mount *mp)
 	struct tmpfs_mount *tmp;
 	struct tmpfs_node *root;
 	size_t pages, mem_size;
-	ino_t nodes;
+	uint32_t nodes;
 	int error;
 	/* Size counters. */
-	ino_t nodes_max;
+	u_int nodes_max;
 	u_quad_t size_max;
 
 	/* Root node attributes. */
@@ -223,7 +223,7 @@ tmpfs_mount(struct mount *mp)
 	if (mp->mnt_cred->cr_ruid != 0 ||
 	    vfs_scanopt(mp->mnt_optnew, "mode", "%ho", &root_mode) != 1)
 		root_mode = va.va_mode;
-	if (vfs_scanopt(mp->mnt_optnew, "inodes", "%d", &nodes_max) != 1)
+	if (vfs_scanopt(mp->mnt_optnew, "inodes", "%u", &nodes_max) != 1)
 		nodes_max = 0;
 	if (vfs_scanopt(mp->mnt_optnew, "size", "%qu", &size_max) != 1)
 		size_max = 0;
@@ -245,9 +245,12 @@ tmpfs_mount(struct mount *mp)
 		pages = howmany(size_max, PAGE_SIZE);
 	MPASS(pages > 0);
 
-	if (nodes_max <= 3)
-		nodes = 3 + pages * PAGE_SIZE / 1024;
-	else
+	if (nodes_max <= 3) {
+		if (pages > UINT32_MAX - 3)
+			nodes = UINT32_MAX;
+		else
+			nodes = pages + 3;
+	} else
 		nodes = nodes_max;
 	MPASS(nodes >= 3);
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 7 Jaakko Heinonen freebsd_committer freebsd_triage 2010-01-20 18:09:06 UTC
State Changed
From-To: feedback->patched

The panic should should be fixed by r201773. I will propose a different 
change for maximum file size.
Comment 8 dfilter service freebsd_committer freebsd_triage 2011-03-08 17:27:46 UTC
Author: jh
Date: Tue Mar  8 17:27:36 2011
New Revision: 219401
URL: http://svn.freebsd.org/changeset/base/219401

Log:
  MFC r201773:
  
  - Change the type of size_max to u_quad_t because its value is converted
    with vfs_scanopt(9) using the "%qu" format string.
  - Limit the maximum value of size_max to (SIZE_MAX - PAGE_SIZE) to
    prevent overflow in howmany() macro.
  
  PR:		kern/141194
  
  MFC r202187:
  
  - Fix some style bugs in tmpfs_mount().
  - Remove a stale comment about tmpfs_mem_info() 'total' argument.
  
  MFC r202708:
  
  - Change the type of nodes_max to u_int and use "%u" format string to
    convert its value.
  - Set default tm_nodes_max to min(pages + 3, UINT32_MAX). It's more
    reasonable than the old four nodes per page (with page size 4096) because
    non-empty regular files always use at least one page. This fixes possible
    overflow in the calculation.
  - Don't allow more than tm_nodes_max nodes allocated in tmpfs_alloc_node().
  
  PR:		kern/138367

Modified:
  stable/8/sys/fs/tmpfs/tmpfs.h
  stable/8/sys/fs/tmpfs/tmpfs_subr.c
  stable/8/sys/fs/tmpfs/tmpfs_vfsops.c
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)

Modified: stable/8/sys/fs/tmpfs/tmpfs.h
==============================================================================
--- stable/8/sys/fs/tmpfs/tmpfs.h	Tue Mar  8 17:00:31 2011	(r219400)
+++ stable/8/sys/fs/tmpfs/tmpfs.h	Tue Mar  8 17:27:36 2011	(r219401)
@@ -476,10 +476,6 @@ int	tmpfs_truncate(struct vnode *, off_t
  * Returns information about the number of available memory pages,
  * including physical and virtual ones.
  *
- * If 'total' is TRUE, the value returned is the total amount of memory
- * pages configured for the system (either in use or free).
- * If it is FALSE, the value returned is the amount of free memory pages.
- *
  * Remember to remove TMPFS_PAGES_RESERVED from the returned value to avoid
  * excessive memory usage.
  *

Modified: stable/8/sys/fs/tmpfs/tmpfs_subr.c
==============================================================================
--- stable/8/sys/fs/tmpfs/tmpfs_subr.c	Tue Mar  8 17:00:31 2011	(r219400)
+++ stable/8/sys/fs/tmpfs/tmpfs_subr.c	Tue Mar  8 17:27:36 2011	(r219401)
@@ -93,7 +93,7 @@ tmpfs_alloc_node(struct tmpfs_mount *tmp
 	MPASS(IFF(type == VLNK, target != NULL));
 	MPASS(IFF(type == VBLK || type == VCHR, rdev != VNOVAL));
 
-	if (tmp->tm_nodes_inuse > tmp->tm_nodes_max)
+	if (tmp->tm_nodes_inuse >= tmp->tm_nodes_max)
 		return (ENOSPC);
 
 	nnode = (struct tmpfs_node *)uma_zalloc_arg(

Modified: stable/8/sys/fs/tmpfs/tmpfs_vfsops.c
==============================================================================
--- stable/8/sys/fs/tmpfs/tmpfs_vfsops.c	Tue Mar  8 17:00:31 2011	(r219400)
+++ stable/8/sys/fs/tmpfs/tmpfs_vfsops.c	Tue Mar  8 17:27:36 2011	(r219401)
@@ -182,18 +182,18 @@ tmpfs_mount(struct mount *mp)
 	struct tmpfs_mount *tmp;
 	struct tmpfs_node *root;
 	size_t pages, mem_size;
-	ino_t nodes;
+	uint32_t nodes;
 	int error;
 	/* Size counters. */
-	ino_t	nodes_max;
-	size_t	size_max;
+	u_int nodes_max;
+	u_quad_t size_max;
 
 	/* Root node attributes. */
-	uid_t	root_uid;
-	gid_t	root_gid;
-	mode_t	root_mode;
+	uid_t root_uid;
+	gid_t root_gid;
+	mode_t root_mode;
 
-	struct vattr	va;
+	struct vattr va;
 
 	if (vfs_filteropt(mp->mnt_optnew, tmpfs_opts))
 		return (EINVAL);
@@ -223,7 +223,7 @@ tmpfs_mount(struct mount *mp)
 	if (mp->mnt_cred->cr_ruid != 0 ||
 	    vfs_scanopt(mp->mnt_optnew, "mode", "%ho", &root_mode) != 1)
 		root_mode = va.va_mode;
-	if (vfs_scanopt(mp->mnt_optnew, "inodes", "%d", &nodes_max) != 1)
+	if (vfs_scanopt(mp->mnt_optnew, "inodes", "%u", &nodes_max) != 1)
 		nodes_max = 0;
 	if (vfs_scanopt(mp->mnt_optnew, "size", "%qu", &size_max) != 1)
 		size_max = 0;
@@ -239,15 +239,18 @@ tmpfs_mount(struct mount *mp)
 	 * allowed to use, based on the maximum size the user passed in
 	 * the mount structure.  A value of zero is treated as if the
 	 * maximum available space was requested. */
-	if (size_max < PAGE_SIZE || size_max >= SIZE_MAX)
+	if (size_max < PAGE_SIZE || size_max > SIZE_MAX - PAGE_SIZE)
 		pages = SIZE_MAX;
 	else
 		pages = howmany(size_max, PAGE_SIZE);
 	MPASS(pages > 0);
 
-	if (nodes_max <= 3)
-		nodes = 3 + pages * PAGE_SIZE / 1024;
-	else
+	if (nodes_max <= 3) {
+		if (pages > UINT32_MAX - 3)
+			nodes = UINT32_MAX;
+		else
+			nodes = pages + 3;
+	} else
 		nodes = nodes_max;
 	MPASS(nodes >= 3);
 
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Comment 9 Jaakko Heinonen freebsd_committer freebsd_triage 2012-02-07 18:09:39 UTC
State Changed
From-To: patched->closed

Fixed in head, stable/9 and stable/8.