kern/143073: [patch][panic] unp_gc panic (race with uipc_detach)

Gleb Kurtsou gleb.kurtsou at gmail.com
Thu Jan 21 23:20:05 UTC 2010


>Number:         143073
>Category:       kern
>Synopsis:       [patch][panic] unp_gc panic (race with uipc_detach)
>Confidential:   no
>Severity:       non-critical
>Priority:       low
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Thu Jan 21 23:20:04 UTC 2010
>Closed-Date:
>Last-Modified:
>Originator:     Gleb Kurtsou
>Release:        
>Organization:
>Environment:
FreeBSD tops 9.0-CURRENT FreeBSD 9.0-CURRENT #0 r201894+9b671bd-dirty: Sat Jan  9 16:54:05 EET 2010     root at tops:/usr/obj/freebsd-src/local/sys/TOPS  amd64
>Description:
It looks like unp_pc/uipc_detach race: unp is marked as dead, the it is removed from the list during locking/unlocking unp list lock to malloc temporary unref buffer.
Unread portion of the kernel message buffer:


Fatal trap 9: general protection fault while in kernel mode
cpuid = 0; apic id = 00
instruction pointer	= 0x20:0xffffffff803a875b
stack pointer	        = 0x28:0xffffff800006fb60
frame pointer	        = 0x28:0xffffff800006fbc0
code segment		= base 0x0, limit 0xfffff, type 0x1b
			= DPL 0, pres 1, long 1, def32 0, gran 1
processor eflags	= interrupt enabled, resume, IOPL = 0
current process		= 0 (thread taskq)
trap number		= 9
panic: general protection fault
cpuid = 0
KDB: stack backtrace:
db_trace_self_wrapper() at db_trace_self_wrapper+0x2a
panic() at panic+0x17d
trap_fatal() at trap_fatal+0x2ad
trap() at trap+0xfa
calltrap() at calltrap+0x8
--- trap 0x9, rip = 0xffffffff803a875b, rsp = 0xffffff800006fb60, rbp = 0xffffff800006fbc0 ---
unp_gc() at unp_gc+0x30b
taskqueue_run() at taskqueue_run+0x90
taskqueue_thread_loop() at taskqueue_thread_loop+0x3f
fork_exit() at fork_exit+0x12a
fork_trampoline() at fork_trampoline+0xe
--- trap 0, rip = 0, rsp = 0xffffff800006fd30, rbp = 0 ---
Uptime: 8h39m56s
Physical memory: 3046 MB
Dumping 1890 MB: 1875 1859 1843 (CTRL-C to abort)  1827 1811 1795 1779 1763 1747 1731 1715 1699 1683 1667 1651 1635 1619 1603 1587 1571 1555 1539 1523 1507 1491 1475 1459 1443 1427 1411 1395 1379 1363 1347 1331 1315 1299 1283 1267 1251 1235 1219 1203 1187 1171 1155 1139 1123 1107 1091 1075 1059 1043 1027 1011 995 979 963 947 931 915 899 883 867 851 835 819 803 787 771 755 739 723 707 691 675 659 643 627 611 595 579 563 547 531 515 499 483 467 451 435 419 403 387 371 355 339 323 307 291 275 259 243 227 211 195 179 163 147 131 115 99 83 67 51 35 19 3

Reading symbols from /boot/kernel/zfs.ko...Reading symbols from /.bootfs/boot/kernel/zfs.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/zfs.ko
Reading symbols from /boot/kernel/opensolaris.ko...Reading symbols from /.bootfs/boot/kernel/opensolaris.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/opensolaris.ko
Reading symbols from /boot/modules/nvidia.ko...done.
Loaded symbols for /boot/modules/nvidia.ko
Reading symbols from /boot/kernel/linprocfs.ko...Reading symbols from /.bootfs/boot/kernel/linprocfs.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/linprocfs.ko
Reading symbols from /boot/kernel/tmpfs.ko...Reading symbols from /.bootfs/boot/kernel/tmpfs.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/tmpfs.ko
Reading symbols from /boot/kernel/pf.ko...Reading symbols from /.bootfs/boot/kernel/pf.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/pf.ko
Reading symbols from /boot/kernel/pefs.ko...Reading symbols from /.bootfs/boot/kernel/pefs.ko.symbols...done.
done.
Loaded symbols for /boot/kernel/pefs.ko
#0  doadump () at pcpu.h:223
223	pcpu.h: No such file or directory.
	in pcpu.h
(kgdb) bt
#0  doadump () at pcpu.h:223
#1  0xffffffff8033b11b in boot (howto=260) at /freebsd-src/local/sys/kern/kern_shutdown.c:416
#2  0xffffffff8033b599 in panic (fmt=Variable "fmt" is not available.
) at /freebsd-src/local/sys/kern/kern_shutdown.c:579
#3  0xffffffff80552273 in trap_fatal (frame=0x9, eva=Variable "eva" is not available.
) at /freebsd-src/local/sys/amd64/amd64/trap.c:858
#4  0xffffffff80552bcc in trap (frame=0xffffff800006fab0) at /freebsd-src/local/sys/amd64/amd64/trap.c:647
#5  0xffffffff80539c23 in calltrap () at /freebsd-src/local/sys/amd64/amd64/exception.S:224
#6  0xffffffff803a875b in unp_gc (arg=Variable "arg" is not available.
) at /freebsd-src/local/sys/kern/uipc_usrreq.c:2145
#7  0xffffffff80378d25 in taskqueue_run (queue=0xffffff000291d600) at /freebsd-src/local/sys/kern/subr_taskqueue.c:239
#8  0xffffffff80378e96 in taskqueue_thread_loop (arg=Variable "arg" is not available.
) at /freebsd-src/local/sys/kern/subr_taskqueue.c:360
#9  0xffffffff8031561a in fork_exit (callout=0xffffffff80378e57 <taskqueue_thread_loop>, arg=0xffffffff8085a9b0, 
    frame=0xffffff800006fc80) at /freebsd-src/local/sys/kern/kern_fork.c:843
#10 0xffffffff8053a07e in fork_trampoline () at /freebsd-src/local/sys/amd64/amd64/exception.S:561
#11 0x0000000000000000 in ?? ()
#12 0x0000000000000000 in ?? ()
#13 0x0000000000000000 in ?? ()
#14 0x0000000000000000 in ?? ()
#15 0x0000000000000000 in ?? ()
#16 0x0000000000000000 in ?? ()
#17 0x0000000000000000 in ?? ()
#18 0x0000000000000000 in ?? ()
#19 0x0000000000000000 in ?? ()
#20 0x0000000000000000 in ?? ()
#21 0x0000000000000000 in ?? ()
#22 0x0000000000000000 in ?? ()
#23 0x0000000000000000 in ?? ()
#24 0x0000000000000000 in ?? ()
#25 0x0000000000000000 in ?? ()
#26 0x0000000000000000 in ?? ()
#27 0x0000000000000000 in ?? ()
---Type <return> to continue, or q <return> to quit---q
Quit
(kgdb) fr 6
#6  0xffffffff803a875b in unp_gc (arg=Variable "arg" is not available.
) at /freebsd-src/local/sys/kern/uipc_usrreq.c:2145
warning: Source file is more recent than executable.

2145			sorflush(unref[i]->f_data);
(kgdb) l
2140		 * Now flush all sockets, free'ing rights.  This will free the
2141		 * struct files associated with these sockets but leave each socket
2142		 * with one remaining ref.
2143		 */
2144		for (i = 0; i < unp_unreachable; i++)
2145			sorflush(unref[i]->f_data);
2146	
2147		/*
2148		 * And finally release the sockets so they can be reclaimed.
2149		 */
(kgdb) p unref
Variable "unref" is not available.
(kgdb) disassemble 
Dump of assembler code for function unp_gc:
[...]
0xffffffff803a869a <unp_gc+586>:	callq  0xffffffff8032a6d6 <malloc>
0xffffffff803a869f <unp_gc+591>:	mov    %rax,%r13
^^^ unref == r13
[...]
0xffffffff803a8752 <unp_gc+770>:	mov    %r13,%rbx
0xffffffff803a8755 <unp_gc+773>:	xor    %r12d,%r12d
0xffffffff803a8758 <unp_gc+776>:	mov    (%rbx),%rcx
^^^ panic here
0xffffffff803a875b <unp_gc+779>:	mov    (%rcx),%rdi
0xffffffff803a875e <unp_gc+782>:	callq  0xffffffff8039e220 <sorflush>
[...]
Quit
(kgdb) info all-registers 
rax            0x1	1
rbx            0xffffff003d55f170	-1098482585232
rcx            0xdeadc0dedeadc0de	-2401050962867404578
rdx            0x0	0
rsi            0x0	0
rdi            0x4	4
rbp            0xffffff800006fbc0	0xffffff800006fbc0
rsp            0xffffff800006fb70	0xffffff800006fb70
r8             0xffffff0002871390	-1099469220976
r9             0xffffff0002871390	-1099469220976
r10            0x0	0
r11            0x0	0
r12            0x0	0
r13            0xffffff003d55f170	-1098482585232
r14            0xffffff800006fb88	-549755356280
r15            0xffffff800006fb70	-549755356304
rip            0xffffffff803a875b	0xffffffff803a875b <unp_gc+779>
eflags         0x10246	66118
cs             0x20	32
ss             0x28	40
ds             0x0	0
es             0x0	0
fs             0x0	0
gs             0x0	0
st0            0	(raw 0x00000000000000000000)
st1            0	(raw 0x00000000000000000000)
st2            0	(raw 0x00000000000000000000)
st3            0	(raw 0x00000000000000000000)
st4            0	(raw 0x00000000000000000000)
(kgdb) p unp_unreachable
$1 = 1
(kgdb) p *(struct file **)0xffffff003d55f170
$2 = (struct file *) 0xdeadc0dedeadc0de



>How-To-Repeat:

>Fix:


Patch attached with submission follows:

diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index fdf3d90..790720f 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -2134,6 +2134,7 @@ unp_gc(__unused void *arg, int pending)
 				KASSERT(i <= unp_unreachable,
 				    ("unp_gc: incorrect unreachable count."));
 			}
+	unp_unreachable = i;
 	UNP_LIST_UNLOCK();
 
 	/*


>Release-Note:
>Audit-Trail:
>Unformatted:


More information about the freebsd-bugs mailing list