Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I get a filename from a file descriptor inside a kernel module?

I need to get the name of a file from a given file descriptor, inside a small linux kernel module that I wrote. I tried the solution given at Getting Filename from file descriptor in C, but for some reason, it prints out garbage values (on using readlink on /proc/self/fd/NNN as mentioned in the solution). How can I do it?

like image 352
Siddhant Avatar asked Nov 23 '11 22:11

Siddhant


People also ask

How do I get file name from file descriptor?

You can use readlink on /proc/self/fd/NNN where NNN is the file descriptor. This will give you the name of the file as it was when it was opened — however, if the file was moved or deleted since then, it may no longer be accurate (although Linux can track renames in some cases).

Where are the file descriptors stored?

All file descriptors that a process contains are stored in the directory /proc/PID/fd/ . We had already talked a bit about the /proc file system. This directory holds information about processes. Every process has a directory in this filesystem and stores its relevant data within that directory.

Is PID a file descriptor?

No it is not. PID is process identifier, and file descriptor is file handler identifier.

Are directories available through file descriptors in Linux?

In Linux/Unix, everything is a file. Regular file, Directories, and even Devices are files. Every File has an associated number called File Descriptor (FD). Your screen also has a File Descriptor.


1 Answers

Don't call SYS_readlink - use the same method that procfs does when one of those links is read. Start with the code in proc_pid_readlink() and proc_fd_link() in fs/proc/base.c.

Broadly, given an int fd and a struct files_struct *files from the task you're interested in (which you have taken a reference to), you want to do:

char *tmp;
char *pathname;
struct file *file;
struct path *path;

spin_lock(&files->file_lock);
file = fcheck_files(files, fd);
if (!file) {
    spin_unlock(&files->file_lock);
    return -ENOENT;
}

path = &file->f_path;
path_get(path);
spin_unlock(&files->file_lock);

tmp = (char *)__get_free_page(GFP_KERNEL);

if (!tmp) {
    path_put(path);
    return -ENOMEM;
}

pathname = d_path(path, tmp, PAGE_SIZE);
path_put(path);

if (IS_ERR(pathname)) {
    free_page((unsigned long)tmp);
    return PTR_ERR(pathname);
}

/* do something here with pathname */

free_page((unsigned long)tmp);

If your code is running in process-context (eg. invoked through a syscall) and the file descriptor is from the current process, then you can use current->files for the current task's struct files_struct *.

like image 71
caf Avatar answered Oct 04 '22 23:10

caf