2

I'm learning how to write character device drivers as dynamically-loadable modules for the Linux. Typically I use the following sequence of function calls to register the device and create a device file which appears under /dev/:

alloc_chrdev_region(&first, 0, 1, "myclass");
myclass = class_create(THIS_MODULE, "myclass");
device_create(myclass, NULL, first, NULL, "mydevicefile");
cdev_init(&c_dev, &fops);
cdev_add(&c_dev, first, 1);

The device file then appears at /dev/mydevicefile and I'm able to interact with it.

This made me wonder what would happen if passed an existing device file name instead of "mydevicefile":

device_create(myclass, NULL, first, NULL, "null");

This resulted in /dev/null being replaced by my character device file -- and more concerning: an onslaught of error messages in my console from daemons expecting the original /dev/null. Not even removing my faux null module fixed this.

While in practice there should not be an existing device file with the same name as the one my module uses, the fact that it is theoretically possible to overwrite another device file still bothers me.

How do I protect against the case that a device file already exists with the same name as the one I intend to use?

UPDATE: I suppose what I'm really tying to find out is why udev is permitting the replacement.

Vilhelm Gray
  • 11,516
  • 10
  • 61
  • 114

3 Answers3

2

All the device drivers (found in /dev) are basically file types, this means the way you check to see if a device file already exists, is the same way you check to see if any file exists. One way would be to use:

#include <unistd.h>  // for F_OK and access()

...

if( access( "/dev/null", F_OK ) != -1 ) {
    printf("File already exists!\n");
} else {
    printf("File doesn't exist!\n");
    // create new dev here
}

Since /dev/null does exist, you'll see "File exists!" here

Mike
  • 47,263
  • 29
  • 113
  • 177
  • When I try to use `access` within my module, gcc spits out: `error: implicit declaration of function 'access'`. I have `#include ` so I'm not sure what I'm missing. – Vilhelm Gray Mar 15 '13 at 14:23
  • Turns out that accessing userspace files from within the kernel is generally bad practice: http://kernelnewbies.org/FAQ/WhyWritingFilesFromKernelIsBad – Vilhelm Gray Mar 15 '13 at 15:16
  • @VilhelmGray - Yeah, sorry about that, I was thinking about checking form userspace if the /dev/ existed. Check out the link in the accepted answer from this question: http://stackoverflow.com/questions/275386/file-i-o-in-a-linux-kernel-module it is possible to access the file system from the kernel and then do what `access()` does, or even try to `open()` a particular /dev to check for the existance of it... there should be abetter way, but I need to think on it for a bit – Mike Mar 15 '13 at 15:52
  • Perhaps the best practice would be to just register the device in the kernel, then implement a userland init script which would check if there are any filename conflicts before executing mknod to create the device node. But then again, it makes me wonder why udev wouldn't perform such a basic check in the first place. – Vilhelm Gray Mar 15 '13 at 15:58
1
This resulted in /dev/null being replaced by my character device file

You can create a new NULL device file using the mknod utility

sudo mknod -m 0666 /dev/null c 1 3

Barath Ravikumar
  • 5,658
  • 3
  • 23
  • 39
0

Device node creation is typically left to be handled by user space operations. This is the purpose of udev: to populate and handle the user space /dev/ directory by interpreting the data from sysfm.

The name passed to the device_create function is merely a suggested default name that appears in sysfm along with other data about the device; it's ultimately up to the user space utility or user to decide what to do with that data.

It just happens that the default behavior of udev when it encounters a device with the same name is to overwrite the old device node with the new device node: http://marc.info/?l=linux-hotplug&m=125559736630729

Vilhelm Gray
  • 11,516
  • 10
  • 61
  • 114