Project

General

Profile

Actions

Bug #2660

closed

Use of IPDIVERT causes kernel crashes

Added by shamaz about 10 years ago. Updated about 10 years ago.

Status:
Closed
Priority:
Normal
Assignee:
Category:
Networking
Target version:
Start date:
Due date:
% Done:

100%

Estimated time:

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&export=download

Vasily
Actions #1

Updated by tuxillo about 10 years ago

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

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

Actions #2

Updated by shamaz about 10 years 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&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)

Actions #3

Updated by shamaz about 10 years 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)

Actions #4

Updated by tuxillo about 10 years ago

Fix pushed, many thanks!

Actions #5

Updated by tuxillo about 10 years ago

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

Also available in: Atom PDF