Hello Hrvoje,

On 09/11/17(Thu) 01:11, Hrvoje Popovski wrote:
> while sending ip6 packets from host connected to vlan200 to host
> connected vlan300 and then destroying vlan300 i'm getting kernel page
> fault. it's clean snapshot from 2017-11-08. it's easily reproducible

You found a nice race.

> # ifconfig vlan300 destroy
> uvm_fault(0xffffffff81afe778, 0xd4, 0, 1) -> e
> kernel: page fault trap, code=0
> Stopped at      ip6_forward+0x59e:      movl    0xd4(%r15),%ecx

When this happens, ifconfig(8) is waiting on the NET_LOCK() but it
already removed the pointer from the array use by if_get(9).

> ddb{3}> ps
>    PID     TID   PPID    UID  S       FLAGS  WAIT          COMMAND
>  90497  504144   5155      0  3         0x3  netlock       ifconfig
                                                             ^^^^^^^^

The problem is that ip6_forward() contains an unchecked if_get().  Diff
below should fix that.

Index: netinet6/ip6_forward.c
===================================================================
RCS file: /cvs/src/sys/netinet6/ip6_forward.c,v
retrieving revision 1.95
diff -u -p -r1.95 ip6_forward.c
--- netinet6/ip6_forward.c      30 Jun 2017 11:29:15 -0000      1.95
+++ netinet6/ip6_forward.c      20 Nov 2017 13:43:37 -0000
@@ -240,6 +240,8 @@ reroute:
         * modified by a redirect.
         */
        ifp = if_get(rt->rt_ifidx);
+       if (ifp == NULL)
+               goto freecopy;
        if (rt->rt_ifidx == m->m_pkthdr.ph_ifidx && !srcrt &&
            ip6_sendredirects &&
            (rt->rt_flags & (RTF_DYNAMIC|RTF_MODIFIED)) == 0) {

Reply via email to