【问题标题】:How to give root permission to a module?如何授予模块root权限?
【发布时间】:2020-04-10 17:43:33
【问题描述】:

我正在开发一个模块,当我调用echo "hello" > /dev/filename 时,我会得到bash: /dev/filename: permission denied。为了获得许可,我必须致电sudo chmod 666 /dev/filename,然后 echo 才能工作。如何让我的模块获得 root 权限,这样我就不必调用sudo chmod 666

ED:这是一个字符模块

【问题讨论】:

    标签: linux-kernel linux-device-driver


    【解决方案1】:

    您可以在初始化时定义您的模块权限,这要归功于miscdevice 结构中的mode 字段(请参阅here):

    #include <linux/miscdevice.h>
    
    static struct miscdevice my_module_cnf = {
        /*some other fields*/,
        .mode = 0666,
    };
    
    static int __init my_module_init(void)
    {
        int ret = misc_register(&my_module_cnf);
        if (ret < 0) {
            printk(KERN_ERR "Unable to register my module");
            return ret;
        }
    
        return 0;
    }
    
    static void __exit my_module_exit(void)
    {
        misc_deregister(&my_module_cnf);
    }
    
    module_init(my_module_init);
    module_exit(my_module_exit);
    

    【讨论】:

    • ...如果它不是杂项设备?
    • 我试过了,但我得到了insmod: ERROR: could not insert module ./filename.ko: Cannot allocate memory
    • @0andriy High 实际上是针对这类问题的机会。
    • @Renato 你能在/dev/ 看到它吗?输入dmesg | grep filename 时是否看到任何有助于调试的相关信息?
    【解决方案2】:

    我的模块拥有root权限

    内核模块在内核级别运行 - 它拥有所有可能的权限来做任何事情。

    1. 您可以更改字符设备的权限,例如使用chmod
    2. 或者提升正在写入字符设备文件的进程的权限,例如,您可以使用 root 权限运行 shell sudo sh -c 'echo hello &gt; /dev/filename' 或将数据通过管道传输到 sudo tee

    【讨论】:

    • 这些解决方案的问题在于,它们都需要一个 sudoer 帐户,这在此处可能不会出现。如果您是模块所有者并且希望允许非 root 用户使用它,您可以在初始化时以编程方式进行(请参阅我的回答)。
    • 为什么你认为它是一个字符设备?
    • 它是一个字符设备,因为用字符设备开始内核编程是最常见的。我认为这对我的回答而言并不重要。如果您有兴趣,请向 OP 索取更多信息。
    【解决方案3】:

    假设您要写入的file 是一个字符设备。您可以通过覆盖为设备创建的类的dev_uevent 以编程方式完成,如下所示。

    static struct class *cl;
    
    int my_uevent(struct device *dev, struct kobj_uevent_env *env)
    {
        add_uevent_var(env, "DEVMODE=%#o", 0666);
        return 0;
    }
    
    .....
    
    int my_init(void)
    {
        int ret;
        struct device *dev_ret = NULL;
    
        if((ret = alloc_chrdev_region(&dev, FIRST_MINOR, MINOR_CNT, "char_dev")) < 0)
        {
            return ret;
        }
        printk("Major Nr: %d\n", MAJOR(dev));
    
        cdev_init(&c_dev, &fops);
    
        if((ret = cdev_add(&c_dev, dev, MINOR_CNT)) < 0)
        {
            unregister_chrdev_region(dev, MINOR_CNT);
            return ret;
        }
    
        if(IS_ERR(cl = class_create(THIS_MODULE, "chardrv")))
        {
            cdev_del(&c_dev);
            unregister_chrdev_region(dev, MINOR_CNT);
            return PTR_ERR(cl);
        }
    
        cl->dev_uevent = my_uevent; // <-- overwrite dev_uevent here
    
        if(IS_ERR(dev_ret = device_create(cl, NULL, dev, NULL, "mychar%d", 0)))
        {
            class_destroy(cl);
            cdev_del(&c_dev);
            unregister_chrdev_region(dev, MINOR_CNT);
            return PTR_ERR(dev_ret);
        }
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-23
      • 1970-01-01
      • 1970-01-01
      • 2012-01-19
      • 2012-04-29
      • 1970-01-01
      • 2019-01-23
      • 1970-01-01
      相关资源
      最近更新 更多