4

I want to check the content of a file from Linux Kernel v3.0.8 knowing only struct inode *. I only need to read the beginning of a file pointed by this inode, then close and return. I don't care about additional information like filename/mountpoint etc.. In fact, the file may not have the name (like deleted but still open). Is it possible?

Piotr Jedyk
  • 361
  • 1
  • 10
  • the `struct inode` has the field `struct inode_operations *i_op;` and the `struct inode_operations` has the field `int (*readpage) (struct file *, struct page *);` but you need the `struct file *` value to call that function, not sure you can with only the _inode_ – bruno Jan 14 '19 at 12:43
  • 1
    kernel v4.19 has `open_with_fake_path` but it comes with dire warnings not to use it, and it needs a `struct cred` to supply the security context. – Ian Abbott Jan 14 '19 at 12:50
  • I don't have `readpage` in `i_op` -- it's 3.0.8 old kernel. The same is for `i_fop` which is `struct file_operations *`, but `open`, `read`, etc. require `struct file *`. – Piotr Jedyk Jan 14 '19 at 12:51
  • I'm checking the code of `open_with_fake_path` -- it looks useful. I will have to move it to my code. `struct cred` is not a problem. – Piotr Jedyk Jan 14 '19 at 12:55
  • @PiotrJedyk I suggest reading the [commit](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=2abc77af89e17582db9039293c8ac881c8c96d79) first, particularly the bit about only doing it if some `dentry` alias of the inode is pinned down. – Ian Abbott Jan 14 '19 at 13:03
  • @IanAbbott, yeah I've read it; currently I need strongly developer version. I'll think about different solutions later (if I'll need). – Piotr Jedyk Jan 14 '19 at 13:07

1 Answers1

5

I finally did it like this:

  1. This is needed.
struct path root;
struct file *filerd;
  1. Get the init task fs root.
task_lock(&init_task);
get_fs_root(init_task.fs, &root);
task_unlock(&init_task);
  1. Change dentry to this file:
root.dentry = d_find_alias(inode);
  1. Open file:
filerd = file_open_root(root.dentry->d_parent, root.mnt,
                        root.dentry->d_name.name, O_RDONLY);

It worked for every process I tested and for different mount points, which surprised me.

Piotr Jedyk
  • 361
  • 1
  • 10