调用alloc_netdev时出现分段错误

问题描述 投票:0回答:1

我在编写 Linux 驱动程序时遇到了麻烦。当尝试在这一行分配 netdev 时:

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

我遇到分段错误。我做错了什么?

这是内核日志中的条目:

[ 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

我的内核版本是6.1.0-16-amd64。

我的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

我的虚拟网络驱动程序代码:

#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);`

我发现问题(通过打印)是在 alloc_netdev 函数中引起的,导致代码不执行它

linux-kernel linux-device-driver systems-programming network-driver
1个回答
0
投票

我已经解决了这个问题。这种比较会导致错误 comprasion 最大接口长度包含在 IFNAMSIZ 常量中,等于 16 个字节。它在 Ifdef.h

中定义
© www.soinside.com 2019 - 2024. All rights reserved.