内核中打开只读文件前,如何预先检查其读权限?
内核态文件读权限前置检查的正确姿势
你之前用fileptr->f_op->read来判断权限的思路走偏啦——这个指针是用来判断文件是否支持读操作(比如目录的文件操作结构体里就没有read函数),和当前进程有没有读这个文件的权限完全是两码事,所以才会总是执行失败。咱们换个正确的方式来做前置权限检查:
核心方法:用内核提供的权限检查函数
内核里有专门的API可以在打开文件前验证权限,步骤大概分三步:
1. 先解析文件路径获取inode
用kern_path()把用户空间的文件路径转换成内核态的struct path,通过它就能拿到文件的inode(inode里存储了文件的权限信息):
struct path path; int ret; // 解析路径,LOOKUP_FOLLOW表示跟随符号链接 ret = kern_path(args->inputfile, LOOKUP_FOLLOW, &path); if (ret != 0) { printk(KERN_ERR "Failed to resolve file path: %d\n", ret); return ret; }
2. 检查读权限
用inode_permission()函数验证当前进程是否有该文件的读权限,传入MAY_READ宏指定要检查的权限:
ret = inode_permission(path.dentry->d_inode, MAY_READ); if (ret != 0) { printk(KERN_ERR "No read permission for file: %d\n", ret); path_put(&path); // 必须释放path资源,避免内存泄漏 return ret; }
3. 权限通过后再打开文件
确认权限没问题,再调用filp_open()以只读模式打开文件:
struct file *fileptr = filp_open(args->inputfile, O_RDONLY, 0); if (IS_ERR(fileptr)) { ret = PTR_ERR(fileptr); printk(KERN_ERR "Failed to open file: %d\n", ret); path_put(&path); return ret; } // 这里可以进行文件读操作... // 用完文件后记得关闭 filp_close(fileptr, NULL); // 最后释放path资源 path_put(&path);
关键注意事项
- 资源释放不能忘:
kern_path()获取的struct path必须用path_put()释放,打开的文件必须用filp_close()关闭,否则会导致内存或文件资源泄漏。 - 权限检查的上下文:
inode_permission()默认用当前进程的凭证(cred)来检查权限,如果需要以特定用户身份检查,可以用inode_permission_cred()并传入对应的cred结构体。 - 路径安全:如果是处理用户传入的路径,要注意防范路径遍历漏洞,必要时可以先用
getname()获取用户空间的路径字符串再处理。
为什么你之前的方法会失败
再强调下:fileptr->f_op->read存在与否,只代表这个文件类型是否支持读操作(比如普通文件、字符设备支持,目录、管道可能不支持),和进程有没有读权限无关。举个例子:一个普通文件如果设置了000权限,f_op->read是存在的,但你依然没有权限读它;反之,一个目录你有读权限,但f_op->read是不存在的。所以用这个判断权限完全不对。
内容的提问来源于stack exchange,提问作者arkham knight
相关产品推荐
相关产品推荐

