Kernel security modules: i_security in struct inode - linux

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.

Related

Resolving file descriptor to file name / file path

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.

What is the best way to store information within the Linux kernel?

A kernel module I created is constantly generating information that I would like to store within the kernel and be readable from root. I was thinking of storing the information in some sort of log file with specific permissions, but I read that writing to files within the kernel space code is not good.
What is a good way to store information in the kernel that is fast and accessible by root?
~Thanks
If it's constantly generating new information, I would write it out with printk(). This way it will be seen by dmesg as well be written out to /var/log/kern.log.
Although, this is not for sensitive information, since dmesg could be used by any user.
Depending on the type of information, you can also provide it via /proc or /sys files, netlink, relayfs, /dev ioctl.

Files informations on unix-based file systems

When I create a new file (eg. touch file.txt) its size equals to 0B.
I'm wondering where are its informations (size, last modify date, owner name, file name) stored.
These informations are stored on hd and are managed by kernel, of course, but I'd love to know something more about them:
Where and how I may get them, using a programming language as C, for example, and how I may change them.
Are these informations changeable, simply using a programming language, or maybe kernel avoids this operations?
I'm working on Unix based file systems, and I'm asking informations especially about this fs.
On unix system, they're traditionally stored in the metadata part of a file representation called an inode
You can fetch this information with the stat() call, see these fields, you can change the owner and permissions with chown() and chmod()
This information is retrievable using the stat() function (and others in its family). Where it's stored is up to the specific file system and for what should be obvious reasons, you cannot change them unless you have raw access to the drive -- and that should be avoided unless you're ok with losing everything on that drive.
The metadata such as owner, size and dates are usually stored in a structure called index-node (inode), which resides in the filesystem's superblock.

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.

Getting inode from path in Linux Kernel

I'm currently trying to get an inode for a given pathname in a kernel function. All I have available is the full pathname. I've tried attempts like:
user_path_at(AT_FDCWD, buffer, LOOKUP_FOLLOW, &path);
But the dentry in that given path isn't valid, it seems to turn out. Then I thought perhaps trying stat() and getting the inode number from that. However, that only gives me a number, not a struct inode. I don't know of a way to convert an inode number to an inode without grabbing an existing inode and traversing the entire list of inodes. And I don't even know if that would work. But I certainly don't want to do that.
Is there any simple way to get a struct inode from a char *pathname inside the kernel?
stat() will give you the inode of a file in the "st_ino" field.
Sorry, initial misunderstanding of the question.
If you want the actual inode structure within the kernel, I'm pretty certain the kernel itself wouldn't walk an array or list looking for the inode number (unless the list is very small). Since the code to the kernel is publicly available, you should be able to find out how it does it, then do the same.
There is no easy way since struct inode is part of the kernel and you are in user space. It all depends on the particular filesystem implementation. Are you sure that info in stat struct is not enough for your needs?
Anyway, this link might help.

Resources