Exclusively open a device file in Linux
What ways are there available, for exclusively opening a device file (say, the display frame buffer)? [Info: I already know about flock() & friends, which have an effect only when the other applications are also using it (in other words: open() will succeed but flock() will fail if already locked) —> but still the device handle retrieved from open() can be used to write to the display..] What about cases when I want to enforce such an exclusive access on a device files? How would such an enforcement be possible?
here is link on mandatory and advisory locking in linux. thegeekstuff.com/2012/04/linux-file-locking-types
@KinjalPatel That will only work if you are using flock() , otherwise it doesn’t prevent writing. The only way to restrict exclusive opens on devices automatically is to have the device driver perform open reference counts itself.
Does the (effective UID of the) first process to open the modem become the owner of the device for the duration? If so, can your first-to-open process then set the permissions on the modem device to 000 so no-one can open it from there on? There’s a race condition, of course, between opening the device and changing its mode, but if the system automatically reverts the ownership back to the system when the process finishes, it might give more-or-less the right effect. A sufficiently privileged user, or another process by the same user, could dink with the permissions before opening it too.
What about creating a login user for your application and set the device file permissions to allow to be read/written only by that user?
4 Answers 4
To make use of mandatory locks, mandatory locking must be enabled both on the filesystem that contains the file to be locked, and on the file itself.
. also, you need to enable CONFIG_MANDATORY_FILE_LOCKING in the kernel.
Mandatory locking is enabled on a filesystem using the «-o mand» option to mount(8), or the MS_MANDLOCK flag for mount(2). Mandatory locking is enabled on a file by disabling group execute permission on the file and enabling the set-group-ID permis‐ sion bit (see chmod(1) and chmod(2)).
Mandatory locking is not specified by POSIX. Some other systems also support mandatory locking, although the details of how to enable it vary across systems.
So, as you request a posix -compliant solution, the answer is: no, there is not such a feature in the POSIX standard.
how sys_open works?
I have write a simple char device driver (mydev) with «open» file operation in it. In user space application I open this driver node. using open(«/dev/mydev», O_RDONLY); The open() system call internally calls the sys_open(). I just want to know the follow of how sys_open() function call my driver’s open file operation. How VFS handles this, which function it internally calls.
1 Answer 1
I found the answer in Understanding Linux Kernel book, at section 12.5.1
- Invokes getname( ) to read the file pathname from the process address space.
- Invokes get_unused_fd( ) to find an empty slot in current->files->fd. The corresponding index (the new file descriptor) is stored in the fd local variable.
- Invokes the filp_open( ) function, passing as parameters the pathname, the access mode flags, and the permission bit mask. This function, in turn, executes the following steps: a. Invokes get_empty_filp( ) to get a new file object. b. Sets the f_flags and f_mode fields of the file object according to the values of the flags and modes parameters. c. Invokes open_namei( ), which executes the following operations:
i. Invokes lookup_dentry( ) to interpret the file pathname and gets the dentry object associated with the requested file. ii. Performs a series of checks to verify whether the process is permitted to open the file as specified by the values of the flags parameter. If so, returns the address of the dentry object; otherwise, returns an error code.
Opening files (and Linux drivers)
We should be careful (if not downright paranoid) when opening files. Some of the recommended checks to perform and best practices include:
- Using realpath(3) to produce a canonicalized absolute path for us when the path comes from outside.
- Setting O_CLOEXEC to make sure that the file descriptor is not leaked to any child processes we spawn
- Sanity-checking the file with fstat(2) to make sure it looks like the kind of file we are expecting
When appropriate, we can also use the fstat(2) output to check for:
- Expected file ownership (at least with the st_uid and st_gid ), for example if we expect a specific user and/or group to own the file, regardless of our ability to access it.
- An expected physical location ( st_dev field), for example if we expect it to reside on a specific disk or device regardless of what the path says.
- Expected permissions ( st_mode field), for example we may want to refuse to open an executable file or a file with too lax of permissions no matter what
The path
A program taking a path from the outside world, for example through a command line argument, should sanitize the path (per CERT FIOO2-C). Typically this looks like:
int main(int argc, char **argv) < if (argc < 2) < printf("Usage: %s \n", argv[0]); exit(EXIT_SUCCESS); > char *path = realpath(argv[1], NULL); if (!path) < fprintf(stderr, "Invalid argument: %m");
The resolved path will need to be freed.
Example: Talking to a SPI (spidev) device
We can now try to open the file given the resolved path, however we should sanity-check that the file looks like something that we expect to open. For example, a SPI device interfaced via the Linux spidev driver should at least:
We specifically want to use fstat(2) rather than stat(2) because we want to be sure that we are checking the file we opened rather than checking a path twice (and allowing whatever the path resolves to to change out from under us).
int fd = open(path, O_CLOEXEC); if (fd == -1)
Then we perform some basic sanity checks. The st_mode field tells us what kind of file we have and there are convenient macros to simplify our checks: ST_IS_CHR checks that this is a character device, which is what we expect. In order cases we may want a regular file ( S_ISREG matches that).
For character devices and other special files we also have the st_rdev field on which we can use macros major and minor to check for specific IDs.
struct stat st; if (fstat(fd, &st) || !S_IS_CHR(st.st_mode) || major(st.st_rdev) != 153)
We have now opened the file and reasonably believe that it is a SPI device. Our cleanup would be in reverse order:
out_st: close(fd); out_fd: free(path);
or the GCC cleanup attribute can be used to clean up resources.
Reading configuration files in linux device driver
How to read configuration files in linux device driver? Experts say that reading and writing file in kernel space is a bad practise. For firmware download we have request_firmware kernel API. Is there a linux kernel API for reading and parsing configuration files for drivers? Eg: Reading baudrate and firmware file path for a particular driver.
There are many ways to configure devices, such as autoconfiguration, ioctl s, or module parameters. What exactly do you want to configure?
I am developing a driver to interact with UART. Need to set baudrate and firmware file location as configurable parameters to driver module. I wanted to explore if there was a Kernel interface for this purpose.
1 Answer 1
Most of the times doing file i/o from kernel space is discouraged, but if you still want the way to read files from kernel space, kernel provides a good interface to open and read files from kernel. Here is an example module.
/* * read_file.c - A Module to read a file from Kernel Space */ #include #include #define PATH "/home/knare/test.c" int mod_init(void) < struct file *fp; char buf[512]; int offset = 0; int ret, i; /*open the file in read mode*/ fp = filp_open(PATH, O_RDONLY, 0); if (IS_ERR(fp)) < printk("Cannot open the file %ld\n", PTR_ERR(fp)); return -1; >printk("Opened the file successfully\n"); /*Read the data to the end of the file*/ while (1) < ret = kernel_read(fp, offset, buf, 512); if (ret >0) < for (i = 0; i < ret; i++) printk("%c", buf[i]); offset += ret; >else break; > filp_close(fp, NULL); return 0; > void mod_exit(void) < >module_init(mod_init); module_exit(mod_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Knare Technologies (www.knare.org)"); MODULE_DESCRIPTION("Module to read a file from kernel space");
I tested this module on linux-3.2 kernel. I used printk() function to print the data, but it will not be your actual case, this is just shown as an example.