Linux内核中能否从系统调用传入的fd获取文件名?
从系统调用传入的fd获取对应文件名(Linux 5.10.0-rc5 arm64)
在Linux内核中,确实可以通过用户态系统调用传入的fd获取对应的文件名,但这个过程存在关键限制,且需要遵循内核安全规范。以下是具体实现思路和注意事项:
核心实现步骤
通过fd获取
struct file实例
从当前进程的文件描述符表中,利用内核函数fget()通过fd定位到对应的文件结构体:struct file *file = fget(fd); if (!file) { // 处理fd无效的情况,比如返回-EBADF错误 return -EBADF; }注意:使用完毕后必须调用
fput(file)释放引用,避免内存泄漏。提取路径相关结构体
struct file中的f_path成员包含struct path对象,其中dentry指向目录项结构体,mnt指向挂载点结构体:struct path *path = &file->f_path; struct dentry *dentry = path->dentry; struct vfsmount *mnt = path->mnt;拼接生成可读路径
使用内核提供的d_path()函数,将struct path转换为用户可读的路径字符串。需要先通过__getname()分配临时内核缓冲区:char *buf = __getname(); if (!buf) { fput(file); return -ENOMEM; } const char *filename = d_path(path, buf, PATH_MAX); // 此时filename指向拼接完成的路径字符串注意:使用完缓冲区后要调用
__putname(buf)释放;d_path()可能返回相对路径,若需绝对路径需额外处理。
关键限制说明
- 非真实文件的fd无法获取有效文件名:如果fd指向管道、socket、匿名inode(如tmpfs中的匿名文件)等特殊对象,
d_path()会返回[pipe]、[socket]这类占位符,无法得到真实文件名。 - 权限与上下文约束:
fget()已隐含权限检查,但跨进程操作fd时需额外验证;必须确保操作处于合法进程上下文。 - 路径的时效性:文件可能在获取路径后被重命名或删除,得到的路径仅代表当前时刻状态,不保证后续有效。
在do_el0_svc中的注意点
在do_el0_svc(struct pt_regs *regs)中读取x0寄存器的fd后,可直接执行上述操作,但需注意:
- 禁止直接访问用户态内存,所有字符串操作必须使用内核安全函数。
- 避免在该函数中执行耗时操作,防止拖慢系统调用的执行效率。
内容的提问来源于stack exchange,提问作者Chan Kim
相关产品推荐
相关产品推荐

