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