# From Global to Local Quiescence: Wait-Free Code Patching of Multi-Threaded Processes

Status: Not started

从全局到局部的静止：多线程进程的无等待代码修补

[https://www.usenix.org/system/files/osdi20-rommel.pdf](https://www.usenix.org/system/files/osdi20-rommel.pdf)

Abstract

活体修补已成为一种常见的技术，用于在修补应用期间不会导致停机的情况下，保持长时间运行的系统服务的安全性和最新性。然而，为了安全地应用补丁，现有的实时更新方法要求整个进程进入静止状态，这可能会对多线程程序产生极大的干扰：不得不停止所有线程（例如，在全局屏障处）进行修补不仅会影响服务质量，而且还可能非常难以正确实现，容易导致死锁或其他同步问题。

在本文中，我们提出了WFPATCH，一种无等待的方法，用于向运行中的多线程程序注入代码更改。WFPATCH无需在应用补丁之前停止整个进程，而是可以在本地静止点逐个线程逐渐应用补丁，而所有其他线程都可以不间断地进行。我们已将WFPATCH实现为Linux 5.1的内核服务和用户空间库，并在Debian 10（“buster”）上使用OpenLDAP、Apache、Memcached、Samba、Node.js和MariaDB进行了评估。总共，我们成功地将33个不同的二进制补丁应用于正在主动服务请求的程序中；其中15个补丁具有CVE号码或其他关键更新。使用WFPATCH应用补丁不会导致请求延迟的明显增加-即使在高负载下也是如此-而在全局静止后应用相同的补丁会将尾部延迟增加41倍。

简而言之，我们提出了 WFPATCH，一种适用于多线程程序的无等待现场修补机制。WFPATCH 的基本区别在于，我们不依赖于全局静止状态的安全状态（可能永远无法达到），然后再将补丁逐渐应用于每个线程的本地静止点。因此，（1）没有线程被停止，（2）单个挂起的线程不能延迟或甚至阻止所有其他线程的修补，（3）实现变得简化，因为静止变成了单个线程的（可组合）属性，而不是它们的完整编排。从技术上讲，我们将补丁安装到附加地址空间（AS）中的后台。该 AS 保留在同一进程中并共享所有内存，除受补丁影响的区域外 - 然后通过切换线程的 AS 应用该补丁。WFPATCH 的当前限制是，我们只能修补只读区域（.text 和 .rodata）。特别是，我们无法应用更改数据结构或全局变量布局的补丁。但是，WFPATCH 旨在用于热修补，而不是任意软件更新，绝大多数软件修复仅为 .text-only：在我们对 OpenLDAP、Apache、Memcached、Samba、Node.js 和 MariaDB 的评估中，这适用于 104 个补丁中的 90 个（87%）。对于 CVE 缓解和其他关键问题，它适用于 41 个补丁中的 36 个（88%）。本文提供以下贡献：

• 我们分析了热修补的全局静止的定性和定量方面，并建议本地静止作为替代方案（第 2 节，第 4 节）。
• 我们介绍了针对多线程应用程序的 WFPATCH 无等待代码注入方法及其在 Linux 上的实现（第 3 节）。
- 我们演示并评估了 WFPATCH 的适用性，将其应用于六个多线程服务器程序（OpenLDAP、Apache、Memcached、Samba、Node.js 和 MariaDB），并在重负载下进行修补（第 4 节）。

本文不涉及修补程序本身的过程，具体而言，二进制补丁是如何生成的以及在将其应用于 AS 时进行了哪些转换。不失一般性，我们使用了稍微修改过的 Kpatch [30] 版本来生成本文的二进制补丁。但是，WFPATCH 在这方面大多是透明的，并且可以与任何修补程序生成框架结合使用。我们在第 5 节讨论了 WFPATCH 的普适性、完整性和限制等属性以及相关工作，然后在第 7 节中总结了本文。