问答

Linux内核中的代码在哪里打开(“/ proc / self / fd / NUM”)?

 来源    2019-06-27    48  

我一直认为开放(/ proc / self / fd / NUM,flags)相当于dup(NUM),但显然情况并非如此!例如,如果您复制文件描述符,然后将新fd设置为非阻塞,这也会影响原始文件描述符(因为非阻塞状态是文件描述的属性,并且两个文件描述符都指向相同的文件描述).但是,如果您打开/ proc / self / fd / NUM,那么您似乎获得了一个新的独立文件描述,并且可以独立设置旧的和新的fds的非阻塞状态.您甚至可以使用它来获取引用相同匿名管道的两个文件描述,否则这是不可能的(example).另一方面,虽然您可以复制套接字fd,但如果NUM引用套接字,则open(“/ proc / self / fd / NUM”,flags)将失败.

现在我希望能够看到这对于其他类型的特殊文件是如何工作的,并回答诸如“以这种方式重新打开文件时进行了哪些权限检查?”这样的问题,所以我试图找到代码Linux实际上实现了这条路径,但是当我开始阅读fs / proc / fd.c时,我很快迷失在一个错误的操作结构迷宫中,各种各样.

所以我的问题是:任何人都可以解释开放后的代码路径(“/ proc / self / fd / NUM”,flags)吗?具体来说,NUM表示一个管道,我们正在讨论最新的内核版本.

评论建议看看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的调试,无需修改源代码.它也可以从函数“返回”并报告错误代码.

相关文章
我在linux内核中发现了一些奇怪的代码,可以有人解释一下吗?
问答我发现这在initramfs.c,我没有看到这个语法之前,可以有人解释它在做什么? static __initdata int (*actions[])(void) = { [Start] = do_ ...
为什么linux内核中的这段代码不会导致死循环?
问答我正在阅读关于启动时页表初始化的linux源代码(4.4.45,但在其他版本中应该是相同的),下面的代码让我很困惑. 具体来说,我正在阅读有关early_level4_pgt如何初始化的内容.这是x8 ...
linux内核 – 设备驱动程序代码在哪里执行?内核空间还是用户空间?
问答第1部分: 对于linux / unix专家来说,请帮助我了解设备驱动程序.据我所知,驱动程序是直接与硬件交互的代码,并且暴露了一些apis来访问设备.我的问题是这段代码在哪里运行,用户空间或内核空间 ...
linux – 内核中的打印输出在哪里?
问答我正在调试一个linux驱动程序(特别是ubuntu server 9.04),代码中有几个printf语句. 在哪里可以查看这些语句的输出? EDIT1:我想要做的是使用proc文件系统写入内核. ...
如何在linux内核中选择“sys”和“proc”文件
问答据我所知, 在Linux文件系统中,为了用户空间和内核空间之间的信息通信,使用两种虚拟文件系统. 1)Proc文件系统 http://www.tldp.org/LDP/Linux-Filesystem ...
linux内核中的系统调用表在哪里?
问答我正在阅读Robert Love的Linux内核开发,他所做的一项练习是创建一个系统调用(第106页).问题是我无法在v3.9中找到x86_32体系结构的系统调用表文件.我知道他正在使用2.6.xx版 ...
linux内核 – 哪个C版本在Linux内核中使用?
问答Linux内核是否仅使用旧的C90语法,或者是否通过C99 / C11功能进行了优化? 我想知道是否在可能的情况下使用C的最新版本.::Linux kernel coding style文件并没有说明 ...
在Linux内核中添加一个新的系统调用3.3
问答我对这个内核的东西很新.我想做的只是添加一个新的系统调用到内核.我遵循这个准则:http://hekimian-williams.com/?p=20. 问题是在arch / x86 / kernel下 ...
如何在Linux内核中打印当前的线程堆栈跟踪?
问答我希望能够在Linux内核中打印线程的堆栈跟踪. 详细信息:我想将代码添加到特定函数(例如swap_writepage()),这些函数将打印调用此函数的线程的完整堆栈跟踪.像这样的东西: int sw ...
从Linux内核中的路径获取inode
问答我目前正在尝试在内核函数中获取给定路径名的inode.我所有的都是完整的路径名.我尝试过这样的尝试: user_path_at(AT_FDCWD, buffer, LOOKUP_FOLLOW, &am ...
Linux内核中的模块间通信
问答我有两个Linux内核模块,其中一个可以为另一个提供一些功能.但是使用该功能并不重要,即使第一个模块不存在,第二个模块也可能(并且应该)工作. 如果我只是从第一个模块导出函数并在第二个模块中使用它,则 ...
linux内核 – 测试linux内核中函数的执行时间
问答我使用Linux安全模块挂钩来添加一些自定义功能到recv()系统调用.与原始的recv()相比,我想测量这个功能的开销.我写了一个简单的tcp服务器,我运行与没有我的模块.这个tcp服务器调用rec ...
内存管理 – 在Linux内核中的Slab和Slub Allocator之间选择什么?
问答有什么因素有助于决定内存分配器在Linux内核的选择? 在当前的Linux内核中,我们可以选择SLAB,SLUB或SLOB.我已经读过,SLOB用于较小的脚印的内核.但我想知道有助于在Slab All ...
linux-kernel – gpiod_ * vs Linux内核中的gpio_ *方法
问答Linux设备驱动程序编程中的哪个GPIO API更受欢迎,在什么条件下:gpio_set_value()或gpiod_set_value()? 一个采用GPIO desc作为对象,而另一个采用从设备 ...
Linux内核中的主要页面错误处理程序
问答我想知道主要的页面错误处理程序在哪里. 我写了一个算法来最小化内核中的页面错误.因此,每当发生页面错误时我都需要记录一些内容.我目前在arch / x86 / mm / fault_32.c中的do_ ...
错误处理 – linux内核中的系统调用错误处理
问答我正在linux内核中编写一个新的系统调用.我想实现一个错误处理系统,以便向使用sycall的用户返回一个描述错误类型的代码.我想知道在内核中是如何完成的,因为我想遵循标准.我想让用户读取errno变 ...
进程 – Linux 2.6内核中是否需要thread_info结构?
问答在Linux 2.6内核之前,struct task_struct存在于每个进程的内核堆栈的末尾.没有thread_info结构概念.但是在Linux 2.6内核中,而不是将task_struct放置 ...
linux-kernel – 在linux内核中返回错误代码
问答我试图了解Linux系统调用如何返回错误代码.我碰到了times()系统调用.这个简单的系统调用将一些数据复制到用户空间,如果该操作不成功,则返回-EFAULT: SYSCALL_DEFINE1(ti ...
memory-management – 用于处理linux内核中TLB未命中的调用图
问答我试图了解linux内核如何处理TLB未命中.具体来说,我知道页表行走发生在mm / memory.c中的follow_page中,但是当发生TLB未命中时如何调用follow_page. follo ...