[Bug 252730] Linuxulator: The symbol link file permissions returned by stat are inconsistent with linux

bugzilla-noreply at freebsd.org bugzilla-noreply at freebsd.org
Sat Jan 16 04:09:20 UTC 2021


https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=252730

            Bug ID: 252730
           Summary: Linuxulator: The symbol link file permissions returned
                    by stat are inconsistent with linux
           Product: Base System
           Version: CURRENT
          Hardware: Any
                OS: Any
            Status: New
          Severity: Affects Only Me
          Priority: ---
         Component: kern
          Assignee: bugs at FreeBSD.org
          Reporter: ankohuu at outlook.com

According to the POSIX standard,symbolic links can always be read, except that
the value of the file mode bits returned in the st_mode field of the stat
structure is unspecified.

Linux implemented like this: stat() always returns st_mode 0777 for almost
symbolic link files, but on FreeBSD returns its own real permission.
Some linux programs do obtain the symbol link file permissions in proc/sys and
check whether it is equal to 777, so I think maybe linux_stat return 0777
better at this time.

BTW. 
I found two exceptions on Linux, I don’t know if there are any other
exceptions.

1. lr-x------ /proc/xxx/fd/yyy
If file is open for reading, mode is S_IRUSR | S_IXUSR.
If file is open for writing, mode is S_IWUSR | S_IXUSR.
linux code 5.7-rc1:                                                            
                  static void tid_fd_update_inode(struct task_struct *task,
struct inode *inode,   
                fmode_t f_mode)                                                 
{                                                                               
    task_dump_owner(task, 0, &inode->i_uid, &inode->i_gid);                     

    if (S_ISLNK(inode->i_mode)) {                                               
        unsigned i_mode = S_IFLNK;                                              
        if (f_mode & FMODE_READ)                                                
            i_mode |= S_IRUSR | S_IXUSR;                                        
        if (f_mode & FMODE_WRITE)                                               
            i_mode |= S_IWUSR | S_IXUSR;                                        
        inode->i_mode = i_mode;                                                 
    }                                                                           
    security_task_to_inode(task, inode);                                        
}                                                                               
In this case, we let fdescfs handle it.

2. lr-------- /proc/aaa/map_files/bbb-ccc
If file is open for reading, mode is S_IRUSR.
If file is open for writing, mode is S_IWUSR.
linux code 5.7-rc1:                                                             
static struct dentry *                                                          
proc_map_files_instantiate(struct dentry *dentry,                               
               struct task_struct *task, const void *ptr)                       
{                                                                               
    fmode_t mode = (fmode_t)(unsigned long)ptr;                                 
    struct proc_inode *ei;                                                      
    struct inode *inode;                                                        

    inode = proc_pid_make_inode(dentry->d_sb, task, S_IFLNK |                   
                    ((mode & FMODE_READ ) ? S_IRUSR : 0) |                      
                    ((mode & FMODE_WRITE) ? S_IWUSR : 0));                      
    if (!inode)                                                                 
        return ERR_PTR(-ENOENT);                                                

    ei = PROC_I(inode);                                                         
    ei->op.proc_get_link = map_files_get_link;                                  

    inode->i_op = &proc_map_files_link_inode_operations;                        
    inode->i_size = 64;                                                         

    d_set_d_op(dentry, &tid_map_files_dentry_operations);                       
    return d_splice_alias(inode, dentry);                                       
}                                                                               
In this case, we don't have such files and just skip.

-- 
You are receiving this mail because:
You are the assignee for the bug.


More information about the freebsd-bugs mailing list