评论建议看看proc_fd_link,这是一个好主意。如果您无法遵循代码如何到达那里,您可以使用systemtap来帮助自己。这是一个神奇的脚本:
probe kernel.function("proc_fd_link") {
print_backtrace();
}
运行它,而从下FD打开文件/给出:
0xffffffffbb2cad70 : proc_fd_link+0x0/0xd0 [kernel]
0xffffffffbb2c4c3b : proc_pid_get_link+0x6b/0x90 [kernel] (inexact)
0xffffffffbb36341a : security_inode_follow_link+0x4a/0x70 [kernel] (inexact)
0xffffffffbb25bf13 : trailing_symlink+0x1e3/0x220 [kernel] (inexact)
0xffffffffbb25f559 : path_openat+0xe9/0x1380 [kernel] (inexact)
0xffffffffbb261af1 : do_filp_open+0x91/0x100 [kernel] (inexact)
0xffffffffbb26fd8f : __alloc_fd+0x3f/0x170 [kernel] (inexact)
0xffffffffbb24f280 : do_sys_open+0x130/0x220 [kernel] (inexact)
0xffffffffbb24f38e : sys_open+0x1e/0x20 [kernel] (inexact)
0xffffffffbb003c57 : do_syscall_64+0x67/0x160 [kernel] (inexact)
0xffffffffbb8039e1 : return_from_SYSCALL_64+0x0/0x6a [kernel] (inexact)
在proc_pid_get_link我们看到:
/* Are we allowed to snoop on the tasks file descriptors? */
if (!proc_fd_access_allowed(inode))
goto out;
aaaand
/* permission checks */
static int proc_fd_access_allowed(struct inode *inode)
{
struct task_struct *task;
int allowed = 0;
/* Allow access to a task's file descriptors if it is us or we
* may use ptrace attach to the process and find out that
* information.
*/
task = get_proc_task(inode);
if (task) {
allowed = ptrace_may_access(task, PTRACE_MODE_READ_FSCREDS);
put_task_struct(task);
}
return allowed;
}
显然,你需要相同的权限,就像你使用ptrace一样。
最后,为什么打开套接字失败? strace显示ENXIO正在退回。 。快速的git的grep ENXIO FS/* C揭示:
static int no_open(struct inode *inode, struct file *file)
{
return -ENXIO;
}
检查代码的最终使用no_open就留给读者自己练习。还要注意systemtap可以用于printf式的调试,而不需要修改源代码。它也可以放在函数的“返回”上并报告错误代码。
有趣的问题。这似乎是[proc_fd_link](http://elixir.free-electrons.com/linux/v4.12.1/source/fs/proc/fd.c#L138)中发生的奇迹,用于得到'/ proc/self/fd/NUM'是一个链接。它只是从打开的文件表中复制'struct path *'(dentry,基本上)。这留给任何创建原始'struct path'来实现打开dentry的inode的功能,在这种情况下[open_fifo](http://elixir.free-electrons.com/linux/v4.12.1/source/fs /pipe.c#L883)来自'fs/pipe.c'。另外TIL:Linux有一个“管道”,所有的管道都在这里:O –