笔者在之前的文章《国产化替代:观察漏洞修补的及时性以供应链关系选择操作系统》中提及了 Linux 发行版厂商的关键工作:代码向后移植[1]。
这项工作是发行版厂商在维持发行版内各软件组件的版本在发行版生命周期内保持不变,也就是确保兼容性的同时,确保安全性和可靠性的关键方法。
这项工作的过程想必也是比较复杂的,但如何实施,我们可以借助 Red Hat 工程师 Yara Ahmad 的一篇博文[2],一窥究竟。
笔者:国际认证信息系统审计师、软考系统分析师、软件工程硕士
向后移植(BACK PORT),是把开源社区在开源软件新版本(比如3.0)中实现的对上一版本(比如2.0)的软件缺陷的修正(补丁a),转移到 Linux 发行版所包含的通常是更早版本(比如1.0)的软件中,从而实现对更早版本的缺陷修正,如图1所示:
图1 向后移植的版本分支关系
向后移植实际上产生了旧版本软件的分支即版本1.0a,因此有大量的潜在成本:发行版中所包含的软件包的数量,软件包可能产生的缺陷数量,以及软件工程师执行向后移植需要耗费的时间。
所以不同的发行版厂商对待向后移植的态度和措施会因为成本的考虑而不同。
比如 Gentoo Linux ,通过持续滚动更新(Rolling Release)方式实现软件组件的安全修复和功能更新,只有在特殊情况下才采取向后移植实现应急处置。
向后移植的目的是在维持发行版内软件包在发行版生命周期期间兼容性的同时,确保稳定性和安全性。
也就是向后移植所处置的软件缺陷,是特指影响安全性的漏洞、影响可靠性或稳定性的缺陷,但不包含软件的新功能。
但这个过程存在很多前提条件:
1)新版本的BUG修正可能并不正确;
2)新版本的BUG修正触发了另一个BUG;
3)新版本代码结构有变化,无法直接应用修正,需要为旧版本专门重写;
4)对旧版本的修补可能破坏旧版本的功能或者触发新BUG,等等。
因此,向后移植需要充分了解软件本身,而不是简单地对软件的旧版本源代码运行一下 patch 命令,编译通过了就万事大吉。
接下来看看向后移植的准备工作要点。
在获悉软件版本发生更新后,负责执行向后移植的软件工程师需要对软件的更新内容进行分析,确定在功能特性变化之外是否存在软件缺陷修补,并考虑和研究如下要点:
1)分析软件缺陷对发行版大版本的影响范围
发行版通常会滚动维持着2~3个大版本,关键在于,作为发行版组件的软件,在发行版各大版本内可能分别是不同的版本,要对每个版本确定是否需要做向后移植。
这种情况,在笔者之前的文章《国产化替代:观察漏洞修补的及时性以供应链关系选择操作系统》也专门介绍过。
2)按影响范围确定需要修补的具体软件版本。
只要发行版大版本还在生命周期内,就需要提供支持,进行修补。因此,需要支持的版本越多,向后移植的工作量也就越多,而且不同版本的软件的修补方法还很可能是不同的。
3)要修补的软件是否存在依赖性,所依赖的软件是否同时在进行向后移植。
鉴于 GNU/Linux 开源软件体系的复杂性,并发缺陷和并行修补的可能性是必然存在的,向后移植的过程要能有效应对和管理。
4)最复杂时,是否需要在保持兼容性的前提下,提升软件的版本(不一定提升到最新版本)后再进行缺陷修补。
这一点最常见的例子可能是 OpenSSL 的修补升级。在新的SSL加密协议获得应用时,OpenSSL这类加密功能函数库有可能采取版本升级而不是向后移植而实现对新加密协议的支持。
5)确定修补的必要性和优先级,从而确定时间排期。
人力资源总是有限的。
向后移植的过程主要使用 GIT 实现过程管理,大致可以分为如图2所示5个步骤:
图2 向后移植的过程
1)建立测试环境
重点是由于要测试的是软件包的特定版本(包括新版本和上一版本)而不是发行版的版本,软件工程师需要掌握如何在操作系统本地范围内对软件包进行构建和运行调用。
2)重现软件缺陷
按漏洞补丁的目标版本,也就是软件包的上一版本,尝试重现软件缺陷。这通常是从软件社区开发者处获得补丁和测试用例,在应用补丁的前后构建软件和运行测试用例,确认软件缺陷存在和得到修复。
3)确认影响范围
对发行版的软件版本,测试软件缺陷是否存在,确定影响范围。
由于补丁不是面向发行版的更旧版本的,所以软件工程师需要理解软件缺陷的根本原因,找出触发软件缺陷的原因和条件。
比如:软件缺陷是源自核心 KERNEL 或是源自平台架构;软件缺陷能通过可预测的条件触发或不存在可预测的模式等等。
总之要用系统性的思维方式设计出解决办法。
4)应用补丁修正缺陷
当软件缺陷得到足够的检查分析后,确认补丁是否可以对软件在发行版的较旧版本进行修正。
也就是前文所指的各种工作前提条件。这些情况可能导致无法简单地甚至不可能实现向后移植。
如果确认补丁可以直接应用于修正,则转入向后移植。如果补丁不能直接应用,则可能需要对补丁进行修改,使其能适配发行版的较旧版本。
最复杂的情况下,需要重新开发补丁,才能实现把补丁的修改内容适配到发行版的较旧版本。
5)测试和打包
对软件每一个被修正的目标版本应用补丁,执行构建和进行测试,确认是否已完成了修补,随后进行源代码打包和编译后执行文件打包。
在 Yara Ahmad 的博文中还具体描述了基于 CentOS Stream 的向后移植具体过程。
由于 CentOS 已经从原来的软件供应链中位于 RHEL 的下游位置,前移成为了 RHEL 的上游,所以在CentOS Stream 中实施向后移植,已经是补丁修补过程纳入到 RHEL 的开发周期的必要过程。
工作流程首先是对软件仓库创建本地分支,在本地分支上进行向后移植,测试通过本地提交后,再用合并请求的方式完成流程。具体过程有需要的读者可以自行参考 Yara 的博文,笔者简单概括了几个要点:
1)使用了 GitLab 进行软件包仓库的管理操作,自此至终都依靠 git 实现过程跟踪和版本管理,也就是软件包仓库本身就是一个 GIT 项目。
2)流程进行期间,需要检查远端软件仓库是否有新的更新,如果未能及时使本地仓库跟上远端仓库的更新,就有可能导致合并请求时产生冲突,处理冲突会更麻烦。
3)由于可能存在并发的流程,所以在进行期间,要确保正确地跟踪了自己在修改的分支,对可能的错误及时发现和纠正。
4)为了避免因向后移植出现软件衰退错误,测试过程不仅要测试被修补的软件,还要重建所有依赖于该软件的其他软件,或至少要通知其维护者注意。
软件衰退错误是指本已获得修复的软件缺陷,因和该缺陷不直接相关的因素重新发生。
5)提交合并请求前,还要先检查确认不存在依赖修改或并发修改,才能提交。
6)最后还有各种文档工作,比如撰写修正内容说明。
向后移植的重要性,在于能维持发行版整体功能的稳定性、兼容性和安全性,从而提高了发行版部署实例的可用性和整体效率。
尤其是对于需要信息系统整体能长期稳定运行的发行版用户,向后移植使得旧软件系统能在相当长的周期内持续获得软件缺陷修复,这就确保了关键任务软件运行。
但需要理解到,对于总是希望实现创造性的软件开发者个人来说,向后移植这件事没有创造性。
甚至乎,当发行版最终走到 EOL 的时候,之前所做的向后移植就在一夜之间全部废弃。
例如 CentOS 7 到时间后,所有的更新补丁源镜像站点都一次性删光了。
所以 Linux 发行版要能长期且同时维持兼容性、可靠性和安全性,是不可能用爱发电的,只能走商业化路线才能支撑。
始终,GNU 的 Free,是知识的自由,而不是免费。
参考引用:
[1] What is backporting and how does it affect Red Hat Enterprise Linux?
https://access.redhat.com/solutions/57665
[2] RHEL: Behind the scenes of a simple backport
https://www.redhat.com/zh/blog/rhel-behind-scenes-simple-backport
本站微信订阅号:
本页网址二维码: