注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

Tsecer的回音岛

Tsecer的博客

 
 
 

日志

 
 

linux文件夹x权限意义  

2013-11-10 21:43:00|  分类: Linux内核 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |
一、文件夹执行权限
文件夹的执行权限像是一个门的通过权限,如果一个文件夹对用户没有可执行权限,那么玩家无法把这个文件夹作为路径的中间一部分。如果用户对文件夹没有exec权限,但是有read权限,可以通过open来打开文件夹,进而通过readdir来枚举这个文件夹下的所有文件。由于打开这个文件夹时把文件作为一个目的而不是路径中间内容,所以即使没有可执行权限,只要有read权限,就可以open一个文件夹,并read文件夹内容。
二、例子
tsecer@harry:/home/tsecer>ll
total 8
drw-r--r-- 2 tsecer users 4096 Nov 10 21:23 execp
drwxr-xr-x 2 tsecer users 4096 Nov 10 17:54 nomerge
tsecer@harry:/home/tsecer>/bin/ls execp 有read权限,没有x权限,可以枚举出文件夹所有文件,因为execp在路径最后而不是在路径中间
bar.txt  foo.txt
tsecer@harry:/home/tsecer>/bin/ls execp -l 无法执行 ls -l选项,由于stat时需要执行execp/foo.txt,此时execp在路径中间,导致无法通过,整个系统调用失败
/bin/ls: execp/foo.txt: Permission denied
/bin/ls: execp/bar.txt: Permission denied
total 0
既然如此,我们先cd到execp文件夹,然后stat foo.txt文件,此时execp就不出现在路径中间了,此时
tsecer@harry:/home/tsecer>cd execp/
bash: cd: execp/: Permission denied
cd到一个文件夹需要文件夹的可执行权限。
三、路径遍历的link_path_walk函数
__link_path_walk
/* At this point we know we have a real path component. */
    for(;;) {
       unsigned long hash;
        struct qstr this;
        unsigned int c;

        nd->flags |= LOOKUP_CONTINUE;
        err = exec_permission_lite(inode, nd);
        if (err == -EAGAIN)
            err = vfs_permission(nd, MAY_EXEC);
         if (err)
            break;

        this.name = name;
        c = *(const unsigned char *)name;

        hash = init_name_hash();
        do {
            name++;
            hash = partial_name_hash(c, hash);
            c = *(const unsigned char *)name;
        } while (c && (c != '/'));
        this.len = name - (const char *) this.name;
        this.hash = end_name_hash(hash);
……
/* remove trailing slashes? */
        if (!c)
            goto last_component;
        while (*++name == '/');
        if (!*name)
            goto last_with_slashes;从这里可以看到,对于指定路径的最后一个单位,并没有判断该文件夹的任何权限。此时该函数也无法判断,它只是一个查找函数,查找的目的可能是一个文件夹,也可能是文件,所有该函数找到之后返回该文件对应的dentry即可
……
        /* here ends the main loop */

last_with_slashes:
        lookup_flags |= LOOKUP_FOLLOW | LOOKUP_DIRECTORY;
last_component:
        /* Clear LOOKUP_CONTINUE iff it was previously unset */
        nd->flags &= lookup_flags | ~LOOKUP_CONTINUE;
        if (lookup_flags & LOOKUP_PARENT)
            goto lookup_parent;
        if (this.name[0] == '.') switch (this.len) {
            default:
                break;
            case 2:   
                if (this.name[1] != '.')
                    break;
                follow_dotdot(nd);
                inode = nd->dentry->d_inode;
                /* fallthrough */
            case 1:
                goto return_reval;
        }
        if (nd->dentry->d_op && nd->dentry->d_op->d_hash) {
            err = nd->dentry->d_op->d_hash(nd->dentry, &this);
            if (err < 0)
                break;
        }
……
        goto return_base;
}
四、open权限的判断
对文件/文件夹的打开通过
sys_open--->>>do_sys_open--->>do_filp_open-->>open_namei-->>may_open--->>vfs_permission--->.permission-->.generic_permission


/**
 * generic_permission  -  check for access rights on a Posix-like filesystem
 * @inode:    inode to check access rights for
 * @mask:    right to check for (%MAY_READ, %MAY_WRITE, %MAY_EXEC)
 * @check_acl:    optional callback to check for Posix ACLs
 *
 * Used to check for read/write/execute permissions on a file.
 * We use "fsuid" for this, letting us set arbitrary permissions
 * for filesystem access without changing the "normal" uids which
 * are used for other things..
 */
int generic_permission(struct inode *inode, int mask,
        int (*check_acl)(struct inode *inode, int mask))
{
    umode_t            mode = inode->i_mode;

    if (current->fsuid == inode->i_uid)
        mode >>= 6;
    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))
            mode >>= 3;
    }

    /*
     * If the DACs are ok we don't need any capability check.
     */
    if (((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask))
        return 0;

 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;

    return -EACCES;
}
五、chdir判断
asmlinkage long sys_chdir(const char __user * filename)
{
    struct nameidata nd;
    int error;

    error = __user_walk(filename,
                LOOKUP_FOLLOW|LOOKUP_DIRECTORY|LOOKUP_CHDIR, &nd);
    if (error)
        goto out;

    error = vfs_permission(&nd, MAY_EXEC);
    if (error)
        goto dput_and_out;

    set_fs_pwd(current->fs, nd.mnt, nd.dentry);

dput_and_out:
    path_release(&nd);
out:
    return error;
}
  评论这张
 
阅读(616)| 评论(0)
推荐 转载

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017