确保 UID/GID 签入系统调用在 RCU-critical 部分执行

Ensure that UID/GID check in system call is executed in RCU-critical section

任务

我有一个为我的 RaspBerry Pi 2 编写的小内核模块,它实现了一个额外的系统调用来生成功耗指标。我想修改系统调用,使其仅在特殊用户(例如 "root" 或用户 "pi")发出时才被调用。否则,该调用将跳过其大部分 body 和 returns 成功。


背景工作

我已经详细阅读了这个问题,I've found a similar question on SO,但从我的角度来看,它有很多问题(如下所述)。


问题


更新

因此,剩下的唯一有效问题如下:

Note, that iterating through processes and reading process's credentials should be done under RCU-critical section.

链接的问题涉及一个根本不同的问题。引用:

Please note that the uid that I want to get is NOT of the current process.

显然,不是当前正在执行的线程的线程原则上可以随时退出或更改凭据。需要采取措施确保我们摆弄的任何东西的稳定性。 RCU 通常是正确答案。从某种意义上说,还有其他方法,这里提供的答案有些错误。

同时,如果您想对执行代码的线程进行操作,您可以知道它不会退出(因为它正在执行您的代码而不是退出路径)。出现了一个问题,凭证的稳定性如何——好消息,它们也保证存在并且可以在没有任何准备的情况下访问。这可以通过检查执行凭据切换的代码轻松验证。

我们剩下的问题是什么原语可以用来进行访问。为此,可以使用 make_kuid、uid_eq 和类似的原语。

真正的问题是为什么这是一个系统调用而不只是一个 /proc 文件。

有关凭据处理的详细说明,请参阅此博文:http://codingtragedy.blogspot.com/2015/04/weird-stuff-thread-credentials-in-linux.html

首先,添加新的系统调用很少是正确的做法。最好通过现有机制来做事,因为您将受益于双方已经存在的工具:内核中现有的实用程序函数、用户空间中现有的 libc 和高级语言支持。文件是 Linux 中的核心概念(与其他 Unix 系统一样),大多数数据都是通过文件交换的,device files or special filesystems such as proc and sysfs.

I would like to modify the system call so that it only gets invoked if a special user (such as "root" or user "pi") issues it.

你不能在内核中这样做。从设计的角度来看,这不仅是错误的,而且甚至是不可能的。内核对用户名一无所知。内核中关于用户的唯一知识是某些特权操作保留给 root namespace (don't forget that last part! And if that's new to you it's a sign that you shouldn't be doing advanced things like adding system calls). (Many actions actually look for a capability 中的用户 0 而不是 root。)

你要用的是sysfs。阅读 kernel documentation 并寻找非古老的在线教程或现有的内核代码(如今使用 sysfs 的代码通常非常干净)。使用 sysfs,您可以通过 /sys 下的文件公开信息。访问控制取决于用户空间——在内核中有一个合理的默认值,并在启动脚本中执行诸如调用 chgrpchmodsetfacl 之类的操作。这是使用现有机制时不需要在用户端重新发明的众多轮子之一。

sysfs show 方法自动锁定文件,因此一次只能有一个内核线程执行它。这是使用现有机制时不需要在内核端重新发明的众多轮子之一。