Resolving file descriptor to file name / file path - linux

I am currently developing a simple kernel module that can steal system calls such as open, read, write and replace them with a simple function which logs the files being opened, read, written, into a file and return the original system calls.
My query is, I am able to get the File Descriptor in read and write system calls, but I am not able to understand how to obtain file name using the same.
Currently I am able to access the file structure associated with given FD using following code:
struct file *file;
file = fcheck(fd);
This file structure has two important entities in it, which are of my concern I believe:
f_path
f_inode
Can anybody help me get dentry or inode or the path name associated with this fd using the file structure associated with it?
Is my approach correct? Or do I need to do something different?
I am using Ubuntu 14.04 and my kernel version is 3.19.0-25-generic, for the kernel module development.

.f_inode is actually an inode.
.f_path->dentry is a dentry.
Traversing this dentry via ->d_parent link, until f_path.mnt.mnt_root dentry will be touched, and collecting dentry->d_name components, will construct the file's path, relative to the mount point. This is done, e.g., with d_path, but in more carefull way.
Instead of fcheck(fd), which should be used inside RCU read section, you can also use fget(fd), which should be paired with fput().

The approach is completely incorrect - see http://www.watson.org/~robert/2007woot/
Linux already has a reliable mechanism for doing this thing (audit). If you want to implement it anyway (for fun I presume), you want to place your hooks roughly where audit is doing that. Chances are LSM hooks are in appropriate places, have not checked.

Related

Dynamically create new files within a Linux filesystem driver

I'm working on a Linux filesystem driver and I've got the hang of generating a superblock, creating inodes and dentry's, and making them handle reads and writes.
Now, though, I want the driver to be able to present new files to the user dynamically. Basically, my question is: how can I do this?
Let's say, for a silly example, every time the user reads from a file, we create a new file. Intuitively, I would want to just create a new inode and dentry, and link them together. The problem here is that in my file reading callback function I have no access to the superblock (I think), which means I can't make a new inode.
I won't post the code for my driver since it's too long, even to create a minimal example, but for a general overview: the file_system_type struct's mount function calls mount_nodev, and then in my function to fill the superblock I setup the root directory and create a file named "file1".
Thanks in advance :)
Based on information from a comment by #Tsyvarev, I can indeed create a file dynamically in the same exact fashion as when I first set up the filesystem, taking the superblock from the struct file*'s linked inode!

Example for reading directory contents in kernel mode?

I am currently working on an antiroot-kit for android as a student project. My task is to identify hidden files on the filesystem.
Therefore, I want to read the contents of a directory in a kernel module to compare it with the contents of a directory an app might see in usermode (which is probably censored by a rootkit). I know that file IO is generally a bad idea in kernel mode but I think this might be an exception.
I used filp_open to open a file and get a struct file. With this I was able to get the inode and dentry structures of the file. I was not able to get the contents of a directory this way. I thought there must be a function for it.
I searched on stackoverflow and found the vfs_readdir function. The problem is that I have not understood how to use this function. What do I set for the filldir_t parameter and what do I set for the buffer? How do I retrieve the contents of a directory in a kernelmodule? Can somebody provide an example? I could not find an easy example on the internet and in the linux kernel.

Kernel security modules: i_security in struct inode

my question is probably again pretty simple, but I did not find anything. I am writing a Linux Security Module. As you might know the struct inode in the kernel contains one field i_security to save security relevant information for the LSM. Now just to make sure: Is it safe to assume that no user (not even root) will be able to read or write this value, i.e. can this value really be accessed only from kernel space?
The reason for my question is, that it is obvious that some inode data can be accessed from userspace (through systemcalls I guess, but still using chmod etc. you are able to change some values in an inode) and now I wonder if that doesn't mean, that all inode data (also the i_security) can be accessed from user space somehow.
Cheers
Yes. You can use grep or ack to scan kernel code for i_security, and you can find it is modified only by files under security/ directory, and cannot be modified by user applications, since they have no direct access to the i_security field.

Why can't files be manipulated by inode?

Why is it that you cannot access a file when you only know its inode, without searching for a file that links to that inode? A hard link to the file contains nothing but a name and a number telling you where to find the inode with all the real information about the file. I was surprised when I was told that there was no usermode way to use the inode number directly to open a file.
This seems like such a harmless and useful capability for the system to provide. Why is it not provided?
Security reasons -- to access a file you need permission on the file AS WELL AS permission to search all the directories from the root needed to get at the file. If you could access a file by inode, you could bypass the checks on the containing directories.
This allows you to create a file that can be accessed by a set of users (or a set of groups) and not anyone else -- create directories that are only accessable by the the users (one dir per user), and then hard-link the file into all of those directories -- the file itself is accessable by anyone, but can only actually be accessed by someone who has search permissions on one of the directories it is linked into.
Some Operating Systems do have that facility. For example, OS X needs it to support the Carbon File Manager, and on Linux you can use debugfs. Of course, you can do it on any UNIX from the command-line via find -inum, but the real reason you can't access files by inode is that it isn't particularly useful. It does kindof circumvent file permissions, because if there's a file you can read in a folder you can't read or execute, then opening the inode lets you discover it.
The reason it isn't very useful is that you need to find an inode number via a *stat() call, at which point you already have the filename (or an open fd)...or you need to guess the inum.
In response to your comment: To "pass a file", you can use fd passing over AF_LOCAL sockets by means of SCM_RIGHTS (see man 7 unix).
Btrfs does have an ioctl for that (BTRFS_IOC_INO_PATHS added in this patch), however it does no attempt to check permissions along the path, and is simply reserved to root.
Surely if you've already looked up a file via a path, you shouldn't have to do it again and again?
stat(f,&s); i=open(f,O_MODE);
involves two trawls through a directory structure. This wastes CPU cycles with unnecessary string operations. Yes, the well-designed file system cache will hide most of this inefficiency from a casual end-user, but repeating work for no reason is ugly if not plain silly.

In a linux kernel module, how can I get inode of a known path

In a linux kernel module (i.e. working in kernel space), I have a path of a file.
Which function(s) can be used to get the inode of that file. Specifically I need to get the "inode *" pointing to the file's inode.
You don't have to open the file. There is a lookup function available in kernel which translates char *name to struct nameidata. Please refer to path_lookup.
You may also want to take a look at how path resolution algorithm works, here.
You can use the filp_open function, but as stated in the comment of the function, opening files in kernel module is not something you want to do.
Here is a function that will return the struct file for your path. From there I think you can go to the inode
Bonus : May be this is not what you intend to do, but here is an article on file reading / writing from the kernel, and why you don't want to do it.
Based on my experience with kernel, I suggest that you always go for top level functions like path_lookup rather than functions in the middle.

Resources