Accessing file system through ioctl function - c

Recently, I developed a simple file system kernel module.
So, I needed to assign my own ioctl function (.unlocked_ioctl) to the file_operation structure to implement specific commands to my file system module. The Ext4 file system has its own ioctl function, for example.
Then, I created a file using the dd command and mounted it:
# mount -t myfs -o loop simple_file /mnt/
Everything works fine, but how can I access this file system using ioctl with a user space program?
I tryed to do ioctl(fd, MY_COMMAND_1, &my_struct_t); (where fd is the file descriptor of the dev file /dev/loop[0..7]), but it returns me Invalid argument.

If you open /dev/loop0, you're accessing a loop device, and therefore you're talking to the loop driver.
The ioctl handler that you've registered for your filesystem applies to files opened on a mounted filesystem.
fd = open("/mnt/something", O_RDWR);
ioctl(fd, MY_COMMAND_1, &my_struct_t);

Related

Kernel module check if file exists

I'm making some extensions to the kernel module nandsim, and I'm having trouble finding the correct way to test if a file exists before opening it. I've read this question, which covers how the basic open/read/write operations go, but I'm having trouble figuring out if and how the normal open(2) flags apply here.
I'm well aware that file reading and writing in kernel modules is bad practice; this code already exists in the kernel and is already reading and writing files. I am simply trying to make a few adjustments to what is already in place. At present, when the module is loaded and instructed to use a cache file (specified as a string path when invoking modprobe), it uses filp_open() to open the file or create it if it does not exist:
/* in nandsim.c */
...
module_param(cache_file, charp, 0400);
...
MODULE_PARM_DESC(cache_file, "File to use to cache nand pages instead of memory");
...
struct file *cfile;
cfile = filp_open(cache_file, O_CREAT | O_RDWR | O_LARGEFILE, 0600);
You might ask, "what do you really want to do here?" I want to include a header for the cache file, such that it can be reused if the system needs to be reset. By including information about the nand page geometry and page count at the beginning of this file, I can more readily simulate a number of error conditions that otherwise would be impossible within the nandsim framework. If I can bring down the nandsim module during file operations, or modify the backing file to model a real-world fault mode, I can recreate the net effect of these error conditions.
This would allow me to bring the simulated device back online using nandsim, and assess how well a fault-tolerant file system is doing its job.
My thought process was to modify it as follows, such that it would fail trying to force creation of a file which already exists:
struct file *cfile;
cfile = filp_open(cache_file, O_CREAT | O_EXCL | O_RDWR | O_LARGEFILE, 0600);
if(IS_ERR(cfile)){
printk(KERN_INFO "File didn't exist: %ld", PTR_ERR(cfile));
/* Do header setup for first-time run of NAND simulation */
}
else{
/* Read header and validate against system parameters. Recover operations */
}
What I'm seeing is an error, but it is not the one I would have expected. It is reporting errno 14, EFAULT (bad address) instead of errno 17 EEXIST (File exists). I don't want to run with this because I would like this to be as idiomatic and correct as possible.
Is there some other way I should be doing this?
Do I need to somehow specify that the file path is in user address space? If so, why is that not the case in the code as it was?
EDIT: I was able to get a reliable error by trying to open with only O_RDWR and O_LARGEFILE, which resulted in ENOENT. It is still not clear why my original approach was incorrect, nor what the best way to accomplish my goal is. That said, if someone more experienced could comment on this, I can add it as a solution.
Indeed, filp_open expects a file path which is in kernel address space. Proof is the use of getname_kernel. You can mimic this for your use case with something like this:
struct filename *name = getname(cache_file);
struct file *cfile = ERR_CAST(name);
if (!IS_ERR(name)) {
cfile = file_open_name(name, O_CREAT | O_EXCL | O_RDWR | O_LARGEFILE, 0600);
if (IS_ERR(cfile))
return PTR_ERR(cfile);
putname(name);
}
Note that getname expects a user-space address and is the equivalent of getname_kernel.

eBPF: retrieve `fd` of the pinned bpf program

I know that eBPF program can be pinned to /sys/fs/bpf (default location of small bpffs. For example using bpftool :
$ bpftool prog load ./my_bpf.o /sys/fs/bpf/my_bpf
I was expecting that open("/sys/fs/bpf/my_bpf") would return me the value of file descriptor allocated for my_bpf by the kernel. But open() call just fails, I think it returns -EINVAL.
In this case, what is the purpose of pinning? How do I normally obtain fd of a BPF program, given that there might be lots of them currently loaded. I know that libbpf allows to retrieve fd from id, but what if I don't have an id either?
bpf(BPF_OBJ_GET, …) wrapped in bpf_obj_get() in libbpf provided by kernel returns fd of the pinned object. Path to pinned object is an argument to bpf_obj_get().

How does a linux kernel module know when its file has been opened?

This is a newbie kernel module question... I have mymodule.c with a function:
static int mymodule_open(struct inode *inode, struct file *filp)
{
//printk(KERN_INFO "open called\n");
/* Success */
return 0;
}
and a user level program where the first line after variable initializations is:
FILE *pFile = fopen("/dev/mymodule", "r+");
When I run the user level program this fopen somehow calls the mymodule_open command in mymodule.c (compiled to mymodule.ko). How does it know to do this? I can't connect the dots as to how mymodule_open() knows when fopen opens up /dev/mymodule.
There is a module registration mechanism in kernel for device driver or kernel modules.
/dev/module will be linked with your module.
The Device operations and file operations structure is mapped with the device file.
something like
struct file_operations fops = {
open : my_module_open,
release : my_module_release,
ioctl : my_module_ioctl,
};
Device file will identify and open the module with help of major and minor number.First with device file and then file operations structure.
Also look into device registration and device file operations
The moment user space hits fopen call, it gets routed to open "system call" and from there to the corresponding/registered driver's fops-open call by identifying the major:minor number of the device file.
Every Device file has got a "major:minor" tuple to belong to a particular driver, and corresponding fops structure will have the supported operations declared/defined.
fopen(/dev/mymodule) -> library_function(open, file_arguments) ->
systemcall(open, file_arguments) -> filesystem_driver(inode, open,
more_arguments) -> filesystem_driver(major:minor, open,
more_arguments) -> fops_structure (open, more_arguments)
NOTE: Above names are for explanation of flow of reach from fopen to mymodule_open, other than that, the names are not absolute function names, viz., library_function, systemcall, filesystem_driver...
The driver knows about the /dev/mymodule file open, because it is a triggered event as mentioned in the above fashion, from fopen, each level of function starts triggering next level of function call, until reaches the ultimate function of mymodule_open inside driver

device file open failed in linux system

I am working in omap4 based system. It has 4 UART port so kernel makes:
/dev/ttyO0
/dev/ttyO1
/dev/ttyO2
/dev/ttyO3
When I open from user space:
fd = open("/dev/ttyO1",O_RDONLY)
it succesfully open and i can peform read and write with that.
But when I open:
fd = open("/dev/ttyO3",O_RDONLY)
Its failed.
I am able to see /dev/ttyO3 node in my system still why i am not able to open it? Any idea?
i have given permission to that node and now i can open that node
chmod 0606 /dev/ttyO3

Finding the description of the device connected to /dev/input/eventX

I have a program that is listening to a certain event file handle. Is there a file I can read to get details about the specific event's device that I am listening to?
Assuming that (a) you're on Linux and (b) you have sysfs mounted (typically on /sys), you can look at /sys/class/input/eventX. This will be a symlink into the device tree; this should provide you some device details. For example:
$ readlink /sys/class/input/event4
../../devices/pci0000:00/0000:00:1d.0/usb2/2-1/2-1.4/2-1.4:1.1/input/input4/event4
For USB devices, you could then probably mount a usbfs filesystem and check out the devices file for more information.
Do you have access to the file descriptor or is this an external program? If this is your fd to the actual device, a list of ioctls provides you with most info you'll need. Have a look at print_device_info from evtest, it does exactly that:
http://cgit.freedesktop.org/evtest/tree/evtest.c#n753

Resources