6

Could anyone provide the code to overcome this problem?

Effectively how do we obtain the struct inode* from kernel level given the file /dev/driver1?

Given in user space that:

int fd;
fd = open("/dev/driver1", O_RDWR | O_SYNC);

In Kernel space:

static long dev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
struct dev_handle *handle;
handle = file->private_data;    

Assuming that, we do not go by that path,

How do we obtain within the kernel itself, by eg. hard coding the file->private_data to be given to handle?

abligh
  • 24,573
  • 4
  • 47
  • 84
  • 2
    Why do you need the file descriptor number? That's not something your filesystem code should need to know. – tangrs Feb 25 '14 at 09:23
  • 1
    I know, but some high ranking guy specified the requirements. No one can change it. – Moirisa Dikaiosýni Feb 25 '14 at 16:12
  • 1
    What are these requirements? This sounds like a XY problem. – tangrs Feb 25 '14 at 20:33
  • That's the requirement. To imitate the calling but from the kernel domain. – Moirisa Dikaiosýni Feb 26 '14 at 03:40
  • 7
    Get the *high ranking guy* fired. He should not be allowed anywhere near Linux kernels. His *"requirements"* are the exact opposite of how the Linux kernel works. The driver interfaces work on userspace pointers, and won't work with kernel ones; you'd need to construct or simulate a userspace process to be able to call these functions. The obvious intent, considering the glaring stupidity of the approach, is to avoid GPLv2 enforcement, right? Won't work, though: the kernel-userspace boundary is not a copyright law boundary, it's just a technical detail. Just ask your lawyer, okay? – Nominal Animal Feb 27 '14 at 08:55
  • 5
    The above is not to say it's impossible; just idiotic and perverse. If you really need to do this, remember you only need a userspace context (including stack, a bit of memory to hold the data, and so on). You can create a process using code similar to the usermodehelper approach, in [kernel/kmod.c](https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/kernel/kmod.c). – Nominal Animal Feb 27 '14 at 09:07
  • Absolutely agree with the high-ranking issue. 1 of our guys highlighted similar issue, but it was still pushed ahead. The user space will not be called. Could you show the codes for this? Thank you – Moirisa Dikaiosýni Feb 27 '14 at 16:14
  • @Babbit: To be honest, I didn't realize using `old_fs=get_fs(); set_fs(KERNEL_DS); DO_STUFF(); set_fs(old_fs);` is a portable way (on non-x86 hardware, I mean) to get around the userspace boundary, but it is. (`__user` is an address space annotation, and `set_fs()` switches between kernel and user address spaces, on all hardware architectures.) Go read what Greg Kroah-Hartman had to say about this approach [in 2005](http://www.linuxjournal.com/node/8110). I'd print the LinuxJournal article, and post it on the nearest wall, making sure the title is visible, if I were you. – Nominal Animal Mar 01 '14 at 11:51

2 Answers2

2

You are looking for filp_open function. From file include/linux/fs.h:

struct file *filp_open(const char *filename, int flags, umode_t mode);

Here is a link to function source and documentation: http://lxr.free-electrons.com/source/fs/open.c#L937

If you really need FD, you can use sys_open (not exported in newer kernels):

long sys_open(const char __user *filename, int flags, int mode);

You can find a very good answer on a similar question: How to read/write files within a Linux kernel module?

Edit (how to get inode):

You can get cached inode from struct file:

struct file *file = ...;
struct inode *inode = file->inode;

If you want it with locking: here is a background: Documentation/filesystems/path-lookup.txt

The starting point for traversing is current->fs->root. There is a number of function in kernel, that already do the work, you can find them in fs/namei.c source file.

There is a function: kern_path:

int error;
struct inode *inode;
struct path path;

error = kern_path(pathname, LOOKUP_FOLLOW, &path);
if (error) ...;

inode = path.dentry->d_inode;
Community
  • 1
  • 1
Valeri Atamaniouk
  • 5,125
  • 2
  • 16
  • 18
1

Your code is in the dev_ioctl function ? If so, then

static long dev_ioctl(struct file *file, unsigned cmd, unsigned long arg)
    struct dev_handle *handle;
    struct inode *inode;
    handle = file->private_data;    
    inode = file->f_inode;

There seems to be no sane documentation for locking requirements, so you should probably try to dig up similar code and see how it operates on the f_inode member.

nos
  • 223,662
  • 58
  • 417
  • 506