Linux权限管理(一)—打开权限

来源:互联网 发布:itools3 for mac 编辑:程序博客网 时间:2024/06/05 00:29

http://tsecer.blog.163.com/blog/static/150181720121159527348/


Linux权限管理(一)—打开权限  

2012-02-15 21:52:46|  分类: Linux内核|字号 订阅

一、打开权限
这里其实比较感兴趣的是文件夹的权限,假设对于root用户的一个文件夹,或者另一个不允许其它用户访问的文件夹,如果用户访问这个路径是否可以访问文件夹下的文件?
简单的模型是这样的
[root@Harry ~]# ll /
drwxr-x--x.   2 root root  4096 2012-02-14 21:32 priotest
[root@Harry ~]# ll /priotest/
total 4
-rwx--xr-x. 1 root root 12 2012-02-14 21:34 tsecer.txt
这里的情况是文件夹/priotest文件夹对其他用户设置的是执行权限而没有打开权限,但是该文件夹下的实体文件却是有读出权限的,那么此时普通用户是否能够读取该文件的内容呢?那么此时普通用户是否可以查看该文件的内容呢?
二、内核实现
我们看一下打开文件内核的目录打开执行的流程中权限的检测为
do_path_lookup
使用的权限判断为
        retval = file_permission(file, MAY_EXEC);
__link_path_walk中判断为
exec_permission_lite(inode, nd)
也就是文件夹打开的权限判断都是使用了文件夹的EXEC权限而不是打开权限。事实上,切换到一个普通用户,然后使用cat命令同样可以查看这个文件的内容:
[tsecer@Harry priotest]$ cat /priotest/tsecer.txt
hello world
tsecer
三、文件夹的打开权限是干什么的
这个输出是我在机器上执行strace命令的一些输出
[tsecer@Harry priotest]$ strace ls /
……
open("/", O_RDONLY|O_NONBLOCK|O_LARGEFILE|O_DIRECTORY|O_CLOEXEC) = 3
fcntl64(3, F_GETFD)                     = 0x1 (flags FD_CLOEXEC)
getdents64(3, /* 26 entries */, 32768)  = 696
getdents64(3, /* 0 entries */, 32768)   = 0
这里可以看到,其中对于根文件夹"/"是直接打开,然后读出目录下的所有文件内容的,所以对于文件夹的读权限和普通文件的读权限是一样的,最后就是文件的读权限判断在open_namei函数的最后,其执行的判断为
error = may_open(nd, acc_mode, flag);
这里判断的就是文件的打开权限判断,此处的判断最终是通过
vfs_permission--->>>permission--->>generic_permission
if (current->fsuid == inode->i_uid) 
        mode >>= 6;对于一个文件的访问权限设置,最高最高3bits为用户所有者权限,所以如果fsud和文件创建者id相同,则逻辑右移6bits
    else {
        if (IS_POSIXACL(inode) && (mode & S_IRWXG) && check_acl) {
            int error = check_acl(inode, mask);
            if (error == -EACCES)
                goto check_capabilities;
            else if (error != -EAGAIN)
                return error;
        }

        if (in_group_p(inode->i_gid)) 如果当前进程和文件在同一用户组中,则右移3bits
            mode >>= 3;
    } 其它的使用的就是mode的最后3bits,作为其它用户的访问权限设置

    /*
     * If the DACs are ok we don't need any capability check.
     */
    if (((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask))这里就是用文件的权限控制列表和对该文件要求的权限判断,如果满足,则返回零,表示进程可以打开该文件
        return 0;
关于这个9bits控制模式,可以看一下chmod命令的说明,这里就不废话了。
这也就是说,如果一个用户对文件夹没有打开权限,那么它不能通过ls来查看该文件夹下文件内容,进一步的一个简单推论就是在bash中,不同通过tab来自动补全文件夹下文件。
四、超级用户如何超越这些判断
超级用户可以绕过这些控制,假设一个极端的情况,一个超级用户自毁长城,将一个自己创建的文件访问属性设置为000,也就是任何人没有任何权限,那么这个文件是不是在系统中就长生不老了?简单测试了一下,不是。超级用户是如何超越这个检测的?
其实同样是在generic_permission函数中实现的,上面的判断并不是文件的全部,而只是一部分,即使上面的
    if (((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask))
  不满足,还有绿色通道,接下来的就是对权限(能力)的判断,这相当于是root用户的后门:
 check_capabilities:
    /*
     * Read/write DACs are always overridable.
     * Executable DACs are overridable if at least one exec bit is set.
     */
    if (!(mask & MAY_EXEC) || 对于文件夹的打开,这里的第一个逻辑或就已经满足,这是通过文件夹权限检测的步骤。
        (inode->i_mode & S_IXUGO) || S_ISDIR(inode->i_mode))
        if (capable(CAP_DAC_OVERRIDE))
            return 0;

    /*
     * Searching includes executable on directories, else just read.
     */
    if (mask == MAY_READ || (S_ISDIR(inode->i_mode) && !(mask & MAY_WRITE)))这里对读权限的超越
        if (capable(CAP_DAC_READ_SEARCH))
            return 0;
对于root用户,这些权限都是满足的:
[root@Harry priotest]# cat /proc/self/status 
Name:    cat
State:    R (running)
……
CapInh:    0000000000000000
CapPrm:    ffffffffffffffff
CapEff:    ffffffffffffffff
CapBnd:    ffffffffffffffff
可以看到,root用户具有所有的权限,其中的capable是使用了其中的CapEff列来判断权限的。
五、open打开权限到ACCESS MODE的转换
这是一个小问题,因为当用户态调用open的时候,如果是要求可读写状态打开一个文件,传入的参数是O_RDWR,但是在内核里搜索了这个字符串,没有发现对这个属性进行判断的地方。借助调试器,才看到这个转换是在一个不起眼并且比较诡异的方式实现的,在
static struct file *do_filp_open(int dfd, const char *filename, int flags,
                 int mode)
    if ((namei_flags+1) & O_ACCMODE)
        namei_flags++;
然后在
int open_namei(int dfd, const char *pathname, int flag,
        int mode, struct nameidata *nd)
    acc_mode = ACC_MODE(flag);
其中
#define ACC_MODE(x) ("\000\004\002\006"[(x)&O_ACCMODE])
#define O_ACCMODE    00000003
假设传入的属性为
#define O_RDWR        00000002
那么它将会在do_filp_open中转换为3,所以在接下来的ACC_MODE转换中转换为006,也就是3bits访问控制权限中的110,所以这个权限就要求文件有读、写(没有要求执行权限)。
六、一个细节
在generic_permission函数中,文件的访问使用的都是进程的fsuid 属性,而一个进程描述符中关于uid,有下面一些定义
    uid_t uid,euid,suid,fsuid;
这些id的具体应用,在之后的描述中将会尝试逐步展开。

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 领导送礼物给我怎么办 南瓜饼和面很稀怎么办 包饺子剩的肉馅怎么办 发好的面团粘手怎么办 富士变频器减速时间过电流怎么办 铺木地板地面不是很平怎么办 眼镜被铁锈烫了怎么办 平车机针头小了怎么办 mk包五金坏了怎么办 迁坟原来的棺材怎么办 新建定额项目没有措施项目怎么办 太岁符忘记烧了怎么办 穿裙子去了寺庙怎么办 美甲彩绘胶干了怎么办 美甲彩绘胶稀怎么办 彩绘胶弄衣服上怎么办 彩绘胶买来太稠怎么办 做指甲没有底胶怎么办 交定金后发现房屋不合法怎么办 买车付了定金不想要了怎么办 买车付定金后不想要怎么办 非法经营的产品至人伤亡怎么办 返修漆施工不对色怎么办 叶子板撞变形了怎么办 挤了三角区疖子怎么办 三角部位太鼓的怎么办 美利车车贷逾期怎么办? 外墙保温层坏了怎么办 双胞胎34周血压高怎么办 夏天穿凉鞋脚后跟干裂起硬皮怎么办 穿凉鞋脚后跟干裂起硬皮怎么办 夏天穿凉鞋磨脚怎么办 lv皮带黑色掉漆怎么办 黑色衣服穿在身上掉色怎么办 电信卡流量超了怎么办 移动卡流量超了怎么办 狗狗老是挠痒痒怎么办 出差同住的同事睡觉打鼾怎么办 小孩皮肤太黑了怎么办 苹果平板突然黑屏打不开怎么办 孩子认人晚上哭怎么办