linux内核权限控制之vfs_permission分析
2016-03-06 09:03
363 查看
在linux文件系统的各种操作里,很重要的一个东西就是权限控制,我们来一起追溯内核源代码,弄清楚内核的权限之谜。
在VFS(linux虚拟文件系统)里,权限控制都是通过vfs_permission来实现的,我们从vfs_permission来看,vfs_permission函数定义在fs/namei.c,定义如下
vfs_permission函数直接调用了permission函数,我们进入permission函数看看。permission函数定义在fs/namei.c,定义如下
接下来进入generic_permission函数看一看通用的权限检查函数的实现。generic_permission函数定义在fs/namei.c,定义如下
在VFS(linux虚拟文件系统)里,权限控制都是通过vfs_permission来实现的,我们从vfs_permission来看,vfs_permission函数定义在fs/namei.c,定义如下
int vfs_permission(struct nameidata *nd, int mask) { return permission(nd->dentry->d_inode, mask, nd); }
vfs_permission函数直接调用了permission函数,我们进入permission函数看看。permission函数定义在fs/namei.c,定义如下
int permission(struct inode *inode, int mask, struct nameidata *nd) { /*得到文件的权限*/ umode_t mode = inode->i_mode; int retval, submask; if (mask & MAY_WRITE) { /*只读文件系统不可以写入*/ if (IS_RDONLY(inode) && (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))) return -EROFS; /*不可修改文件不能写*/ if (IS_IMMUTABLE(inode)) return -EACCES; } /*对于普通文件的MAY_EXEC需要可执行权限,如果文件系统不可以执行,就返回错误*/ if ((mask & MAY_EXEC) && S_ISREG(mode) && (!(mode & S_IXUGO) || (nd && nd->mnt && (nd->mnt->mnt_flags & MNT_NOEXEC)))) return -EACCES; /* 一般的权限程序不理解MAY_APPEND*/ submask = mask & ~MAY_APPEND; /*如果inode的函数操作结构体有permission函数,就调用这个函数*/ if (inode->i_op && inode->i_op->permission) retval = inode->i_op->permission(inode, submask, nd); else /*否则就调用通用的权限检查函数*/ retval = generic_permission(inode, submask, NULL); if (retval) return retval; /*安全操作,最后决定是否有权限,调用内核自己注册的security_ops结构体的函数,新的内核特性*/ return security_inode_permission(inode, mask, nd); }
接下来进入generic_permission函数看一看通用的权限检查函数的实现。generic_permission函数定义在fs/namei.c,定义如下
/** * generic_permission - 在POSIX系列操作系统检察权限 * @inode: 检察权限需要的inode * @mask: 权限检查(%MAY_READ, %MAY_WRITE, %MAY_EXEC) * @check_acl: 回调函数,我们传入的是NULL,不必考虑 */ 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; } /*如果对于组ID检查成功,就右移三位*/ if (in_group_p(inode->i_gid)) mode >>= 3; } /*自主控制位检查*/ if (((mode & mask & (MAY_READ|MAY_WRITE|MAY_EXEC)) == mask)) return 0; check_capabilities: /*DAC权限检查*/ 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; }
相关文章推荐
- Linux Kernel 4.0 RC5 发布!
- Linux 自检和 SystemTap
- 一张图看尽 Linux 内核运行原理
- Linux C函数参考手册(PDF版)
- C# partial关键字说明
- Lua教程(十七):C API简介
- 简单谈谈lua和c的交互
- C#实现打造气泡屏幕保护效果
- 举例讲解C#编程中委托的实例化使用
- 使用C#代码获取存储过程返回值
- C/C++数据对齐详细解析
- 利用C语言来求最大连续子序列乘积的方法
- 字符串的组合算法问题的C语言实现攻略
- C 语言基础教程(我的C之旅开始了)[三]
- 学习C和C++的9点经验总结
- C++中的extern “C”用法详解
- C 语言基础教程(我的C之旅开始了)[七]
- 最大子矩阵问题实例解析
- C字符串操作函数实现方法小结