sys_read实现过程
-
sys_read interface
asmlinkage long sys_read(unsigned int fd, char __user *buf, size_t count);
-
read - implement
SYSCALL_DEFINE3(read, unsigned int, fd, char __user *, buf, size_t, count) { /* 1. 文件描述符 struct fd { struct file *file; unsigned int flags; }; */ struct fd f = fdget_pos(fd); //通过文件描述符,获取fd结构体 ssize_t ret = -EBADF; //ssize_t -> long if (f.file) { //loff_t -> long long loff_t pos = file_pos_read(f.file); // 读取文件的偏移量 ret = vfs_read(f.file, buf, count, &pos); //在@file的@pos位置,写入@count个@buf中的字符, if (ret >= 0) file_pos_write(f.file, pos); fdput_pos(f); } return ret; }
-
vfs_read
ssize_t vfs_read(struct file *file, char __user *buf, size_t count, loff_t *pos) { ssize_t ret; //前两个if做一些file的权限检查 if (!(file->f_mode & FMODE_READ)) return -EBADF; if (!(file->f_mode & FMODE_CAN_READ)) return -EINVAL; //检查buff是否合法 if (unlikely(!access_ok(VERIFY_WRITE, buf, count))) return -EFAULT; //检查文件是否相关的权限,hook函数在里面 ret = rw_verify_area(READ, file, pos, count); if (!ret) { //检查写入长度 if (count > MAX_RW_COUNT) count = MAX_RW_COUNT; //写入数据,以及相关的属性的变化 ret = __vfs_read(file, buf, count, pos); if (ret > 0) { fsnotify_access(file); add_rchar(current, ret); } inc_syscr(current); } return ret; }
-
rw_verify_area
int rw_verify_area(int read_write, struct file *file, const loff_t *ppos, size_t count) { struct inode *inode; loff_t pos; int retval = -EINVAL; //get file's inode inode = file_inode(file); //check inode size if (unlikely((ssize_t) count < 0)) return retval; pos = *ppos; //check file offset if (unlikely(pos < 0)) { if (!unsigned_offsets(file)) return retval; if (count >= -pos) /* both values are in 0..LLONG_MAX */ return -EOVERFLOW; } else if (unlikely((loff_t) (pos + count) < 0)) { if (!unsigned_offsets(file)) return retval; } //check current pos's lock if (unlikely(inode->i_flctx && mandatory_lock(inode))) { retval = locks_mandatory_area(inode, file, pos, pos + count - 1, read_write == READ ? F_RDLCK : F_WRLCK); if (retval < 0) return retval; } //lsm relevant hook function return file_permission(file, read_write == READ ? MAY_READ : MAY_WRITE); }
分析Hook函数
-
函数原型
int file_permission(struct file *file, int mask);
-
执行流程
- 当Linux传统的DAC检查完以后,会检查LSM hook中定义了的检查函数