Search code examples
clinux-kernellinux-device-driverkernel-moduledevice-driver

How to set the mode for a character device in a Linux kernel module?


I'm creating a character device module that plays a game of Tic-tac-toe. I'm trying to program it so it sets it's /dev/ticactoe mode to 666, instead of having a user use the chmod command.

My main.c contains the following with implementations of tictactoe's init and exit (redacted for conciseness):

static dev_t device_number;
static struct cdev our_cdev;
static struct class* my_class = NULL;

static struct file_operations fops = {
.owner = THIS_MODULE,
.read = tictactoe_read,
.write = tictactoe_write,
.open = tictactoe_open,
.release = tictactoe_release,
};

I have a tictactoe.h containing the following:

#define MODULE_NAME "tictactoe"

int tictactoe_open(struct inode *pinode, struct file *pfile);
ssize_t tictactoe_read(struct file *pfile, char __user *buffer, size_t length, loff_t *offset);
ssize_t tictactoe_write(struct file *pfile, const char __user *buffer, size_t length, loff_t *offset);
int tictactoe_release(struct inode *pinode, struct file *pfile);

I read about umode_t, but I'm not sure how I might use that for this module. Can anyone lead me in the right direction or explain how to implement the umode_t variable? Any help is appreciated.


Solution

  • The kernel source code for /dev/{null,zero,...} is a good place to look for this kind of stuff when you are in doubt, take a look at how this is implemented in drivers/char/mem.c.

    Once you've created the class my_class for your device, you should set the ->devnode field to a function to set the mode you want. You can find modes in the <linux/stat.h> header, setting to 666 means rw-rw-rw-, which is S_IRUGO|S_IWUGO. It's a good idea to make this a constant somewhere in the code.

    Here's the solution:

    #define DEV_CLASS_MODE ((umode_t)(S_IRUGO|S_IWUGO))
    
    static char *my_class_devnode(struct device *dev, umode_t *mode)
    {
        if (mode != NULL)
            *mode = DEV_CLASS_MODE;
        return NULL;
    }
    

    Then in your module init function:

    my_class = class_create(THIS_MODULE, "tictactoe");
    if (IS_ERR(my_class)) {
        // Abort...
    }
    
    my_class->devnode = my_class_devnode;
    

    Oh, and by the way, you do not need to #define MODULE_NAME, it's already defined automatically and it's KBUILD_MODNAME.