Libseccomp: RFE:支持“最大内核版本”

创建于 2015-08-21  ·  14评论  ·  资料来源: seccomp/libseccomp

随着系统调用被添加到内核中,我觉得没有足够的讨论默认情况下各种各样的应用程序会突然获得对新攻击面的访问权限。

这里的典型示例是perf_event_open() ,它是众多 CVE 的来源。 虽然性能很棒,但我的(例如)网络服务器(默认情况下)不应该能够使用它。

今天可以使用 seccomp 将其列入黑名单。 白名单可能很难管理。

可能有用的一件事是过滤任何比特定内核版本更新的系统调用,比如 3.10。 这样,每个新的系统调用在添加之前都必须经过验证才能在例如容器中使用。 升级内核不会突然将容器暴露给新的攻击面。

在与@pcmoore的讨论中,他指出这可能是结构中的另一个注释,例如arch-x86-syscalls.c

enhancement pendininfo prioritmedium

最有用的评论

看起来问题 #286 是帮助推动这项工作向前发展的具体问题......即使它已经快五年了;)

我认为第一步是在syscalls.csv文件中添加一个新字段,以指示首次引入系统调用的时间。 这将是一大块工作,因为我们目前定义了大约 469 个系统调用(!)。 然而,我们可以用一个“未定义”的值来分摊现有系统调用的这项工作,我们将把它简单地视为在时间黎明时创建的系统调用。 当然,syscalls.csv 表的所有新增内容都需要与内核版本一起添加。

一些更快速的想法:

  • syscall.csv 格式
#syscall (v5.8.0-rc5 2020-07-14),kver_min,x86,x86_64,...
accept,<version>,PNR,43,...

... 其中<version>可能是“5_8”、“UNDEF”或类似的东西。

  • 版本令牌
enum kernel_version {
    KV_UNDEF = 0,
    KV_1_0,
    KV_1_1,
    KV_1_3,
    KV_2_0,
    ...
    KV_5_8,
    _KV_MAX,
};

所有14条评论

+1
这将有助于使黑名单可用于缓解安全问题。

@nmav需要明确的是,此 RFE 用于向内部系统调用表添加有关何时首次将系统调用引入 Linux 内核的信息,而不是用于添加逻辑以确定当前运行的内核是否支持给定的系统调用。 但是,如果您试图阻止系统调用,您可以使用 libseccomp 来执行此操作,无论它是否在特定的架构/ABI 和内核版本上受支持,libseccomp 都会为您做正确的事情。

这个 RFE 已经有将近 5 年的历史了,除了与@cgwalters的一次讨论之外,我还没有看到或听说过对此类功能有太多其他兴趣。 由于还有许多其他未解决的问题,其中大多数具有更高的优先级,尚不清楚我们何时会处理这个问题,或者即使这样的事情是否会是一个有用的补充。

@cgwalters@drakenclimber您如何看待 2020 年的这个问题? 我很想以 WONTFIX 的身份结束它,但在我们采取这一步之前,我想获得一些评论和反馈。

@cgwalters@drakenclimber您如何看待 2020 年的这个问题? 我很想以 WONTFIX 的身份结束它,但在我们采取这一步之前,我想获得一些评论和反馈。

老实说,我认为这是一个非常酷的想法。 由于这个确切的原因,我的一些内部客户正在使用许可名单。 如果他们使用拒绝名单并将新的系统调用添加到内核中,那么该系统调用将成为另一种攻击途径。

让我们让它打开一段时间。 我会在 Oracle 内部四处打听,看看是否有客户对这个特性有足够的兴趣让我接受它。 但是如果@cgwalters (或其他任何人)有时间和兴趣,完全欢迎拥有它:)。

好的,只要有兴趣,我就可以保持这个开放。

我觉得还是有用的!

看起来问题 #286 是帮助推动这项工作向前发展的具体问题......即使它已经快五年了;)

我认为第一步是在syscalls.csv文件中添加一个新字段,以指示首次引入系统调用的时间。 这将是一大块工作,因为我们目前定义了大约 469 个系统调用(!)。 然而,我们可以用一个“未定义”的值来分摊现有系统调用的这项工作,我们将把它简单地视为在时间黎明时创建的系统调用。 当然,syscalls.csv 表的所有新增内容都需要与内核版本一起添加。

一些更快速的想法:

  • syscall.csv 格式
#syscall (v5.8.0-rc5 2020-07-14),kver_min,x86,x86_64,...
accept,<version>,PNR,43,...

... 其中<version>可能是“5_8”、“UNDEF”或类似的东西。

  • 版本令牌
enum kernel_version {
    KV_UNDEF = 0,
    KV_1_0,
    KV_1_1,
    KV_1_3,
    KV_2_0,
    ...
    KV_5_8,
    _KV_MAX,
};

内核版本是否适合跟踪? 是否保证较新的系统调用不会被反向移植到例如具有较低版本号的稳定内核分支?

Red Hat 会将各种东西向后移植到他们的内核中,所以不会。

如果 RedHat 将系统调用反向移植到较旧的内核版本,他们还可以修补他们的 libseccomp 版本以匹配。 虽然公平地说,这对于某些用例可能更重要,但作为修复 #286 的一种方法,我认为它是相当可行的。 另一个问题是我不确定有没有更好的方法——系统调用可以不连续的顺序添加(例如openat2是在close_range之前添加的——尽管这个例子很好我的错)。

如果 RedHat 将系统调用反向移植到较旧的内核版本,他们还可以修补他们的 libseccomp 版本以匹配。

对,就是这样。 上游 libseccomp 项目无法控制各种企业 Linux 发行版,如果这些发行版决定偏离上游项目(Linux Kernel 或 libseccomp),它们将自行寻求支持。 尽管我们将尽最大努力提供帮助,但我们不能牺牲上游项目来支持这些拥有自己的支持和工程人员的企业发行版。

作为参考, syscalls(2)手册页有一些关于何时将各种系统调用引入内核的历史信息:

我可以对系统调用进行深入研究,以找出每个系统调用的版本号——唯一的问题是我们是否应该为每个架构设置版本号,因为我很确定某些系统调用已添加到不同版本的不同架构中。

...唯一的问题是我们是否应该为每个架构设置版本号,因为我很确定某些系统调用已添加到不同版本的不同架构中。

据我所知,他们绝对是,现在仍然是。 虽然它会有点烦人,并且肯定会爆炸 CSV,但跟踪系统调用在每个 arch/ABI 的首次出现可能是正确的做法。

您可以在此@cyphar上提供的任何帮助将不胜感激。

此页面是否有帮助?
0 / 5 - 0 等级