NetBSD-Bugs archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

port-atari/56859: "iteconfig -h 480" triggers vm_fault panic on ATARITT kernel



>Number:         56859
>Category:       port-atari
>Synopsis:       "iteconfig -h 480" triggers vm_fault panic on ATARITT kerne
>Confidential:   no
>Severity:       critical
>Priority:       medium
>Responsible:    port-atari-maintainer
>State:          open
>Class:          sw-bug
>Submitter-Id:   net
>Arrival-Date:   Sun May 29 12:15:01 +0000 2022
>Originator:     Izumi Tsutsui
>Release:        NetBSD 9.2
>Organization:
>Environment:
System: NetBSD ataritt 9.2 NetBSD 9.2 (ATARITT) #0: Wed May 12 13:15:55 UTC 2021  mkrepro%mkrepro.NetBSD.org@localhost:/usr/src/sys/arch/atari/compile/ATARITT atari
Architecture: m68k
Machine: atari
>Description:
"iteconfig -h 480" command immediately triggers vm_fault kernel panic
on TT030 and NetBSD/atari 9.2 ATARITT kernel.

The backtrace on crash shows:
---
[ 30443.6719614] vm_fault(0x26d840, 0, 1) -> e
[ 30443.6719614]   type 8, code [mmu,,ssw]: 4020755
[ 30443.6719614] trap type 8, code = 4020755, v = 14
[ 30443.6719614] kernel program counter = 0x19f76
[ 30443.6719614] kernel: MMU fault trap
[ 30443.6719614] pid = 4009, lid = 1, pc = 00019F76, ps = 2700, sfc = 1, dfc = 1

[ 30443.6719614] Registers:
[ 30443.6719614]              0        1        2        3        4        5        6        7
[ 30443.6719614] dreg: 003E2000 00000001 00000000 0025D0AC 00000001 00000014 00000014 FFEFF8D4
[ 30443.6719614] areg: 003E5FD0 00000000 003DBF70 0025DB68 003E5FB8 005A1220 05FBBC54 FFEFF854

[ 30443.6719614] Kernel stack (05FBBAA8):
[ 30443.6719614] FBBAA8: 0001967C 05FBBBA4 00000080 00000008 00000000 00147AB8 005A1220 05FBBB8C
[ 30443.6719614] FBBAC8: 00019C56 00000008 04020755 00000014 05FBBBA4 00000000 0025D0AC 00000001
[ 30443.6719614] FBBAE8: 00000014 00000014 FFEFF8D4 003DBF70 0025DB68 003E5FB8 005A1220 005AB538
[ 30443.6719614] FBBB08: 00000001 05FBBE58 00000001 00000000 00000000 00000000 00000000 00000001
[ 30443.6719614] FBBB28: 00000000 00000000 00000000 00000008 00000000 00000000 00000000 00000000
[ 30443.6719614] FBBB48: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 30443.6719614] FBBB68: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
[ 30443.6719614] FBBB88: 05FBBBE4 05FBBC54 00002042 05FBBBA4 00000008 04020755 00000014 003E2000
[ 30443.6719614] FBBBA8: 00000001 00000000 0025D0AC 00000001 00000014 00000014 FFEFF8D4 003E5FD0
[ 30443.6719614] FBBBC8: 00000000 003DBF70 0025DB68 003E5FB8 005A1220 05FBBC54 FFEFF854 00000000
[ 30443.6719614] FBBBE8: 27000001 9F76B008 1EEE0755 667C2169 00000014 00000014 00002000 4A290014
[ 30443.6719614] FBBC08: 00019F7E 00019F7C 00019F7A 003DBF00 0014FF0C 000FF6EC 270049E8 0024BB1C
[ 30443.6719614] FBBC28: 00002700 00002700 80200000 00000014 00000000 003BA000 00019F64 0025D0AC
[ 30443.6719614] FBBC48: 0025DB68 0025DB68 005A1220 05FBBC64 0000D2A6 003E5FD0 0025DB7C 05FBBC98
[ 30443.6719614] FBBC68: 00010A42 0025D0AC 80145A73 00000C00 05FBBDA0 0025D170 004EE7C0 00000000
[ 30443.6719614] FBBC88: 005A1220 000F9002 00000280 000001E0 05FBBCE8 0000C802 00000000 00000000
[ 30443.6719614] panic: MMU fault
[ 30443.6719614] cpu0: Begin traceback...
[ 30443.6719614] ?(?)
[ 30443.6719614] db_panic(8,2710,5fb8000,5fbbba4,5fbbaa8) at 0
[ 30443.6719614] vpanic(1e16c6,5fbbab4,5fbbac4,1969a,1e16c6) + 162
[ 30443.6719614] panic(1e16c6,8,0,147ab8,5a1220) + c
[ 30443.6719614] panictrap(?)
[ 30443.6719614] mmc_gettrackinfo(8,4020755,14,5fbbba4,0) + b8
[ 30443.6719614] trap(5fbbba4,8,4020755,14) + 51e
[ 30443.6719614] free_stmem(3e5fd0) + 2a
[ 30443.6719614] tt_free_view(?)
[ 30443.6719614] grf_free_view(25d0ac) + 3e
[ 30443.6719614] viewioctl(0,0,80145602,5fbbcd4,0) + 18a
[ 30443.6719614] ite_newsize(?)
[ 30443.6719614] _ufetch_8(4ee7c0,5fbbe80) + 52
[ 30443.6719614] itecc_ioctl(?)
[ 30443.6719614] cdev_ioctl(4ee7c0,80145a73,5fbbe80,5,62c340,62c340) + 48
[ 30443.6719614] spec_ioctl(5fbbd50,202fac,832d14,80145a73,5fbbe80) + a0
[ 30443.6719614] VOP_IOCTL(832d14,80145a73,5fbbe80,5,4f6c4c) + 38
[ 30443.6719614] vn_ioctl(5d85e0,80145a73,5fbbe80) + 158
[ 30443.6719614] sys_ioctl(62c340,5fbbf38,5fbbf30,d,0) + 240
[ 30443.6719614] syscall_plain(36,62c340,5fbbfb4,ffeff948,5) + d2
[ 30443.6719614] syscall(36) + 70
[ 30443.6719614] trap0() + e
[ 30443.6719614] cpu0: End traceback...

[ 30443.6719614] dumping to dev 4,1 offset 1957882
[ 30443.6719614] Do you want to dump memory? [y]
---

>> [ 30443.6719614] trap type 8, code = 4020755, v = 14

"v = 14" implies NULL pointer dereference, and

>> [ 30443.6719614] pid = 4009, lid = 1, pc = 00019F76, ps = 2700, sfc = 1, dfc = 1

"pc = 00019F76" is the following instruction in free_stmem():
---
00019f4c <free_stmem>:
   19f4c:       4e56 0000       linkw %fp,#0
   19f50:       48e7 003c       moveml %a2-%a5,%sp@-
   19f54:       206e 0008       moveal %fp@(8),%a0
   19f58:       4a88            tstl %a0
   19f5a:       6700 0210       beqw 1a16c <free_stmem+0x220>
   19f5e:       40c0            movew %sr,%d0
   19f60:       46fc 2700       movew #9984,%sr
   19f64:       49e8 ffe8       lea %a0@(-24),%a4
   19f68:       2268 ffe8       moveal %a0@(-24),%a1
   19f6c:       2468 ffec       moveal %a0@(-20),%a2
   19f70:       246a 0004       moveal %a2@(4),%a2
   19f74:       2452            moveal %a2@,%a2
   19f76:       4a29 0014       tstb %a1@(20)
                                ^^^^^^^^^^^^^ *this one*
   19f7a:       667c            bnes 19ff8 <free_stmem+0xac>
---

This means the following "next" in free_stmem() is NULL:
(note %a0 points *mem here)
 https://nxr.netbsd.org/xref/src/sys/arch/atari/atari/stalloc.c?r=1.16#166
---
void
free_stmem(void *mem)
{
	struct mem_node *mn, *next, *prev;
	int s;

	if (mem == NULL)
		return;

	s = splhigh();
	mn = (struct mem_node *)mem - 1;
	next = TAILQ_NEXT(mn, link);
	prev = TAILQ_PREV(mn, stlist, link);

	/*
	 * check ahead of us.
	 */
	if (next->type == MNODE_FREE) {
            ^^^^ *this one*
---

>How-To-Repeat:
See above.

>Fix:
stalloc.c rev 1.16 removed "next != NULL" (and "prev != NULL") checks,
but they should still be checked before dereference?

 https://nxr.netbsd.org/diff/src/sys/arch/atari/atari/stalloc.c?r2=%2Fsrc%2Fsys%2Farch%2Fatari%2Fatari%2Fstalloc.c%401.16&r1=%2Fsrc%2Fsys%2Farch%2Fatari%2Fatari%2Fstalloc.c%401.15

--- stalloc.c	27 Nov 2013 17:24:43 -0000	1.15
+++ stalloc.c	3 Jan 2014 07:14:20 -0000	1.16
@@ -117,7 +117,7 @@ alloc_stmem(u_long size, void **phys_add
 		 * for a new node in between.
 		 */
 		TAILQ_REMOVE(&free_list, mn, free_link);
-		TAILQ_NEXT(mn, free_link) = NULL;
+		mn->type = MNODE_USED;
 		size = mn->size;	 /* increase size. (or same) */
 		stmem_total -= mn->size;
 		splx(s);
@@ -138,7 +138,7 @@ alloc_stmem(u_long size, void **phys_add
 	 * and mark as not on free list
 	 */
 	TAILQ_INSERT_AFTER(&st_list, new, mn, link);
-	TAILQ_NEXT(mn, free_link) = NULL;
+	mn->type = MNODE_USED;
 
 	stmem_total -= size + sizeof(struct mem_node);
 	splx(s);
@@ -150,7 +150,7 @@ void
 free_stmem(void *mem)
 {
 	struct mem_node *mn, *next, *prev;
-	int		s;
+	int s;
 
 	if (mem == NULL)
 		return;
@@ -163,48 +163,52 @@ free_stmem(void *mem)
 	/*
 	 * check ahead of us.
 	 */
-	if (next != NULL && TAILQ_NEXT(next, free_link) != NULL) {
+	if (next->type == MNODE_FREE) {
 		/*
 		 * if next is: a valid node and a free node. ==> merge
 		 */
 		TAILQ_INSERT_BEFORE(next, mn, free_link);
+		mn->type = MNODE_FREE;
 		TAILQ_REMOVE(&st_list, next, link);
-		TAILQ_REMOVE(&st_list, next, free_link);
+		TAILQ_REMOVE(&free_list, next, free_link);
 		stmem_total += mn->size + sizeof(struct mem_node);
 		mn->size += next->size + sizeof(struct mem_node);
 	}
-	if (prev != NULL && TAILQ_PREV(prev, freelist, free_link) != NULL) {
+	if (prev->type == MNODE_FREE) {
 		/*
 		 * if prev is: a valid node and a free node. ==> merge
 		 */
-		if (TAILQ_NEXT(mn, free_link) == NULL)
+		if (mn->type != MNODE_FREE)
 			stmem_total += mn->size + sizeof(struct mem_node);
 		else {
 			/* already on free list */
 			TAILQ_REMOVE(&free_list, mn, free_link);
+			mn->type = MNODE_USED;
 			stmem_total += sizeof(struct mem_node);
 		}
 		TAILQ_REMOVE(&st_list, mn, link);
 		prev->size += mn->size + sizeof(struct mem_node);
-	} else if (TAILQ_NEXT(mn, free_link) == NULL) {
+	} else if (mn->type != MNODE_FREE) {
 		/*
 		 * we still are not on free list and we need to be.
 		 * <-- | -->
 		 */
 		while (next != NULL && prev != NULL) {
-			if (TAILQ_NEXT(next, free_link) != NULL) {
+			if (next->type == MNODE_FREE) {
 				TAILQ_INSERT_BEFORE(next, mn, free_link);
+				mn->type = MNODE_FREE;
 				break;
 			}
-			if (TAILQ_NEXT(prev, free_link) != NULL) {
+			if (prev->type == MNODE_FREE) {
 				TAILQ_INSERT_AFTER(&free_list, prev, mn,
 				    free_link);
+				mn->type = MNODE_FREE;
 				break;
 			}
 			prev = TAILQ_PREV(prev, stlist, link);
 			next = TAILQ_NEXT(next, link);
 		}
-		if (TAILQ_NEXT(mn, free_link) == NULL) {
+		if (mn->type != MNODE_FREE) {
 			if (next == NULL) {
 				/*
 				 * we are not on list so we can add
@@ -214,6 +218,7 @@ free_stmem(void *mem)
 			} else {
 				TAILQ_INSERT_HEAD(&free_list,mn,free_link);
 			}
+				mn->type = MNODE_FREE;
 		}
 		stmem_total += mn->size;/* add our helpings to the pool. */
 	}


---
Izumi Tsutsui



Home | Main Index | Thread Index | Old Index