Bug #2660

Use of IPDIVERT causes kernel crashes

Added by shamaz 8 months ago. Updated 8 months ago.

Status:ClosedStart date:
Priority:NormalDue date:
Assignee:tuxillo% Done:

100%

Category:Networking
Target version:3.8.0

Description

Hello. I was trying to set up NAT on DragonFly machine and got a crash. I
have a following configuration:

1) Machine A with DragonFlyBSD 3.4
2) Machine B (the one which crashes) with DragonFlyBSD
3.6.1.24.gd9a9-RELEASE x86_64 (from git branch DragonFly_RELEASE_3_6)
3) Machine C is a vkernel machine hosted by B

Machine B kernel was compiled with following lines in config:

IPFIREWALL
IPFIREWALL_VERBOSE
IPFIREWALL_VERBOSE_LIMIT=100
IPFIREWALL_DEFAULT_TO_ACCEPT
IPDIVERT

Machine B has 2 network interfaces: nfe0 (with connection to A) and tap0
(with connection to C) configured as follows:

$ ifconfig nfe0 192.168.10.1 netmask 255.255.255.0 up (A has an address
192.168.10.2 assigned to re0 which is the interface on the other side)
$ ifconfig tap0 192.168.20.1 netmask 255.255.255.0 up (C has an address
192.168.20.2 assigned to vke0)

So I do as follows:

On machine A:
$ route add default 192.168.10.1

On machine B:
$ sysctl net.inet.ip.forwarding=1
$ ipfw -f flush (accept all because of line in config)
$ natd -interface tap0
$ ipfw add 100 divert natd ip from any to any in via tap0
$ ipfw add 110 divert natd ip from any to any out via tap0

Again, on machine A:
$ ping 192.168.20.2

Machine B crashes. 100% repeatable

Here is a part of the backtrace:

#11 0xffffffff8092429f in calltrap ()
at /usr/src/sys/platform/pc64/x86_64/exception.S:188
#12 0xffffffff80673d22 in ip_input (m=m@entry=0xffffffe0f49ce800)
at /usr/src/sys/netinet/ip_input.c:684
#13 0xffffffff8066813a in div_output (control=<optimized out>,
sin=0xffffffe0f605a130, m=0xffffffe0f49ce800, so=0xffffffe0bf0ff7c0)
at /usr/src/sys/netinet/ip_divert.c:373
#14 div_send (msg=0xffffffe0f54896a0) at
/usr/src/sys/netinet/ip_divert.c:514
#15 0xffffffff8061be6a in netmsg_service_loop (arg=<optimized out>)
at /usr/src/sys/net/netisr.c:319
#16 0xffffffff80571c57 in lwkt_deschedule_self (td=<optimized out>)
at /usr/src/sys/kern/lwkt_thread.c:327

Crash dump (129 Mb) is here:
https://drive.google.com/uc?id=0B1NArWn4pLpxazAxYjJOQVRMeGM&amp;export=download

Vasily

Associated revisions

Revision f82a5263
Added by tuxillo 8 months ago

netinet/ip - Avoid a NULL pointer dereference.

- Before checking for packets on broadcast addresses, see if there
is actually a ifnet associated with the mbuf being handled.

FreeBSD-SVN: 130685
DragonFly-bug: <http://bugs.dragonflybsd.org/issues/2660>
Reported-and-Found-by: Vasily Postnicov

This commit closes #2660

Revision 4d9e27a0
Added by tuxillo 7 months ago

netinet/ip - Avoid a NULL pointer dereference.

- Before checking for packets on broadcast addresses, see if there
is actually a ifnet associated with the mbuf being handled.

FreeBSD-SVN: 130685
DragonFly-bug: <http://bugs.dragonflybsd.org/issues/2660>
Reported-and-Found-by: Vasily Postnicov

This commit closes #2660

History

#1 Updated by tuxillo 8 months ago

  • Category set to Networking
  • Status changed from New to In Progress
  • Assignee set to tuxillo
  • Target version set to 3.8.0

Hi Vasily,

The panic is caused by a null-pointer dereference, see below:

#12 0xffffffff80673d22 in ip_input (m=m@entry=0xffffffe0f49ce800) at /usr/src/sys/netinet/ip_input.c:684
684 if (m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST) {

But rcvif is NULL:

(kgdb) p m->M_dat.MH.MH_pkthdr->rcvif
$3 = (struct ifnet *) 0x0

I'm going to try to reproduce your setup.

Cheers,
Antonio Huete

#2 Updated by shamaz 8 months ago

2014-04-09 11:05 GMT+04:00 <>:

> Issue #2660 has been updated by tuxillo.
>
> Category set to Networking
> Status changed from New to In Progress
> Assignee set to tuxillo
> Target version set to 3.8.0
>
> Hi Vasily,
>
> The panic is caused by a null-pointer dereference, see below:
>
> #12 0xffffffff80673d22 in ip_input (m=m@entry=0xffffffe0f49ce800) at
> /usr/src/sys/netinet/ip_input.c:684
> 684 if (m->m_pkthdr.rcvif->if_flags & IFF_BROADCAST) {
>
> But rcvif is NULL:
>
> (kgdb) p m->M_dat.MH.MH_pkthdr->rcvif
> $3 = (struct ifnet *) 0x0
>
> I'm going to try to reproduce your setup.
>
> Cheers,
> Antonio Huete
>
>
>
> ----------------------------------------
> Bug #2660: Use of IPDIVERT causes kernel crashes
> http://bugs.dragonflybsd.org/issues/2660#change-11913
>
> * Author: shamaz
> * Status: In Progress
> * Priority: Normal
> * Assignee: tuxillo
> * Category: Networking
> * Target version: 3.8.0
> ----------------------------------------
> Hello. I was trying to set up NAT on DragonFly machine and got a crash. I
> have a following configuration:
>
> 1) Machine A with DragonFlyBSD 3.4
> 2) Machine B (the one which crashes) with DragonFlyBSD
> 3.6.1.24.gd9a9-RELEASE x86_64 (from git branch DragonFly_RELEASE_3_6)
> 3) Machine C is a vkernel machine hosted by B
>
> Machine B kernel was compiled with following lines in config:
>
> IPFIREWALL
> IPFIREWALL_VERBOSE
> IPFIREWALL_VERBOSE_LIMIT=100
> IPFIREWALL_DEFAULT_TO_ACCEPT
> IPDIVERT
>
> Machine B has 2 network interfaces: nfe0 (with connection to A) and tap0
> (with connection to C) configured as follows:
>
> $ ifconfig nfe0 192.168.10.1 netmask 255.255.255.0 up (A has an address
> 192.168.10.2 assigned to re0 which is the interface on the other side)
> $ ifconfig tap0 192.168.20.1 netmask 255.255.255.0 up (C has an address
> 192.168.20.2 assigned to vke0)
>
> So I do as follows:
>
> On machine A:
> $ route add default 192.168.10.1
>
> On machine B:
> $ sysctl net.inet.ip.forwarding=1
> $ ipfw -f flush (accept all because of line in config)
> $ natd -interface tap0
> $ ipfw add 100 divert natd ip from any to any in via tap0
> $ ipfw add 110 divert natd ip from any to any out via tap0
>
> Again, on machine A:
> $ ping 192.168.20.2
>
> Machine B crashes. 100% repeatable
>
> Here is a part of the backtrace:
>
> #11 0xffffffff8092429f in calltrap ()
> at /usr/src/sys/platform/pc64/x86_64/exception.S:188
> #12 0xffffffff80673d22 in ip_input (m=m@entry=0xffffffe0f49ce800)
> at /usr/src/sys/netinet/ip_input.c:684
> #13 0xffffffff8066813a in div_output (control=<optimized out>,
> sin=0xffffffe0f605a130, m=0xffffffe0f49ce800, so=0xffffffe0bf0ff7c0)
> at /usr/src/sys/netinet/ip_divert.c:373
> #14 div_send (msg=0xffffffe0f54896a0) at
> /usr/src/sys/netinet/ip_divert.c:514
> #15 0xffffffff8061be6a in netmsg_service_loop (arg=<optimized out>)
> at /usr/src/sys/net/netisr.c:319
> #16 0xffffffff80571c57 in lwkt_deschedule_self (td=<optimized out>)
> at /usr/src/sys/kern/lwkt_thread.c:327
>
> Crash dump (129 Mb) is here:
> https://drive.google.com/uc?id=0B1NArWn4pLpxazAxYjJOQVRMeGM&amp;export=download
>
> Vasily
>
>
>
> --
> You have received this notification because you have either subscribed to
> it, or are involved in it.
> To change your notification preferences, please click here:
> http://bugs.dragonflybsd.org/my/account
>

I've just found out in my little investigation, that this is an old bug
fixed in FreeBSD in 2004. Look at this commit:

https://github.com/freebsd/freebsd/commit/66acd3ba6eb9d3017cc3cdf36d1268749512dd82

So it is OK, that m->m_pkthdr.rcvif == NULL, all we need is just to check
it explicitly. I'll write if this solution works for me (it should)

#3 Updated by shamaz 8 months ago

2014-04-10 16:25 GMT+04:00 Vasily Postnicov <>:

> I've just found out in my little investigation, that this is an old bug
> fixed in FreeBSD in 2004. Look at this commit:
>
>
> https://github.com/freebsd/freebsd/commit/66acd3ba6eb9d3017cc3cdf36d1268749512dd82
>
> So it is OK, that m->m_pkthdr.rcvif == NULL, all we need is just to check
> it explicitly. I'll write if this solution works for me (it should)
>

Yes, it works (I can ping machine C form A, no panic)

#4 Updated by tuxillo 8 months ago

Fix pushed, many thanks!

#5 Updated by tuxillo 8 months ago

  • Status changed from In Progress to Closed
  • % Done changed from 0 to 100

Also available in: Atom PDF