1

I am interested in /proc/sys and trying to understand the access control mechanism of files in this directory.
I am not sure if accessing /proc/sys is the same as accessing on-disk file systems, like ext4. So I just started with the open system call and tried to trace critical kernel functions called among the process.
And found that it first called do_sys_open(), which called do_filp_open() internally. In do_filp_open(), some path name resolution is done at first and then it called may_open() to do some permission checks, and finally vfs_open() is called to do the specific open function according to the file system.
From reading the source code, I suppose the permission check work is indeed done by generic_permission() which located in /fs/namei.c. The whole function looks like this:

int generic_permission(struct inode *inode, int mask)
{
    int ret;

    /*
     * Do the basic permission checks.
     */
    ret = acl_permission_check(inode, mask);
    if (ret != -EACCES)
        return ret;

    if (S_ISDIR(inode->i_mode)) {
        /* DACs are overridable for directories */
        if (capable_wrt_inode_uidgid(inode, CAP_DAC_OVERRIDE))
            return 0;
        if (!(mask & MAY_WRITE))
            if (capable_wrt_inode_uidgid(inode,
                             CAP_DAC_READ_SEARCH))
                return 0;
        return -EACCES;
    }
    /*
     * Read/write DACs are always overridable.
     * Executable DACs are overridable when there is
     * at least one exec bit set.
     */
    if (!(mask & MAY_EXEC) || (inode->i_mode & S_IXUGO))
        if (capable_wrt_inode_uidgid(inode, CAP_DAC_OVERRIDE))
            return 0;

    /*
     * Searching includes executable on directories, else just read.
     */
    mask &= MAY_READ | MAY_WRITE | MAY_EXEC;
    if (mask == MAY_READ)
        if (capable_wrt_inode_uidgid(inode, CAP_DAC_READ_SEARCH))
            return 0;

    return -EACCES;
}

So, it seems like UGO check comes at first, if UGO failed kernel will check if you have special Capability. But this process is not consistent with the experiment result I saw when I tried access files under /proc/sys.
Take /proc/sys/kernel/usermodehelper/bset as an example:

$ ll /proc/sys/kernel/usermodehelper/bset
-rw------- 1 root root 0 Nov  6 12:15 /proc/sys/kernel/usermodehelper/bset

This file is owned by root and can’t be read from others. From the logic in generic_permission(), non-root could read this file if he has CAP_DAC_OVERRIDE. So I give /bin/cat CAP_DAC_OVERRIDE, but got an “Permission denied” and still cannot read the file.
However, I could read /etc/shadow after grand CAP_DAC_OVERRIDE to cat, which is also a root file and can't be read by a normal user.
Why did this happen?What is the permission check process like when accessing files under /proc/sys? Doesn’t it go through generic_permission()? Is there some other check in kernel when accessing /proc/sys?

JJ Meng
  • 11
  • 2
  • 1
    I used ftrace to trace the kernel functions called when I tried to open /proc/sys/kernel/usermodehelper/bset, and I may have a clue now. The truth is when I tried open bset, generic_permission() is not called, the inode_operations->permission() of /proc/sys is called instead. And the logic of proc_sys_permission() doesn’t look at CAP_DAC_OVERRIDE, it only care about the access mode of the file. So actually I was blocked by UGO check. – JJ Meng Nov 07 '20 at 01:42
  • I have same issue with accessing files in /proc. Setting CAP_DAC_OVERRIDE is just not enough. I wonder if it is feature Linux kernel or is it bug? – JiriHnidek Oct 06 '21 at 09:32
  • @JiriHnidek I think it is a special implementation method is used under /proc, which is not a bug. As we can see from the source code, CAP_DAC_OVERRRIDE can be used to bypass files that use generic_permission() for permission checks. But profs is a virtual file system. It mainly abstracts the information of the kernel and processes and displays it to users in the form of files. Some 'files' under proc do not use generic_permission but use other permission check functions, which cannot be bypassed by CAP_DAC_OVERRIDE. – JJ Meng Oct 08 '21 at 10:45
  • Yeah, it looks like that it is feature. It is necessary to have special capabilities to access some files in /proc like CAP_SYS_RAWIO. Unfortunately there is only few capabilities that are related /proc. It limits usage of capabilities in some cases and it IMHO enforce you to use approach, when you use 0 EUID anyway and you only limit capabilities of such process. – JiriHnidek Oct 29 '21 at 20:32

0 Answers0