System crash with slip+ip_queue+dnat

Sami Ponkanen sami.ponkanen@vtt.fi
Mon, 17 Dec 2001 17:57:00 +0200


Hello,

Firstly, my network:

A <--- slip ---> B <--- slip ---> C

I was trying to do the following at host B:
1. get a UDP packet sent by a local process (src: B dest: A) to user space 
via ip_queue and libipq
2. give a verdict to the packet
3. redirect the packet back to host B with dnat
However when the packet is reinjected back to kernel space (in step 2 I 
think) I get a kernel oops.

This happens only with UDP+slip. TCP works perfectly and so does UDP if I use 
ppp or ethernet. Similarly slip+UDP does not crash the system if the UDP 
source is on C and B is acting as a router.

The crash is reproducible (atleast on my system) with the code attached below.
Both kernel versions I tested (2.4.7 and 2.4.16) crashed, the ksymoops-dump 
below is from 2.4.7.

Versions of most important stuff:
linux-2.4.7 
iptables-1.2.4
libc-2.2.4.so
slattach 1.21

I'm not sure if I am reading the ksymoops-dump correctly, but the lines with 
references to "eth_header" do seem a bit odd, since as I understand the 
packet should go via lo or slip and not the ethernet interface.

Any ideas how I could solve my problem? I have to use slip, since last time I 
tried ppp did not work well with diffserv stuff.


Thanks,

Sami Pönkänen


slip_crasher.c:
/*
 * slip_crasher.c
 *
 * 1. Set up slip
 * /sbin/slattach -p slip -s 9600 /dev/ttyS0
 * /sbin/ifconfig sl0 192.168.1.2 pointopoint 192.168.1.1
 *
 * 2. Do the iptables stuff
 * modprobe ip_queue
 * iptables -t mangle -A OUTPUT -s 192.168.1.2 -d 192.168.1.1 -p udp -j QUEUE
 * iptables -t nat -A OUTPUT -s 192.168.1.2 -d 192.168.1.1 -p udp -j DNAT 
--to-destination 192.168.1.2
 *
 * 3. Compile and run slip_crasher
 * gcc -L/path/to/libipq/lib -I/path/to/libipq/include -o slip_crasher 
slip_crasher.c -lipq
 * ./slip_crasher
 *
 * 3. Send a couple of UDP packets from 192.168.1.2 to 192.168.1.1
 *
 * 4. Sit back and enjoy
 */
#include "libipq/libipq.h"
#include <stdio.h>

#define BUF_SIZE 65536

int main()
{
   struct ipq_handle *h;
   char buf[BUF_SIZE];
   size_t buf_size = BUF_SIZE, read_bytes;
   int i;

   h = ipq_create_handle(0);
   ipq_set_mode(h, IPQ_COPY_PACKET, BUF_SIZE);
   printf("created ipq handle\n");

   for(i=0; i<2;)
     {
        read_bytes = ipq_read(h, buf, buf_size, 0);
        printf("read  %d  bytes\n", (int) read_bytes);

        if(read_bytes >= 0)
          {

             switch ( ipq_message_type(buf) )
               {
                case IPQM_PACKET:
                    {
                       ipq_packet_msg_t *m = ipq_get_packet(buf);
                       i++;
                       printf("packet %d\n", i);
                       fflush(stdout);

                       /* When i reaches 2 watch your system crash... */
                       ipq_set_verdict(h, m->packet_id, 1, m->data_len, 
m->payload);
                    }
               }
          }
     }

   return 0;
}

ksymoops:
ksymoops 2.4.3 on i586 2.4.7.  Options used
     -V (default)
     -k /var/log/ksymoops/20011217154948.ksyms (specified)
     -l /proc/modules (default)
     -o /lib/modules/2.4.7/ (specified)
     -m /boot/System.map-2.4.7 (specified)

Error (compare_ksyms_lsmod): module slip is in ksyms but not in lsmod
skput:under: c01ca44d:67 put:14 dev:lokernel BUG at skbuff.c:110!
invalid operand: 0000
CPU:    0
EIP:    0010:[<c01c10e1>]
Using defaults from ksymoops -t elf32-i386 -a i386
EFLAGS: 00010286
eax: 0000001c   ebx: 00000800   ecx: c1e92000   edx: c026f224
esi: c2e18800   edi: c0fc4140   ebp: 00000000   esp: c17e5c70
ds: 0018   es: 0018   ss:0018
Process slip_crasher (pid:218, stackpage=c17e5000)
Stack: c024b08c c024b280 0000006e c01ca456 c2e18800 0000000e c01ca44d c1ddb5c0
       c2e18800 c0fc4140 c027bd20 c01c7c46 c2e18800 c027bd20 00000800 c0fc4168
       00000000 00000035 c2e18800 c1ddb5c0 00000000 00000002 c01d5264 c2e18800
Call Trace: [<c01ca456>] [<c01ca44d>] [<c01c7c46>] [<c01d5264>] [<c01ca24e>] 
[<c01d4141>] [<c01d51d0>]
       [<c01d51c9>] [<c01ca369>] [<c02029ab>] [<c0202a80>] [<c0202efd>] 
[<c0206868>] [<c0206271>] [<c02066f3>]
       [<c01be675>] [<c01bf7b8>] [<c0187e48>] [<c01bd457>] [<c0184f06>] 
[<c0188536>] [<c017d820>] [<c017965d>]
       [<c01bfc2c>] [<c0106b43>]
Code: 0f 0b 83 c4 0c c3 90 a1 68 f8 2b c0 57 56 53 f7 d8 8b 7c 24

>>EIP; c01c10e0 <skb_under_panic+3c/44>   <=====
Trace; c01ca456 <eth_header+36/114>
Trace; c01ca44c <eth_header+2c/114>
Trace; c01c7c46 <neigh_resolve_output+ce/1a8>
Trace; c01d5264 <ip_finish_output2+94/d4>
Trace; c01ca24e <nf_hook_slow+136/188>
Trace; c01d4140 <ip_output+50/58>
Trace; c01d51d0 <ip_finish_output2+0/d4>
Trace; c01d51c8 <output_maybe_reroute+c/14>
Trace; c01ca368 <nf_reinject+c8/180>
Trace; c02029aa <ipq_set_verdict+72/84>
Trace; c0202a80 <ipq_receive_peer+c4/d8>
Trace; c0202efc <netlink_receive_user_sk+14c/1bc>
Trace; c0206868 <netlink_data_ready+1c/64>
Trace; c0206270 <netlink_unicast+28c/2d4>
Trace; c02066f2 <netlink_sendmsg+1fa/20c>
Trace; c01be674 <sock_sendmsg+68/88>
Trace; c01bf7b8 <sys_sendmsg+18c/1e8>
Trace; c0187e48 <do_con_write+594/64c>
Trace; c01bd456 <vgacon_cursor+17e/188>
Trace; c0184f06 <set_cursor+6e/88>
Trace; c0188536 <con_flush_chars+16/20>
Trace; c017d820 <write_chan+1fc/214>
Trace; c017965c <tty_write+154/1c0>
Trace; c01bfc2c <sys_socketcall+1e4/200>
Trace; c0106b42 <system_call+32/40>
Code;  c01c10e0 <skb_under_panic+3c/44>
00000000 <_EIP>:
Code;  c01c10e0 <skb_under_panic+3c/44>   <=====
   0:   0f 0b                     ud2a      <=====
Code;  c01c10e2 <skb_under_panic+3e/44>
   2:   83 c4 0c                  add    $0xc,%esp
Code;  c01c10e4 <skb_under_panic+40/44>
   5:   c3                        ret
Code;  c01c10e6 <skb_under_panic+42/44>
   6:   90                        nop
Code;  c01c10e6 <skb_under_panic+42/44>
   7:   a1 68 f8 2b c0            mov    0xc02bf868,%eax
Code;  c01c10ec <alloc_skb+4/190>
   c:   57                        push   %edi
Code;  c01c10ec <alloc_skb+4/190>
   d:   56                        push   %esi
Code;  c01c10ee <alloc_skb+6/190>
   e:   53                        push   %ebx
Code;  c01c10ee <alloc_skb+6/190>
   f:   f7 d8                     neg    %eax
Code;  c01c10f0 <alloc_skb+8/190>
  11:   8b 7c 24 00               mov    0x0(%esp,1),%edi

Kernel panic: Aiee, killing interrupt handler!

1 error issued.  Results may not be reliable.