确保在RCU关键部分中执行UID / GID检入系统调用

时间:2016-08-24 20:10:41

标签: c linux linux-kernel kernel kernel-module

任务

我为我的RaspBerry Pi 2编写了一个小内核模块,它实现了额外的系统调用以生成功耗指标。我想修改系统调用,以便只有在特殊用户(例如" root"或者用户" pi")发出它时才会调用它。否则,该呼叫只会跳过其大部分身体并返回成功。

背景工作

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

问题

  • 链接的问题指出list包含指向array的指针元素,如struct task_structstruct cred中所定义。两个标题中的后一个不存在于我的系统上,前者没有显示指向linux/sched.h元素的任何声明。 这有意义吗?
    • 愚蠢的错误。这完全出现在内核头文件中(即:linux/cred.h),我在struct cred中的gcc-build标头中搜索。
  • 即使上述情况有效,也没有提及我是否会获得the real, effective, or saved UID for the process甚至可以从系统调用中获取这三个值中的每一个吗?
    • /usr/src/linux-headers-$(uname -r)/include/linux/cred.h已包含所有这些内容。
  • 内核模块中是否有一种安全的方法可以在不解析/usr/include/linux的情况下快速确定用户所属的组?
    • cred.h已包含所有这些内容。

更新

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

  

注意,迭代过程和阅读过程   证书应在RCU关键部分下完成。

2 个答案:

答案 0 :(得分:2)

相关问题涉及一个根本不同的问题。引用:

  

请注意,我想要的uid不是当前的过程。

显然,一个不是当前正在执行的线程的线程原则上可以在任何时候退出或更改凭据。需要采取措施确保我们所摆弄的任何东西的稳定性。 RCU通常是正确的答案。答案提供的是,在其他方面也有一些错误。

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

我们还有一个问题是可以使用哪些原语来进行访问。为此,可以使用make_kuid,uid_eq和类似的原语。

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

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

答案 1 :(得分:2)

首先,添加新的系统调用很少是正确的做事方式。最好通过现有机制来做事,因为您将从双方已有的工具中受益:内核中的现有实用程序功能,现有libc和用户空间中的高级语言支持。文件是Linux中的核心概念(与其他Unix系统一样),大多数数据通过device files文件或procsysfs等特殊文件系统进行交换。

  

我想修改系统调用,以便只有在特殊用户(例如“root”或用户“pi”)发出它时才会调用它。

你不能在内核中这样做。从设计的角度来看,这不仅是错误的,而且甚至是不可能的。内核对用户名一无所知。关于内核中用户的唯一知识是,某些特权操作保留给根namespace中的用户0(不要忘记最后一部分!如果这对您来说是新的,则表明您不应该是做高级的事情,如添加系统调用)。 (许多动作实际上都在寻找capability而不是root。)

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

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