1

I am having trouble with coding linux driver. When try to allocate netdev in this line:

dev = alloc_netdev(sizeof(struct dev_priv),"super_giga_interface",NET_NAME_UNKNOWN,ipsec_setup);

I get segmentation fault. What am I doing wrong?

Here is entries in kernel journal:

[ 2055.285970] invalid opcode: 0000 [#1] PREEMPT SMP NOPTI
[ 2055.285972] CPU: 3 PID: 3714 Comm: insmod Tainted: G           OE      6.1.0-16-amd64 #1  Debian 6.1.67-1
[ 2055.285974] Hardware name: innotek GmbH VirtualBox/VirtualBox, BIOS VirtualBox 12/01/2006
[ 2055.285975] RIP: 0010:alloc_netdev_mqs+0x418/0x420
[ 2055.285979] Code: e8 dd b2 ae ff 41 0f b7 86 66 02 00 00 4c 89 f7 48 29 c7 e8 5a 2d ae ff e9 4b ff ff ff 49 c7 86 08 02 00 00 00 4b 93 b2 eb b4 <0f> 0b 66 0f 1f 44 00 00 0f 1f 44 00 00 41 57 49 89 cf 41 56 49 89

My kernel version is 6.1.0-16-amd64.

My Makefile:

obj-m += net.o

PWD := $(CURDIR)

all:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules
clean:
    make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

My dummy network driver code:

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/err.h>
#include <linux/slab.h>
#include <linux/netdevice.h>
#include <linux/proc_fs.h>

MODULE_DESCRIPTION("Iplementation of IPsec");
MODULE_AUTHOR("Artem");
MODULE_VERSION("1.0");
MODULE_LICENSE("GPL");

#define NET_BUFF_LENGTH 128
#define PROC_FILENAME "IPsec_buffer"

static struct proc_dir_entry* proc_file;

struct dev_priv {
    char* dev_buff;
    ssize_t dev_buff_length;
};

static struct net_device* dev;
static struct dev_priv* priv;

static int proc_open(struct inode* inode, struct file* filp)
{
    try_module_get(THIS_MODULE);
    return 0;
}

static ssize_t proc_read(struct file* filp, char __user* buffer, size_t len, loff_t* offset)
{
    char* msg = "Reading is not supported!";
    if (buffer == NULL || len < 26)
    {
        return -EINVAL;
    }

    int n = copy_to_user(buffer,msg,26);
    return 26 - n;
}

static ssize_t proc_write(struct file* filp, const char __user* buff, size_t len, loff_t* offset)
{
    if (buff == NULL || len <= 0 || len > NET_BUFF_LENGTH)
    {
        return -EINVAL;
    }
    int n = copy_from_user(priv->dev_buff,buff,len);
    return len - n;

}
static int proc_release(struct inode *, struct file *)
{
    module_put(THIS_MODULE);
    return 0;
}


static const struct proc_ops proc_fops = {
    .proc_open = proc_open,
    .proc_read = proc_read,
    .proc_write = proc_write,
    .proc_release = proc_release,
};

static int open(struct net_device *dev)
{
    pr_info("IPsec: Interface is up\n");
    proc_file = proc_create(PROC_FILENAME, 0444, NULL, &proc_fops);
    if (proc_file == NULL)
    {
        pr_err("IPsec: Can't create proc file!\n");
        return -ENOMEM;
    }
    return 0;
}
static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
{
    pr_info("IPsec: Sending packet\n");
    return NETDEV_TX_OK;
}
static int stop(struct net_device* dev)
{
    pr_info("IPsec: Interface is down\n");
    remove_proc_entry(PROC_FILENAME, NULL);
    return 0;
}

static struct net_device_ops net_ops = {
    .ndo_open = open,
    .ndo_stop = stop,
    .ndo_start_xmit = start_xmit,
};

static void ipsec_setup(struct net_device* dev)
{
    dev->netdev_ops = &net_ops;
}

static int __init ipsec_init(void)
{
    int err;
    dev = alloc_netdev(sizeof(struct dev_priv),"super_giga_interface",NET_NAME_UNKNOWN,ipsec_setup);
    
    if (!dev)
    {
        pr_err("IPsec: Can't allocate netdev!\n");
        return -ENOMEM;
    }
    priv = netdev_priv(dev);
    

    pr_info("IPsec:allocating memory\n");
    priv->dev_buff = kmalloc(NET_BUFF_LENGTH,GFP_KERNEL);
    if (!priv)
    {
        pr_err("IPsec: Can't allocate memory for net device private data!\n");
        return -ENOMEM;
    }
    pr_info("IPsec:memory is allocated!\n");
    priv->dev_buff_length = NET_BUFF_LENGTH;

    err = register_netdev(dev);
    if (err)
    {
        free_netdev(dev);
        pr_err("IPsec: Can't register netdev! Error: %d\n",err);
        return err;
    }
    pr_info("IPsec: Module is successfuly initialized!\n");
    return 0;
}

static void __exit ipsec_cleanup(void)
{
    kfree(priv->dev_buff);
    unregister_netdev(dev);
    free_netdev(dev);
    pr_info("IPsec: Module is successfuly removed!\n");
}

module_init(ipsec_init);
module_exit(ipsec_cleanup);`

I have detected that the problem (by printing) is causing right in alloc_netdev function, cause code does not goes after it

2
  • Does the log contain more useful lines above the one with invalid opcode? E.g. the line started with kernel BUG at .., as in that question? Commented Feb 26, 2024 at 16:36
  • yes, it does kernel BUG at net/core/dev.c:10747! I have found out, that my interface length is lonher than the maximum avaliavle one Commented Feb 26, 2024 at 19:00

1 Answer 1

1

I've solved this problem. This comprasion causes error. Look here snippet from source code

Maximum interface length is contained in IFNAMSIZ constant and equals to 16 bytes. It is defined in Ifdef.h

Sign up to request clarification or add additional context in comments.

1 Comment

Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.