linux文件访问权限代码,Linux内核源代码情景分析-访问权限与文件安全性

在Linux内核源代码情景分析-从路径名到目标节点,一文中path_walk代码中,err = permission(inode, MAY_EXEC)当前进程是否可以访问这个节点,代码如下:

int permission(struct inode * inode,int mask)

{

if (inode->i_op && inode->i_op->permission) {

int retval;

lock_kernel();

retval = inode->i_op->permission(inode, mask);

unlock_kernel();

return retval;

}

return vfs_permission(inode, mask);

}    在ext2_read_inode中,i_op可以设置为ext2_file_inode_operations,ext2_dir_inode_operations,ext2_fast_symlink_inode_operations,page_symlink_inode_operations,均没有permission指针。所以执行vfs_permission,代码如下:

int vfs_permission(struct inode * inode,int mask)

{

int mode = inode->i_mode;

if ((mask & S_IWOTH) && IS_RDONLY(inode) &&

(S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)))

return -EROFS; //如果要求的写文件,并且是只读系统,而且是常规文件,目录,或者链接时,返回-EROFS,表示不能访问

if ((mask & S_IWOTH) && IS_IMMUTABLE(inode)) //Nobody gets write access to an immutable file

return -EACCES;

if (current->fsuid == inode->i_uid)//如果当前进程的fsuid和inode结构的i_uid相等,那么应该比较mode中S_IRUSR、S_IWUSR、S_IXUSR位

mode >>= 6;

else if (in_group_p(inode->i_gid))//如果当前进程的fsgid和inode结构的i_gid相等,那么应该比较mode中S_IRGRP、S_IWGRP、S_IXGRP位

mode >>= 3;

if (((mode & mask & S_IRWXO) == mask) || capable(CAP_DAC_OVERRIDE))//mask相当于要求,mode是现有的当前用户可以访问的权限,如果相等就返回0。假如不相等,如果当前进程得到了授权,允许其CAP_DAC_OVERRIDE,即可以凌驾于文件系统的访问权限控制机制DAC之上。

return 0;

/* read and search access */

if ((mask == S_IROTH) ||

(S_ISDIR(inode->i_mode) && !(mask & ~(S_IROTH | S_IXOTH))))

if (capable(CAP_DAC_READ_SEARCH))

return 0;

return -EACCES;

}

其中mask为:

#define MAY_EXEC 1

#define MAY_WRITE 2

#define MAY_READ 4    inode->i_mode为:

用于对三种不同用户的访问权限:

#define S_IRWXU 00700

#define S_IRUSR 00400

#define S_IWUSR 00200

#define S_IXUSR 00100

#define S_IRWXG 00070

#define S_IRGRP 00040

#define S_IWGRP 00020

#define S_IXGRP 00010

#define S_IRWXO 00007

#define S_IROTH 00004

#define S_IWOTH 00002

#define S_IXOTH 00001

参考这张图就好理解了。

MMKlOcNzxOU4f8B34kyC5qfS70AAAAASUVORK5CYII=

还有三个标志位,是一个状态占一个位:

#define S_ISUID 0004000

#define S_ISGID 0002000

#define S_ISVTX 0001000    现在16位只剩下4位了,表示文件类型,要为每种文件类型都分配一个标志位就不够了,所以表示文件的类型的这4位是编码的。

#define S_IFMT 00170000

#define S_IFSOCK 0140000

#define S_IFLNK 0120000

#define S_IFREG 0100000

#define S_IFBLK 0060000

#define S_IFDIR 0040000

#define S_IFCHR 0020000

#define S_IFIFO 0010000

capable,代码如下:

static inline int capable(int cap)

{

#if 1 /* ok now */

if (cap_raised(current->cap_effective, cap))

#else

if (cap_is_fs_cap(cap) ? current->fsuid == 0 : current->euid == 0)

#endif

{

current->flags |= PF_SUPERPRIV;

return 1;

}

return 0;

}#define cap_raised(c, flag) (cap_t(c) & CAP_TO_MASK(flag))#define cap_t(x) (x)#define CAP_TO_MASK(x) (1 << (x))

current->cap_effective是在sys_execve->do_execve->prepare_binprm初始设置的。

int prepare_binprm(struct linux_binprm *bprm)

{

int mode;

struct inode * inode = bprm->file->f_dentry->d_inode;

mode = inode->i_mode;

/* Huh? We had already checked for MAY_EXEC, WTF do we check this? */

if (!(mode & 0111))/* with at least _one_ execute bit set */

return -EACCES;

if (bprm->file->f_op == NULL)

return -EACCES;

bprm->e_uid = current->euid;

bprm->e_gid = current->egid;

if(!IS_NOSUID(inode)) {

/* Set-uid? */

if (mode & S_ISUID)

bprm->e_uid = inode->i_uid;

/* Set-gid? */

/*

* If setgid is set but no group execute bit then this

* is a candidate for mandatory locking, not a setgid

* executable.

*/

if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP))

bprm->e_gid = inode->i_gid;

}

/* We don‘t have VFS support for capabilities yet */

cap_clear(bprm->cap_inheritable);

cap_clear(bprm->cap_permitted);

cap_clear(bprm->cap_effective);

/* To support inheritance of root-permissions and suid-root

* executables under compatibility mode, we raise all three

* capability sets for the file.

*

* If only the real uid is 0, we only raise the inheritable

* and permitted sets of the executable file.

*/

if (!issecure(SECURE_NOROOT)) {

if (bprm->e_uid == 0 || current->uid == 0) {

cap_set_full(bprm->cap_inheritable);

cap_set_full(bprm->cap_permitted);

}

if (bprm->e_uid == 0)

cap_set_full(bprm->cap_effective);//这里设置的

}

memset(bprm->buf,0,BINPRM_BUF_SIZE);

return kernel_read(bprm->file,0,bprm->buf,BINPRM_BUF_SIZE);

}

原文:http://blog.csdn.net/jltxgcy/article/details/44831699

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值