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()
.
创建的进程使用
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()
.