memfd_secret():它应该如何工作?

memfd_secret(): how is it supposed to work?

memfd_secret() 已合并到内核中,但我看不到它真正的安全优势。我的意思是,这有避免旁路攻击的想法,但这就像当车钥匙被锁定并且没有人知道它们在哪里时。

据我所知,在内核模式下,提供给应用程序的页面根本不会被映射,但这不能用于隔离病毒或内核本身的任何内容。

隔离内核的一段内存应该如何更安全?

有人可以提供一个代码示例来说明它如何保护幽灵或类似的东西吗?

更新

int main(int argc, char *argv[]) {
    while(true) {
        int rc = fork();
        if(rc == -1) {
            perror("fork error");
        }
    }
}

memfd_secret() 允许用户-space 进程拥有一个“秘密”内存区域。在这种情况下,“秘密”意味着其他进程不能访问该内存区域(甚至不能访问内核本身,或者至少不是偶然的)。

此系统调用允许进程以更安全的方式存储机密信息(如密码或私钥),因为恶意软件更难访问该秘密内存区域。这个系统调用还应该防止像 Spectre 这样的漏洞,因为秘密内存区域是未缓存的;并且还应该保护(虽然不是完全,但至少部分)免受内核错误的影响,因为内核无法访问该内存区域。

为了使用此系统调用(将在 Linux 5.14 中可用),您首先调用 memfd_secret() 以获得文件描述符;然后调用 ftruncate() 以选择秘密内存区域的大小;最后你使用 mmap() 来映射秘密内存,这样你就可以像往常一样通过指针访问它。

其他详细信息可用 here

编辑:不幸的是,由于对性能的担忧,使 memfd_secret() 不易受到 Spectre 等攻击的“未缓存”功能已被删除。

编辑 2:有关为什么使用 memfd_secret() 获得的秘密内存区域使程序更安全的更多详细信息(source,为清楚起见,我稍作修改):

  • 增强保护(结合所有其他内核 攻击预防系统)针对 ROP attacks。秘密记忆让“简单” ROP 不足以执行渗出,这增加了所需的 攻击的复杂性。连同内核等其他保护 堆栈大小限制和地址 space 布局随机化使得发现 小工具真的很难,没有任何用于访问的内核原语 秘密内存意味着一个小工具 ROP 攻击无法工作。由于唯一 访问秘密内存的方法是重建丢失的映射条目, 攻击者必须恢复物理页面并插入指向 它在内核中,然后检索内容。这至少需要三个 比大多数标准攻击难度更高的小工具。

  • 防止跨进程秘密用户-space内存暴露。曾经的秘密 内存已分配,用户不能不小心将其传递到内核中 传到某处。不能通过访问秘密内存页面 直接映射,它们在 GUP 中是不允许的。

  • 针对被利用的内核漏洞进行加固。为了访问秘密内存, 内核端攻击需要遍历页表并创建新的 一个,或者产生一个新的特权用户-space进程来执行秘密 使用 ptrace 进行渗漏。

编辑 3:我认为可能相关的注释:使用 fork() 创建的子进程可以访问秘密内存区域,因此必须谨慎。至少,使用标志 O_CLOEXEC(传递给 memfd_secret()),该进程不会使秘密内存可供使用 execve().

创建的进程使用