Search code examples
linux-kernelkernel-modulestrcmpnetfilter

strcmp inside kernel module crash


I am trying to to detect the a outgoing packets in my kernel(Netfilter) module. I am using a strcmp function to achieve it. The kernel always crashes after loading my kernel module with strcmp function. I tried removing the strcmp function - loaded without any problem. I hope the problem is with all string function, I also tried strstr() - my system crashed

The logic behind this, Incoming packet will have eth[0-9]+ assigned to "in->name" and "out->name" will be and vice-versa for outgoing packet.

Any insight to detect a outgoing packet? I knew another option is to use output_hook instead of prerouting and postrouting hook. But here I want to mangle both incoming and outgoing packet in different way. Does the kernel version I am using doesn't support string function inside modules?

$ uname -a
Linux vmdsk01 2.6.32-21-generic #32-Ubuntu SMP Fri Apr 16 08:09:38 UTC 2010 x86_64 GNU/Linux

Include Part

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>

#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>

#include <linux/skbuff.h>
#include <linux/inet.h>
#include <linux/ip.h>
#include <linux/tcp.h>
#include <net/ip.h>

#include <linux/string.h>

Main Hook

31 unsigned int main_hook(unsigned int hooknum,  
32                   struct sk_buff *skb,
33                   const struct net_device *in,
34                   const struct net_device *out,
35                   int (*okfn)(struct sk_buff*))
36 {
37     if( strcmp(out->name, "<NULL>") == NULL ) // Outgoing packet must not have <NULL>
38     {
39         printk( KERN_INFO "OUTGOING PACKET");
40     }
41     ....

I also tried replacing line 37 with following, my system hangs

37     if( strstr(out->name, "eth") != NULL ) // Outgoing packet must have eth[0-9]+ 

Solution

  • You might have NULL pointer in out struct pointer. You may add some sanity checks in main_hook like:

    unsigned int main_hook(unsigned int hooknum,  
                       struct sk_buff *skb,
                       const struct net_device *in,
                       const struct net_device *out,
                       int (*okfn)(struct sk_buff*))
     {
         if (!out)
             return -EINVAL;
    
         if( strncmp(out->name, "<NULL>", IFNAMSIZ) == 0 ) // Outgoing packet must not have <NULL>
         {
             printk( KERN_INFO "OUTGOING PACKET");
         }
         ....
    

    So I've added check for out pointer and using strncmp instead of strcmp where IFNAMSIZ is size of out->name as defined in include/linux/netdevice.h. Also, str(n)cmp does not return NULL, it returns 0.

    Check it and please provide any crash messages.