git: a7f20faa074d - main - netinet6: fix panic on kldunload pfsync

From: Kristof Provost <kp_at_FreeBSD.org>
Date: Wed, 01 Jun 2022 07:26:52 UTC
The branch main has been updated by kp:

URL: https://cgit.FreeBSD.org/src/commit/?id=a7f20faa074d5e9ac0e83f78485fb9cfd3bbf9fd

commit a7f20faa074d5e9ac0e83f78485fb9cfd3bbf9fd
Author:     Kristof Provost <kp@FreeBSD.org>
AuthorDate: 2022-05-31 19:11:14 +0000
Commit:     Kristof Provost <kp@FreeBSD.org>
CommitDate: 2022-06-01 07:26:15 +0000

    netinet6: fix panic on kldunload pfsync
    
    Commit d6cd20cc5 ("netinet6: fix ndp proxying") caused us to panic when
    unloading pfsync:
    
            Fatal trap 12: page fault while in kernel mode
            cpuid = 19; apic id = 38
            fault virtual address   = 0x20
            fault code              = supervisor read data, page not present
            instruction pointer     = 0x20:0xffffffff80dfe7f4
            stack pointer           = 0x28:0xfffffe015d4f8ac0
            frame pointer           = 0x28:0xfffffe015d4f8ae0
            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         = 5477 (kldunload)
            trap number             = 12
            panic: page fault
            cpuid = 19
            time = 1654023100
            KDB: stack backtrace:
            db_trace_self_wrapper() at db_trace_self_wrapper+0x2b/frame 0xfffffe015d4f8880
            vpanic() at vpanic+0x17f/frame 0xfffffe015d4f88d0
            panic() at panic+0x43/frame 0xfffffe015d4f8930
            trap_fatal() at trap_fatal+0x387/frame 0xfffffe015d4f8990
            trap_pfault() at trap_pfault+0xab/frame 0xfffffe015d4f89f0
            calltrap() at calltrap+0x8/frame 0xfffffe015d4f89f0
            --- trap 0xc, rip = 0xffffffff80dfe7f4, rsp = 0xfffffe015d4f8ac0, rbp = 0xfffffe015d4f8ae0 ---
            in6_purge_proxy_ndp() at in6_purge_proxy_ndp+0x14/frame 0xfffffe015d4f8ae0
            if_purgeaddrs() at if_purgeaddrs+0x24/frame 0xfffffe015d4f8b90
            if_detach_internal() at if_detach_internal+0x1c2/frame 0xfffffe015d4f8bf0
            if_detach() at if_detach+0x71/frame 0xfffffe015d4f8c20
            pfsync_clone_destroy() at pfsync_clone_destroy+0x1dd/frame 0xfffffe015d4f8c70
            if_clone_destroyif() at if_clone_destroyif+0x239/frame 0xfffffe015d4f8cc0
            if_clone_detach() at if_clone_detach+0xc8/frame 0xfffffe015d4f8cf0
            vnet_pfsync_uninit() at vnet_pfsync_uninit+0xda/frame 0xfffffe015d4f8d10
            vnet_deregister_sysuninit() at vnet_deregister_sysuninit+0x85/frame 0xfffffe015d4f8d40
            linker_file_sysuninit() at linker_file_sysuninit+0x147/frame 0xfffffe015d4f8d70
            linker_file_unload() at linker_file_unload+0x269/frame 0xfffffe015d4f8db0
            kern_kldunload() at kern_kldunload+0x18d/frame 0xfffffe015d4f8e00
            amd64_syscall() at amd64_syscall+0x12e/frame 0xfffffe015d4f8f30
            fast_syscall_common() at fast_syscall_common+0xf8/frame 0xfffffe015d4f8f30
            --- syscall (444, FreeBSD ELF64, sys_kldunloadf), rip = 0x1601eab28cba, rsp = 0x1601e9c363f8, rbp = 0x1601e9c36c50 ---
    
    This happens because ifp->if_afdata[AF_INET6] is NULL. Check for this,
    just as we already do in a few other places.
    See also c139b3c19b52a ("arp/nd: Cope with late calls to
    iflladdr_event").
    
    Reviewed by:    melifaro
    Sponsored by:   Rubicon Communications, LLC ("Netgate")
    Differential Revision:  https://reviews.freebsd.org/D35374
---
 sys/netinet6/in6.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/sys/netinet6/in6.c b/sys/netinet6/in6.c
index 857e05c0f112..02294b40379b 100644
--- a/sys/netinet6/in6.c
+++ b/sys/netinet6/in6.c
@@ -2700,6 +2700,9 @@ in6_purge_proxy_ndp(struct ifnet *ifp)
 	struct lltable *llt;
 	bool need_purge;
 
+	if (ifp->if_afdata[AF_INET6] == NULL)
+		return;
+
 	llt = LLTABLE6(ifp);
 	IF_AFDATA_WLOCK(ifp);
 	need_purge = ((llt->llt_flags & LLT_ADDEDPROXY) != 0);