Kernel panic with skb_alloc during post_routing

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi,

I am writing a netfilter module to process outgoing packets
(NF_INET_POST_ROUTING) and modify them according to certain rules. In
the current version, I am just trying to push the same VLAN tag on
every outgoing pkt.
However, after running for a few seconds at ~1Gbps, it crashes with
kernel panic. Also, I see similar crash, when I don't modify the pkt,
i.e. I create a copy and send it. Am I missing something when using
skb_alloc()? What can I do next to debug this issue?

------------------------------------------
Log:
------------------------------------------

      KERNEL: /usr/lib/debug/boot/vmlinux-3.13.0-32-generic
    DUMPFILE: dump.201505121934  [PARTIAL DUMP]
        CPUS: 4
        DATE: Tue May 12 19:34:18 2015
      UPTIME: 00:22:08
LOAD AVERAGE: 1.95, 1.34, 0.64
       TASKS: 752
     RELEASE: 3.13.0-32-generic
     VERSION: #57-Ubuntu SMP Tue Jul 15 03:51:08 UTC 2014
     MACHINE: x86_64  (2699 Mhz)
      MEMORY: 4 GB
       PANIC: ""
         PID: 6186
     COMMAND: "client"
        TASK: ffff88009e5017f0  [THREAD_INFO: ffff88009b20e000]
         CPU: 1
       STATE: TASK_RUNNING (PANIC)

crash> bt
PID: 6186   TASK: ffff88009e5017f0  CPU: 1   COMMAND: "client"
 #0 [ffff88013fc83610] machine_kexec at ffffffff8104a742
 #1 [ffff88013fc83660] crash_kexec at ffffffff810e6cf3
 #2 [ffff88013fc83728] oops_end at ffffffff817251a8
 #3 [ffff88013fc83750] die at ffffffff810171db
 #4 [ffff88013fc83780] do_general_protection at ffffffff81724ace
 #5 [ffff88013fc837b0] general_protection at ffffffff817243e8
    [exception RIP: __kmalloc_node_track_caller+371]
    RIP: ffffffff811a4383  RSP: ffff88013fc83860  RFLAGS: 00010246
    RAX: 0000000000000000  RBX: ffff88009f62b500  RCX: 00000000013656da
    RDX: 00000000013656d9  RSI: 0000000000000000  RDI: 00000000000172c0
    RBP: ffff88013fc838a8   R8: ffff88013fc972c0   R9: ffff88013b001400
    R10: ffff88013b001400  R11: 0000000000000000  R12: 0000000000010220
    R13: 0000000000000740  R14: 5452d00923005452  R15: 00000000ffffffff
    ORIG_RAX: ffffffffffffffff  CS: 0010  SS: 0018
 #6 [ffff88013fc83860] sch_direct_xmit at ffffffff81640cdf
 #7 [ffff88013fc838b0] __kmalloc_reserve at ffffffff816104f1
 #8 [ffff88013fc838f0] __alloc_skb at ffffffff81610e7e
 #9 [ffff88013fc83938] process_pkt_post_routing at ffffffffa0295a74 [modmerlin]
#10 [ffff88013fc839b8] nf_iterate at ffffffff8164faba
#11 [ffff88013fc83a00] nf_hook_slow at ffffffff8164fb44
#12 [ffff88013fc83a68] ip_output at ffffffff8165bf02
#13 [ffff88013fc83a88] ip_local_out at ffffffff8165b635
#14 [ffff88013fc83aa0] ip_queue_xmit at ffffffff8165b98d
#15 [ffff88013fc83ad8] tcp_transmit_skb at ffffffff81672749
#16 [ffff88013fc83b40] tcp_write_xmit at ffffffff81672cf0
#17 [ffff88013fc83ba8] __tcp_push_pending_frames at ffffffff8167391e
#18 [ffff88013fc83bc0] tcp_rcv_established at ffffffff8166f2bf
#19 [ffff88013fc83c08] tcp_v4_do_rcv at ffffffff81679185
#20 [ffff88013fc83c78] tcp_v4_rcv at ffffffff8167b590
#21 [ffff88013fc83cf0] ip_local_deliver_finish at ffffffff81656328
#22 [ffff88013fc83d18] ip_local_deliver at ffffffff81656628
#23 [ffff88013fc83d38] ip_rcv_finish at ffffffff81655fad
#24 [ffff88013fc83d60] ip_rcv at ffffffff816568f8
#25 [ffff88013fc83d90] __netif_receive_skb_core at ffffffff81620366
#26 [ffff88013fc83de8] __netif_receive_skb at ffffffff81620558
#27 [ffff88013fc83e08] netif_receive_skb at ffffffff816205c3
#28 [ffff88013fc83e30] virtnet_poll at ffffffff81526384
#29 [ffff88013fc83eb0] net_rx_action at ffffffff81620942
#30 [ffff88013fc83f08] __do_softirq at ffffffff8106cafc
#31 [ffff88013fc83f68] irq_exit at ffffffff8106d045
#32 [ffff88013fc83f80] do_IRQ at ffffffff8172e996
--- <IRQ stack> ---
#33 [ffff88009b20fbb8] ret_from_intr at ffffffff8172412d
    [exception RIP: __copy_user_nocache+96]
    RIP: ffffffff8136d320  RSP: ffff88009b20fc60  RFLAGS: 00000206
    RAX: 0000000000000000  RBX: ffff8800a16c3800  RCX: 000000000000000c
    RDX: 0000000000000014  RSI: 0000000001444890  RDI: ffff8800a00663b0
    RBP: ffff88009b20fd18   R8: 74737271706f6e6d   R9: 31307a7978777675
    R10: 3938373635343332  R11: 6c6b6a6968676665  R12: 00000000ffffffff
    R13: 00000000000000d0  R14: ffff8800a16c3800  R15: ffff88013b001600
    ORIG_RAX: ffffffffffffff7c  CS: 0010  SS: 0018
#34 [ffff88009b20fc60] tcp_sendmsg at ffffffff81665296
#35 [ffff88009b20fd20] inet_sendmsg at ffffffff8168e8f4
#36 [ffff88009b20fd50] sock_sendmsg at ffffffff816079eb
#37 [ffff88009b20fe58] SYSC_sendto at ffffffff81607b91
#38 [ffff88009b20ff70] sys_sendto at ffffffff816086ae
#39 [ffff88009b20ff80] tracesys at ffffffff8172c87f (via system_call)
    RIP: 00007ff3166a403d  RSP: 00007fff6b95f828  RFLAGS: 00000246
    RAX: ffffffffffffffda  RBX: ffffffff8172c87f  RCX: ffffffffffffffff
    RDX: 0000000000000e10  RSI: 0000000001444010  RDI: 0000000000000003
    RBP: 00007fff6b95fa90   R8: 0000000000000000   R9: 0000000000000000
    R10: 0000000000000000  R11: 0000000000000246  R12: ffffffff816086ae
    R13: ffff88009b20ff78  R14: 0000000000000000  R15: 0000000000000000
    ORIG_RAX: 000000000000002c  CS: 0033  SS: 002b


------------------------------------------
Code:
------------------------------------------

static unsigned int post_routing_process(const struct nf_hook_ops *ops,
        struct sk_buff *skb,
        const struct net_device *in,
        const struct net_device *out
        /*, int (*okfn)(struct sk_buff *)) */
)
{
    struct ethhdr *eth_hdr;
    __be16 proto;
    struct iphdr *ip_hdr;
    struct iphdr *ip_hdr2;
    char* ip_pkt;
    char* ip_pkt2;
    int ip_pkt_len;
    int ip_pkt_len2;
    struct sk_buff *skb2 = NULL;
    struct flow_keys flow_key;
    int eth_hdr_len, full_pkt_len, ip_hdr_len;
    void *saddr;
    void *daddr;

    struct stack stk;

    u_int16_t tag11[] = {11};

    __wsum skb2_csum = 0;
    unsigned char dst[] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};

    pr_debug("Packet in ++++++++\n");

    if(skb_is_nonlinear(skb)){
        pr_debug("Proces_pkt: Still non-linear skb.\n");
        goto cleanup;
    }

    proto = ntohs(skb->protocol);
    switch (proto) {
        case ETH_P_IP:
            eth_hdr = (struct ethhdr *)skb_mac_header(skb); // need to set
            // proto is set; h_proto isn't
            pr_debug("Proto: %04x %04x\n", ntohs(eth_hdr->h_proto), proto);

            ip_hdr = (struct iphdr *)skb_network_header(skb);
            ip_hdr_len = ip_hdrlen(skb);
            ip_pkt = (char*)ip_hdr;
            ip_pkt_len = ntohs(ip_hdr->tot_len);
            skb_flow_dissect(skb, &flow_key);

            /* struct stk {int num_tags; u_int16_t tags[]; }; */
            stk.num_tags = 1;
            stk.tags = tag11;
            eth_hdr_len = ETH_HLEN + stk.num_tags * sizeof(vlan_label);
            full_pkt_len = eth_hdr_len + ip_pkt_len;
            pr_debug("Full length: %d", full_pkt_len);

            skb2 = alloc_skb(full_pkt_len, GFP_ATOMIC);

            if (skb2 == NULL) {
                goto cleanup;
            }
            if(skb->sk != NULL) {
                skb_set_owner_w(skb2, skb->sk);
            }
            else{
                goto cleanup;
            }

            pr_debug("mod_vlan: skb2 - Reserving header\n");
            skb_reserve(skb2, eth_hdr_len);

            // Copy IP packet
            pr_debug("mod_vlan: copying IP pkt.\n");
            if (!(ip_pkt2 = skb_put(skb2, ip_pkt_len))) {
                pr_debug("skb_put failed!\n");
                goto cleanup;
            }
            skb_reset_network_header(skb2);
            memcpy(ip_pkt2, ip_pkt, ip_pkt_len);
            ip_hdr2 = (struct iphdr *)(ip_pkt2);
            ip_pkt_len2 = ntohs(ip_hdr2->tot_len);

            skb2_csum = fix_csum(ip_hdr2);

            // Set VLAN stack
            if(set_vlan_stack(skb2, &stk)){
                proto = ETH_P_8021Q;
            }

            // Get outgoing interface
            skb2->dev = dev_get_by_name(&init_net,out->name);
            if (!skb2->dev) {
                pr_debug("mod_vlan dev_get_by_name (%s) FAILED.", out->name);
                goto cleanup;
            }

            saddr = skb2->dev->dev_addr;
            daddr = dst;

            // ARP Lookup
            if(0 == get_dst_haddr(daddr, flow_key.dst, skb2->dev)){
                pr_debug("ARP lookup - success!\n");
            }

            pr_debug("calling dev_hard_header\n");
            if (dev_hard_header(skb2, skb2->dev, proto,
                        daddr, saddr, skb2->dev->addr_len) < 0) {
                pr_debug("mod_vlan dev_hard_header FAILED.\n");
                goto cleanup;
            }
            pr_debug("Resetting mac header\n");
            skb_reset_mac_header(skb2);
            pr_debug("mod_vlan dev_hard_header SUCCESS.\n");

            // Set skb checksum
            skb2->csum = skb2_csum;

            // Send out packet
            pr_debug("mod_vlan: sending skb2....\n");
            if (dev_queue_xmit(skb2) != NET_XMIT_SUCCESS) {
                pr_debug("mod_vlan dev_queue_xmit failed.");
                goto cleanup;
            }
            kfree_skb(skb);
            return NF_STOLEN;
            break;
        default:
            pr_debug("Proto: Non-IP pkt\n");
            break;
    }
cleanup:
    if(skb2)   kfree_skb(skb2);
    if(skb) kfree_skb(skb);
    return NF_STOLEN;
}



Thanks,
Praveen
--
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html




[Index of Archives]     [Netfitler Users]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux