Date: Tue, 1 May 2018 18:26:35 +0200 From: Stefano Duo <duostefano93@gmail.com> To: freebsd-net@freebsd.org Cc: Vincenzo Maffione <v.maffione@gmail.com> Subject: Page fault inside ifunit_ref() FreeBSD12.0-CURRENT Message-ID: <CALkzoBv8rPXVwerJfGHt_69k2D9OUnYON6d3%2BTgrd6vAiGTWWw@mail.gmail.com>
next in thread | raw e-mail | index | archive | help
Hi, I am a GSoC student working on netmap. I am trying to get a kernel module to call nm_vi_create(), which creates a persistent VALE port. Internally, nm_vi_create() calls ifunit_ref() to check if an interface with the specified name already exists. The system panics inside ifunit_ref() due to a page fault while accessing V_ifnet. This happens using FreeBSD12.0-CURRENT. To better understand what is going on, I have written a dummy module, that only calls ifunit_ref(), here you can find the source code https://github.com/StefanoDuo/ifunit_ref_test. This is what I have found. FreeBSD11.1-STABLE: The module works correctly, either if loaded through kldload or compiled with the kernel. FreeBSD12.0-CURRENT: Calling ifunit_ref() inside the module loader function does not cause a page fault, while calling it inside a write() or ioctl() causes a page fault. This happens either if the module is loaded through kldload or compiled with the kernel. Following Vincenzo's advice (he's one of my mentors), i tried enclosing the call to ifunit_ref() between CURVNET_SET() and CURVNET_RESTORE(). This solves the problem on FreeBSD12.0-CURRENT, but only if the module is compiled with the kernel, if loaded through kldload, i still get a page fault. The problem seems related to the virtualization of the network stack, and therefore the of the V_ifnet variable. It seems that inside the module loader function i have a struct vnet selected, instead inside a write() or ioctl() call i do not. This though, doesn't explain (at least to me) why adding CURVNET_SET() and CURVNET_RESTORE(), doesn't solve the problem for modules loaded through kldload. I don't know if i'm doing something wrong (or not doing something needed), or if it's a bug introduced in FreeBSD12.0-CURRENT. Does anyone have a better idea of what's happening? Here is the panic message i get after writing to the device (causing a call to ifunit_ref). [root@freebsd ~/repos/ifunit_ref_test/sys/modules/foo_module]# echo "test" >/dev/FOO_DEV Kernel page fault with the following non-sleepable locks held: shared rw ifnet_rw (ifnet_rw) r = 0 (0xffffffff820474e8) locked @ /usr/src/sys/net/if.c:2379 stack backtrace: #0 0xffffffff80ba5cd3 at witness_debugger+0x73 #1 0xffffffff80ba70b1 at witness_warn+0x461 #2 0xffffffff80ffe2d3 at trap_pfault+0x53 #3 0xffffffff80ffdad2 at trap+0x2f2 #4 0xffffffff80fd9d9c at calltrap+0x8 #5 0xffffffff8261d10e at foo_write+0x1e #6 0xffffffff80a0a8c0 at devfs_write_f+0xf0 #7 0xffffffff80baad77 at dofilewrite+0xa7 #8 0xffffffff80baa968 at kern_writev+0x68 #9 0xffffffff80baa8f6 at sys_write+0x86 #10 0xffffffff80fff0cb at amd64_syscall+0x79b #11 0xffffffff80fda5ed at fast_syscall_common+0x101 Fatal trap 12: page fault while in kernel mode cpuid = 0; apic id = 00 fault virtual address = 0x28 fault code = supervisor read data, page not present instruction pointer = 0x20:0xffffffff80c3e2f2 stack pointer = 0x28:0xfffffe00005c0950 frame pointer = 0x28:0xfffffe00005c0960 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 = 700 (bash) [ thread pid 700 tid 100087 ] Stopped at ifunit_ref+0x32: movq ll+0x7(%rax),%rax And here you can find the backtrace taken from the dump. (kgdb) l *0xffffffff80c3e2f2 0xffffffff80c3e2f2 is in ifunit_ref (/usr/src/sys/net/if.c:2380). 2375 ifunit_ref(const char *name) 2376 { 2377 struct ifnet *ifp; 2378 2379 IFNET_RLOCK_NOSLEEP(); 2380 TAILQ_FOREACH(ifp, &V_ifnet, if_link) { 2381 if (strncmp(name, ifp->if_xname, IFNAMSIZ) == 0 && 2382 !(ifp->if_flags & IFF_DYING)) 2383 break; 2384 } (kgdb) bt #0 __curthread () at ./machine/pcpu.h:230 #1 doadump (textdump=0) at /usr/src/sys/kern/kern_shutdown.c:361 #2 0xffffffff8040ac9b in db_dump (dummy=<optimized out>, dummy2=<unavailable>, dummy3=<unavailable>, dummy4=<unavailable>) at /usr/src/sys/ddb/db_command.c:574 #3 0xffffffff8040aa69 in db_command (last_cmdp=<optimized out>, cmd_table=<optimized out>, dopager=<optimized out>) at /usr/src/sys/ddb/db_command.c:481 #4 0xffffffff8040a7e4 in db_command_loop () at /usr/src/sys/ddb/db_command.c:534 #5 0xffffffff8040da0f in db_trap (type=<optimized out>, code=<optimized out>) at /usr/src/sys/ddb/db_main.c:250 #6 0xffffffff80b85603 in kdb_trap (type=12, code=0, tf=<optimized out>) at /usr/src/sys/kern/subr_kdb.c:697 #7 0xffffffff80ffe1d0 in trap_fatal (frame=0xfffffe00005c0890, eva=40) at /usr/src/sys/amd64/amd64/trap.c:815 #8 0xffffffff80ffe2e2 in trap_pfault (frame=0xfffffe00005c0890, usermode=<optimized out>) at /usr/src/sys/amd64/amd64/trap.c:664 #9 0xffffffff80ffdad2 in trap (frame=0xfffffe00005c0890) at /usr/src/sys/amd64/amd64/trap.c:413 #10 <signal handler called> #11 0xffffffff80c3e2f2 in ifunit_ref (name=0xffffffff8261d174 "FOO") at /usr/src/sys/net/if.c:2380 #12 0xffffffff8261d10e in foo_write (dev=<optimized out>, uio=<optimized out>, ioflag=<optimized out>) at /root/repos/ifunit_ref_test/sys/modules/foo_module/../../dev/foo_module/foo_module.c:50 #13 0xffffffff80a0a8c0 in devfs_write_f (fp=<optimized out>, uio=0xfffffe00005c0a80, cred=0xfffff80003fb0000, flags=0, td=<optimized out>) at /usr/src/sys/fs/devfs/devfs_vnops.c:1784 #14 0xffffffff80baad77 in fo_write (fp=<optimized out>, uio=<optimized out>, active_cred=0x1, flags=<optimized out>, td=<optimized out>) at /usr/src/sys/sys/file.h:309 #15 dofilewrite (td=0xfffff80003fb0000, fd=1, fp=0xfffff8000401c820, auio=0xfffffe00005c0a80, offset=<optimized out>, flags=0) at /usr/src/sys/kern/sys_generic.c:593 #16 0xffffffff80baa968 in kern_writev (td=0xfffff80003fb0000, fd=1, auio=0xfffffe00005c0a80) at /usr/src/sys/kern/sys_generic.c:507 #17 0xffffffff80baa8f6 in sys_write (td=0x0, uap=<optimized out>) at /usr/src/sys/kern/sys_generic.c:421 #18 0xffffffff80fff0cb in syscallenter (td=0xfffff80003fb0000) at /usr/src/sys/amd64/amd64/../../kern/subr_syscall.c:134 #19 amd64_syscall (td=0xfffff80003fb0000, traced=0) at /usr/src/sys/amd64/amd64/trap.c:936 #20 <signal handler called> #21 0x0000000800b7baca in ?? () Backtrace stopped: Cannot access memory at address 0x7fffffffe808 Thanks, Stefano.
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?CALkzoBv8rPXVwerJfGHt_69k2D9OUnYON6d3%2BTgrd6vAiGTWWw>