【问题标题】:Ensure that UID/GID check in system call is executed in RCU-critical section确保系统调用中的 UID/GID 检查在 RCU-critical section 中执行
【发布时间】:2016-08-24 20:10:41
【问题描述】:

任务

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


背景工作

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


问题

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

更新

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

注意,遍历进程并读取进程的 凭据应在 RCU-critical 部分下完成。

【问题讨论】:

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


    【解决方案1】:

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

    请注意,我要获取的 uid 不是当前进程的。

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

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

    剩下的问题是可以使用哪些原语进行访问。为此,可以使用 make_kuid、uid_eq 和类似的原语。

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

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

    【讨论】:

    • /proc 用于进程信息。还有一些遗留的东西,但与流程无关的新东西应该放在/sys下。
    【解决方案2】:

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

    我想修改系统调用,使其仅在特殊用户(例如“root”或用户“pi”)发出它时才被调用。

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

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

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

    【讨论】:

    • 小错字“您可以在内核中执行此操作”。内核是否至少理解非零 PID/GID 值,即使它不能将它们映射到/etc/passwd 中的用户名字符串?谢谢。
    • @DevNull 内核维护着 UID 和 GID 值,但它不知道它们的含义,除了 0 = 允许做很多其他人不能做的事情的用户。但请记住,UID/GID 仅在命名空间中有意义:它不是整数,而是一对 {namespace, integer}。在用户空间的不同虚拟环境中很可能有多个/etc/passwd,单独一个UID值没有任何意义。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-05
    • 1970-01-01
    • 1970-01-01
    • 2010-10-19
    • 2018-08-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多