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) {