評論建議看看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 –