How to give root permission to a module?

Viewed 1027

I'm working on a module that when I call echo "hello" > /dev/filename I get bash: /dev/filename: permission denied. For me to get permission I have to call sudo chmod 666 /dev/filename and then echo can work. How can I make my module to have root permission so I don't have to call sudo chmod 666?

ED: It's a character module

3 Answers

You can define your module permission at initialization, thanks to the mode field from the miscdevice structure (see 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);

my module to have root permission

A kernel module runs at the kernel level - it has all possible permissions to do anything with anything.

  1. You can either change the permission of the character device, which you can do for example with chmod.
  2. Or alternatively elevate the permission of the process that is is writing to the character device file, which you can do by for example running your shell with root permisions sudo sh -c 'echo hello > /dev/filename' or pipeing the data to sudo tee.

Assume the file you want to write to is a character device. You can do it programmatically by overwriting dev_uevent of the class created for the device like below.

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;
}
Related