何时(以及如何)在内核空间中做出文件权限/访问决策?

何时(以及如何)在内核空间中做出文件权限/访问决策?

(我认为)我对 Linux 权限的工作原理有相对较好的理解 - 传统的 Unix DAC 权限及其表示方式、与进程相关的安全上下文(即 cred 结构、功能等)、LSM 的挂钩等.,以及它们与 (E)UID/E(GID) 等的链接。我不明白,并且很难在内核代码中找到,并且使用ftrace(通过trace-cmd),是这些检查实际完成的时间(大概)在内核空间中,并且在哪一点访问决策实际上已做出。

详细说明:

我有一个 root 拥有的目录/dirchmod-ed 到r-x------500)。作为非特权用户,我运行/bin/ls /dir并收到权限被拒绝的错误,正如预期的那样。

如果我运行,strace -s 10000 /bin/ls /dir我可以看到open系统调用,它返回-1用户空间,并设置errnoEACCES(即“权限被拒绝”)。然后有一个后续的write系统调用将错误消息打印到 STDERR,一切都按预期进行。我在这里从来没有看到getdentsgetdents64调用过系统调用。

如果我使用trace-cmd运行相同的测试,就像在单独的终端选项卡中trace-cmd record -p function_graph -F /bin/ls执行相同的非特权用户一样(将在执行二进制文件时触发),我基本上可以映射我看到的大多数系统调用,一 -一对一,strace 和trace-cmd 输出之间。/bin/ls /dirtrace-cmdls

然而,差异在于,在open系统调用后的trace-cmd输出中,我不是看到写入输出及其退出,而是看到getdents正在进行的调用(以及迭代目录中的项目的完整调用树等)。 。我想,由于 ftrace 的限制(以及我理解中更可能的限制),我没有在输出中看到系统调用参数或返回,所以我看不到何时(如果有的话)我收到权限错误,但根据我有限的理解,内核似乎实际上正在执行完整的目录列表,但只是不将输出返回到用户空间。

那么任何人都可以解释实际发生的情况 - 为什么trace-cmd显示内核实际上正在执行getdents系统调用,而strace在 open 调用失败后退出?大多数论坛帖子(在这里和其他地方)都涉及与权限相关的问题,建议在打开文件时进行检查,但提供的细节不多,尽管这与我所看到的一致strace(但不是ftrace/ trace-cmd)。

查看内核源代码,然后从open/openat系统调用手动进行跟踪,我可以看到函数调用序列,例如inode_permission -> do_inode_permission -> generic_permission -> acl_permission_check后者实际上对经典 Unix 权限进行比较,并从中返回。我还可以在其他地方看到 LSM 的钩子,例如 SELinux、Apparmor、SMACK、Tomoyo 等,我想它们会发挥作用。

我的假设是尝试打开目录,将进行权限检查,内核说不,并将错误返回到用户空间,并且它永远不会达到实际执行目录列表的程度。但是,根据trace-cmd输出似乎实际显示目录列表正在发生,我不再确定。

任何信息 - 尽可能多的技术深度 - 将不胜感激。另外,我知道使用 Systemtap 可能可以为我提供更多信息,但我对此的了解是非常有限的!

为了提高认识,我在基于 Debian 的发行版上的内核版本 2.6.35 和 6.5.0 上进行了测试,结果相对相似。

答案1

用户错误和缺乏对trace-cmd(特别是-F我正在使用的标志)的理解是问题所在。

我的假设是,在 running 中trace-cmd record -p function_graph -F /bin/lstrace-cmd会等到看到“ls”进程正在执行,然后挂钩它。事实证明,这-F只会导致二进制文件在那里然后运行(作为 root,给定trace-cmd将以 root 身份运行)。 Hacky 的解决方法是确保我附加到一个进程(一些丑陋的 C 会休眠几秒钟,同时我获取进程的 PID,然后让该进程ls以用户身份执行)。这样做的时候,一切都在预料之中。我能够确认我原来的理解是正确的。

作为参考,权限检查是在打开文件时完成的,遵循open系统调用的函数调用链。一些代码最初分配一个空文件描述,并开始填充该结构的位。实际的权限检查似乎发生在接近调用链末端的地方。如果它是目录对象,则有一些专用代码用于检查执行权限,这是有道理的,因为该位具有不同的行为。然后调用一个may_open函数,该函数又调用inode_permission,该函数generic_permission调用执行基本的 DAC 检查。这里也有 LSM 检查。如果这些失败,则会返回权限错误,正如人们所期望的那样。

相关内容