当我在大学时,我被告知我可以在分配内存时请求锁定内存。这将阻止它被交换到磁盘。这是不正确的,因为当挂起到磁盘完成时它会换出。 (锁定位是一个请求,它旨在提高性能,而不是安全性,并且只有在您知道自己在做什么时才应使用。)
所以我想知道是否有一种方法来分配安全内存。我有两个想法,但我不知道它们是否实现:
安全锁:将防止休眠,因此可能会给系统的其他部分带来问题,除非有办法向进程发出信号,告诉它释放内存。但如果没有呢?
请求易失性/瞬态内存:我使用易失性来表示比 RAM 更易失性,因为系统可以取消内存映射,而无需交换或警告。这可能会导致应用程序必须处理的内存错误。
大量分配将用于解密缓存,并且可以取消映射,但也可以重建。对于密码短语,它们将存储在较小的分配中,希望它们不会被取消映射(休眠除外)。如果密码短语未映射,则需要用户交互。
是否存在这样的事情,包括其他替代方案?
我正在使用 Debian9 Gnu/Linux,但也对其他操作系统的功能感兴趣。
答案1
除了休眠之外,mlock() 保证将内存保留在 Linux 上的 RAM 中。这可以通过调用 malloc() 分配一块与可用内存大小相同的内存,在其上调用 mlock() ,然后强制每个页面出现故障(不要在生产中执行此操作)来非常简单地证明系统,它会触发OOM杀手,并且可能不会选择你的测试程序来收获)。因此,除了休眠之外,您还可以信任 mlock()。
休眠变得很棘手,但有一些方法可以部分解决这个问题。假设您的威胁模型信任root
用户(并且您必须这样做),那么当内存中有敏感数据时,您应该能够连接到 systemd 以阻止休眠。请记住,这并不完美,但它可能是您可以获得的最接近的结果。或者,我认为您可以注册一个钩子来通知您的程序是否开始休眠并擦除您的敏感内存,但我对此并不 100% 确定。
不管怎样,你可能想得太多了。
如果您只是编写通用软件并且平台控制为零(想想 GPG 或 OpenSSL 之类的东西),您应该假设您的用户知道风险, mlock() 适当的内存区域(或者更好的是,提供选项这样,具有瞬态(例如 zram)或加密交换的人就可以选择退出资源使用命中),并完成它。还要记住,虽然内核的本机休眠支持是一个安全问题(并且有很好的文档记录),但用户空间实现(如 µswsusp)通常具有内置加密支持。
但是,如果您正在处理控制软件运行操作系统的操作,则可以在禁用休眠支持的情况下构建自己的内核。
答案2
防止内存被换出并不是很有用(除了在内核中)。您担心的威胁是攻击者绕过操作系统从磁盘读取换出的数据。这意味着攻击者可以物理访问磁盘。实际上,这意味着攻击者可以物理访问计算机,因此他们可以从 RAM 中读取相同的信息。它是可以从断电几秒钟的 RAM 芯片中提取数据 - 不太可靠,但足够令人担忧的是,如果 RAM 中最近有秘密数据,您就不应该将计算机闲置。
作为一名程序员,不要去寻找一些奇怪的操作系统技巧来防止休眠。用户会讨厌它,因为它会削弱他们的功能而不利于他们的安全。
作为用户,加密您的交换空间。