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?
Asked
Active
Viewed 1.6k times
18
-
possible duplicate of [sys_readlink fails EFAULT - alternative](http://stackoverflow.com/questions/8216871/sys-readlink-fails-efault-alternative) – ephemient Nov 23 '11 at 22:52
1 Answers
27
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 *
.

caf
- 233,326
- 40
- 323
- 462
-
Nice. That worked. Thanks! Quick question though. What purpose do the `path_get` and `path_put` calls serve (because removing them doesn't have much of an effect on my program)? Also, any idea why wouldn't `sys_readlink` work? – Siddhant Nov 25 '11 at 23:42
-
1@Siddhant: The `path_get()` and `path_put()` calls are required for correctness, because they pin the path so that it doesn't go away while you are trying to work with it (all the `struct path` contains is a pair of pointers, to a `struct vfsmount` and a `struct dentry`). – caf Nov 26 '11 at 00:32
-
Also, why is it necessary to call `path_get` and get a reference to the path structure? – sherrellbc Jun 15 '15 at 15:07
-
Is there a reason or benefit of allocating a single page from memory as opposed to using `kmalloc`? Is it simply because you know a page would fit the worst-case requirement for the path data? It seems that the whole mess witih `IS_ERR` and `PTR_ERR` could be avoided by simply using the latter memory allocation method. – sherrellbc Jun 15 '15 at 15:25
-
@sherrellbc: Right, the pagesize is an upper limit on the possible size of the pathname, so there's no point in using `kmalloc()` - the return value of `d_path()` has to be tested with `IS_ERR()` regardless. It is necessary to call `path_get()` to prevent the path from going away after we release `->file_lock` (because at that point, the file could be closed by another thread in parallel). We don't want to keep `->file_lock` held for longer than necessary because it's a spinlock. – caf Jun 16 '15 at 01:49
-
In fact I'm not even sure if it's allowed to call `d_path()` while holding a spinlock. – caf Jun 16 '15 at 01:50
-
If your code is running in process-context ... then you can use **current->files** for the current task's **files_struct**. See this [answer](http://stackoverflow.com/a/17512619/2706918). – Nitinkumar Ambekar Aug 25 '15 at 06:01
-
Wouldn't be possible in this case to use, `rcu_read_lock()/rcu_read_unlock()`, instead of `spin_lock/spin_unlock`? it seems that is only reading the values of the files struct without updating them. – wallek876 Nov 05 '19 at 12:17
-
@wallek876: I believe that using RCU protection for this would require taking a reference on the `struct file` itself instead, because the file reference count can be decremented to zero while the RCU lock is held. – caf Nov 06 '19 at 03:13
-
Whats wrong with just `strcpy(n, file->f_path.dentry->d_name.name);` – teknopaul Jun 20 '21 at 17:38
-
@teknopaul: That will only look at the final component of the path, not the full pathname. It also races with dcache modifications like renames. – caf Jun 21 '21 at 14:54
-
I use d_path in __fput kprobe handler func to get file name from struct file , and it panic. Why is cannot used there ? – seamaner Dec 28 '22 at 06:01
-
@seamaner: I suggest you ask a new question and include more information about the panic and your code. – caf Dec 29 '22 at 07:36
-
@caf Thanks. I found that 'current->fs == NULL' and 'current->mm == NULL' too, so its a kthread. – seamaner Jan 04 '23 at 07:19