JJ Meng
JJ Meng

Reputation: 11

What permission check happened in kernel when accessing files in /proc/sys?

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?

Upvotes: 1

Views: 928

Answers (0)

Related Questions