Fedora 变革的目标是实现 99% 的软件包可重复性
多年来,为确保开源软件的可重复性所做的努力一直在不断加强,并在主要的 Linux 发行版中获得了越来越多的支持。例如,Debian 十多年来一直在努力实现可重现的构建;它现在可以制作当前稳定版本的可重现官方 Live CD。Fedora 在这条道路上起步较晚,但已经取得了足够大的进展,目前该项目正在考虑为预计于 10 月份发布的 Fedora 43 开发周期提出修改建议,目标是使 Fedora 99% 的软件包构建都具有可重复性。到目前为止,人们对该提案的反应似乎不错,主要集中在如何实现这一目标–将打包者的痛苦降到最低–而不是是否要尝试。
可重现构建的定义
可重现构建项目将 “在相同的源代码、构建环境和构建指令下,任何一方都能逐位重现所有指定工件的相同副本 “的构建定义为可重现。Zbigniew Jędrzejewski-Szmek在2023 hackfest报告中说,Fedora过去没有优先考虑可重现性构建,因为Fedora对其构建过程的控制比Debian和其他发行版更强。他说,由于 Debian 允许维护者在本地系统生成源码包,并上传一些本地构建的软件包分发给用户,因此 “对源码包和二进制包内容的信任度都很低”。(Debian的构建守护进程会从源代码中构建大多数二进制软件包,然后分发给用户,但也有例外)。另一方面,Fedora 对软件包的控制要强得多。
在 Fedora 中,所有分发给用户的软件包都是在集中、严格控制的基础架构中构建的。所有源代码包都是从 “dist-git ”构建的:一个包含构建 “配方 ”和软件包源代码加密哈希值的 Git 仓库,因此可以相对容易地验证软件包版本之间的变化、特定源代码包的 “输入 ”以及二进制包是在什么环境下构建的。
不过,尽管 Fedora 对其软件包有更严格的控制,Jędrzejewski-Szmek 还是说,可重现构建的好处之一是有助于检测和减少针对 Fedora 构建者的任何形式的供应链攻击,并允许其他人执行独立验证,确保软件包源与 Fedora 交付的二进制文件相匹配。值得注意的是,Fedora 在 XZ 后门引起人们对供应链攻击的更多关注之前就已经开始了这项工作。
他承认 Debian 在可重现性构建流程方面更为先进,并指出 Fedora 正在为可重现性构建设定不同的定义。这个定义排除了签名和一些元数据,只关注特定 RPM 中打包文件的有效载荷:
如果给定相同的源代码、构建环境和构建说明,以及来自构建工件的元数据,任何一方都能重新创建除签名和部分元数据外完全相同的工件副本,那么该构建就是可重现的。
Fedora 追求可重现构建的不同定义的原因是,它无法按照原始定义实现 “逐位 ”重现。这是因为软件包格式和 Fedora 构建软件包的方式不同。RPM 在构建时会在 RPM 中嵌入软件包签名,但 Debian 使用的是分离签名。RPM 还包含一些信息,如 RPM 头文件中的构建时间 (BUILDTIME) 和构建主机 (BUILDHOST),这些信息可能会影响重现性。与会者讨论了允许覆盖这些变量的问题。不过,普遍的意见是,BUILDHOST 提供的信息是有用的,覆盖其包含的内容并不可取。不过,尽管 Fedora 的定义中没有出现 “逐位 ”一词,但其内容仍应 “逐位 ”相同。
根据 Jan Zerebecki 的说法,同样使用 RPM 格式发布软件的 openSUSE 项目将 BUILDHOST 设置为 “可重现”。实际的构建主机会打印在构建日志中,感兴趣的用户可以搜索 openSUSE 的构建日志来查找主机。
可重现性路径
对于 BUILDTIME,openSUSE 将构建时间设置为最新更新日志条目的日期。这是通过 SOURCE_DATE_EPOCH 环境变量提供给构建的。Fedora 的可重现性构建工作就是从这里开始的,在 Fedora 38 开发周期中进行了修改,将打包文件的修改时间(mtime)“钳制 ”为 SOURCE_DATE_EPOCH。这确保了 mtimes 与实际构建的时间无关。如果由于某种原因,他们的软件包会被新的行为破坏,打包者可以选择不执行此操作。
在 Fedora 41 开发周期中,项目对 RPM 编译过程进行了另一项修改,以消除不可复制性的常见来源。这一改动使用了 Rust 程序 add-determinism,该程序试图将二进制文件或源文件中的元数据标准化,以确保一致性。它与 Debian 的 strip-nondeterminism
类似,后者是一个 Perl 库,是用于构建 Debian 软件包的 debhelper 工具的一部分。使用 strip-nondeterminism
工具,debhelper 可以从各种文件和归档格式中移除时间戳和文件系统排序等非确定性信息。Fedora 项目选择编写自己的工具,因为将 Perl 拉入每个软件包的构建根目录并不可取。
根据新的变更提案,迄今为止,对 Fedora 构建基础架构的修改已使 90% 的软件包构建具有可重复性。现在的目标是达到 99% 的软件包构建。看来,Fedora 已经尽可能多地利用了基础架构的改动,而不需要各个打包者来处理可重复性问题。为了达到 99%,该项目将不得不要求打包者将其软件包中的可重复性问题视为 Bug。
变更的所有者–Jędrzejewski-Szmek、Davide Cavalca 和 Jelle van der Waa–将打包 fedora-repro-build 工具,允许开发者对在 Koji(Fedora 的构建系统)中构建的软件包进行本地重建,以测试它们的可重复性。这还需要建立一个 rebuilderd 公共实例,它是一个提供独立验证的系统,证明二进制软件包可以从源代码中复制。它可以扫描软件包资源库的元数据,查找新的或更新的软件包,然后排队等待重建,它还提供了一个应用程序接口来查询软件包的可重现性状态。Rebuilderd 还可以选择使用 diffoscope 工具生成差异报告。Arch Linux 可重现性状态页面提供了一个很好的 rebuilderd 使用示例。
如果该提案被采纳,还需要更新 Fedora 的打包指南,规定软件包应该(至少目前不是 “必须”)可重现地构建,并允许在软件包不可重现时针对软件包提交错误报告。
除了可重现性在安全方面的益处外,该提案还认为可重现性将提高软件包的质量。软件包中不可重现的位往往是 “由代码中的错误或疏忽造成的”。例如,独立于架构(noarch)软件包对硬件架构的依赖 “几乎总是不必要的和/或错误”,而可重复性测试可以发现这些错误。
该提案承认,有些软件包在可重复性方面会有一些不容易修复的问题。例如,Haskell 软件包目前在由多个线程编译时无法重现,但正在努力修复。由于 GNU 调试器索引文件(.gdb_index)即使在输入相同的情况下也可能大小不一,因此使用 Go 生成的软件包的调试数据无法重现。目前还没有解决这个问题的方法。另一个已知的问题是,Linux 内核对模块签名使用的是短暂密钥。LWN 报道了 Thomas Weißschuh 提供的一套补丁,或许能解决这个问题。
反馈
在 Fedora Discourse 论坛的讨论主题中,Fedora 基础架构负责人 Kevin Fenzi 问:”这个 [rebuilderd] 实例将在哪里运行,谁来维护它?他还指出,最好能有关于设置 rebuilderd 实例的文档。“除此之外,我喜欢这个想法!” 卡瓦尔卡说,可重复性工作目前使用的是由 Meta 赞助的亚马逊网络服务(AWS)账户,但 “如果有偏好,我们可以考虑转移到 Fedora 基础架构中”。Fenzi 回答说,在 Fedora 基础架构之外继续运行这项工作也许是件好事,可以使其更加独立。“当然,我们可以运行一个,然后其他人也可以运行其他的,并进行比较”。
Daniel P. Berrangé 问 rebuilderd 能否与 Koji 集成,这样维护者就不必学习另一种构建工具。”我对使用另一个提供编译后测试的独立网络服务非常不感兴趣。Jędrzejewski-Szmek说,使用Koji进行构建是一个有趣的想法,但 “我们也希望我们的重建尽可能独立”,因此在Koji之外的系统中进行重建仍然是可取的。在同一构建环境中第二次重建软件包意味着 “我们没有进行太多测试”。
Fedora 基础架构团队的成员 Miroslav Suchý 想知道 rebuilderd 是否可以向 Fedora 的 Copr 构建系统提交构建,而不是在 Fedora 中建立另一个构建系统。这引发了关于 Copr 功能以及它是否能与 rebuilderd 完美集成的讨论。Jędrzejewski-Szmek 指出,rebuilderd 是一个 “以自己的方式做事的完整项目”,试图教会它异步地与外部服务对话可能会很复杂。
将 rebuilderd 工具和报告集成到 Fedora 现有的基础架构中一直是讨论中反复出现的主题。Simon de Vlieger 说,他并不执着于在 Koji 中进行构建,而是希望该项目 “能与 Fedora 现有的工具和东西很好地集成,这样人们使用它的几率就会最大”,并能达到人们的期望。
下一步
提案的下一步是向 Fedora 工程指导委员会(Fedora Engineering Steering Committee,FESCo)提交票据,至少在提案公布一周后。在这种情况下,时间不会早于 3 月 26 日。如果 FESCo 批准,所有者就可以开始提案工作,争取在 Fedora 43 计划发布的 10 月份完成。
到目前为止,大多数 Fedora 用户可能都没有注意到 Fedora 的可重现性工作,他们在安装 Fedora 43(或 44、45 等等)时也不会发现有什么不同。不过,鉴于不良分子一直在努力寻找并利用开源项目中的供应链弱点,这项工作还是很有价值的。
本文文字及图片出自 Fedora change aims for 99% package reproducibility
你也许感兴趣的:
- 安装 Fedora 36 后一些适合中国用户的简单设置
- 对比 Ubuntu 18.04 和 Fedora 28
- chroot 技术–Linux 系统的瑞士军刀
- 20 年前的 exe 现在仍然可以在 Windows 上运行,linux 呢?
- Linux 内核 6.14 在性能和 Windows 兼容性方面实现了巨大飞跃
- Android 15 上的原生 linux 开发环境
- 早期的 Linux
- Linus正面回应Linux内核“Rust之争”:未来必定使用,完全生产级别尚需时日!
- C 语言老将从中作梗,Rust for Linux 项目内讧升级!核心维护者愤然离职:不受尊重、热情被消耗光
- 【外评】Linux 桌面市场份额升至 4.45
真正的宝藏是我一路上找到的朋友
https://github.com/keszybz/add-determinism
我猜这是 https://salsa.debian.org/reproducible-builds/strip-nondeterm 的 NIH 版本… …
在 README 的底部提到了这一点。
…and in the article:
> Fedora 项目选择编写自己的工具,因为将 Perl 拉入每个软件包的构建根目录是不可取的。
我有点想知道这个或类似的东西是否能以某种方式使时间戳失效,这样您就可以比较两个日志文件了……
更进一步的是可以比较带有指针地址或其他东西的日志文件
我不确定我是否理解您的要求,但您不能直接用 sed 删除每一行的时间戳吗?或者举个更极端的例子,我偶尔会用……tr,我想是吧,从日志中完全删除所有数字,以便汇总错误信息,而不用担心它们一直包含无关的变化数字(类似于 tail -5000 logfile | tr -d [0-9] | sort | uniq -c | sort -n 或类似的)。
如果用打印机将日志打印在纸上,每行打印的时间都是随机的(由于一个错误),油墨中含有半衰期为 `h`(打印到纸上)的化学示踪剂,但油墨是从不同半衰期为 `h1`、h2`、……的几种(`m`)油墨中随机抽样的,你会怎么做?您可以使用标准的 unix 实用程序。
让实习生把这些都塞进扫描仪,把结果通过魔方运行,然后做我之前说过的事情。不过,我觉得你的问题并不真诚,你到底想表达什么意思?
对不起,我只是想开个玩笑(关于疯狂系统和面试问题),因为你回答的问题有点不清楚。我猜我没说中,哈哈。
啊,这样就说得通了。我猜你是在暗示,我所使用的 unix 工具既神秘又笨重。谢谢你的澄清。
确保可重复性的另一种更强大的方法是使用可正式验证的证明进行更严格的编译。
https://pi2.network/ 就是这么做的。它使用的是 K-Framework,在我看来,作为解决此类问题的长期方法,K-Framework 被低估了,值得更多关注。
你可以通过 LD_PRELOAD 将时间系统调用设置为总是返回 0
很高兴看到他们也参与其中。
https://news.opensuse.org/2025/02/18/rbos-project-hits-miles…
我还希望看到更多静态链接的二进制文件。比如 Python,它的安装和使用简直就是一场噩梦
我想大家都反对你这么做。Fedora 打包政策 [1]:
> 包含库的软件包应尽可能排除静态库(例如使用 –disable-static 进行配置)。只有在特殊情况下,才应包含静态库。针对库进行链接的应用程序应尽可能针对共享库而非静态版本进行链接。
[1]: https://docs.fedoraproject.org/en-US/packaging-guidelines/
我宁可使用静态二进制文件,也不愿意为单个应用程序捆绑虚拟机,因为虚拟机会产生静态二进制文件的所有缺点,外加 900 个新的缺点。
发行版文档中的打包指南并不能反驳上述评论。
这是目前的正统做法,所以显然所有文档都这么说。我们都知道现行标准的标准论据。他们的评论明确表示 “我希望看到改变当前的正统观念”。他们的意思是,也许在 90 年代,当我们开始使用动态库时,这种说法并不尽如人意。
与其说是 1000 个程序和 1000 个库,不如说是 1000 个程序和 1,000,000 个库?
鉴于评论说的是 python,他可能已经有了这 1.000.000 个库。
对于不直接捆绑在操作系统中的 python 程序,通常的做法是为每个程序单独建立一个虚拟环境,然后从头开始下载/编译每个依赖项的精确版本。
这已经是大多数容器格式的结果了,只是更混乱而已
不明白你是怎么做到的,但不感兴趣。
他们的观点是,如果有 1000 个程序使用相同的 1000 个库,静态链接会在每个二进制文件中重复使用所有这些库,从而占用更多的存储空间和内存(这也会影响性能),实际上就是在使用 1000000 个库。
动态链接提供 M 个二进制文件 + N 个库。静态链接则是 M * N。
但并没有提出 1000 个程序。没有人说系统中的每个二进制程序都有问题。只有某些二进制程序才有问题。这是愚蠢的夸张说法,没有任何用处,也没有任何有效的论据。
我具体说的是,我宁可要静态二进制文件,也不要 flatpak/snap/appimage/docker/等。这是两个具体事物之间的比较,而它们都不是 “1000 个程序使用 1000 个库”
而且有些二进制文件已经自带了所有库的副本,只不过是以静态链接之外的其他形式而已。如果有 1000 个 flatpaks/snaps/docker镜像等,那么这一百万个库就已经以比静态二进制文件更糟糕的形式存在了。但一般来说,任何单一系统上都还没有这样的库,尽管数量在增加而不是减少。
尽管动态链接具有众所周知的明显优势,但有时也会出现动态链接不适合任务的情况。
在这种情况下,不管出于什么原因,你都希望可执行文件是独立的,那么就有很多方法来安排它,从将 lib 和 bin 放在不冲突位置的简单 tar,到设置自定义 lib 路径(或 bin 与 lib 路径一起编译)的启动脚本,到 appimage/snap/等,到完整的 docker/其他容器,到 unikernel,到简单的静态 bin。
所有这些都有不同的好处和代价。静态链接的好处是非常简单。与任何容器或捆绑系统相比,它既节省空间,又节省复杂性。
我不明白,既然容器是显而易见的选择,你为什么还要直接使用虚拟机作为替代。
字面意义上的虚拟机是夸张的说法,也是我用词不严谨的地方。我指的是所有不同形式的容器化或捆绑应用程序及其所有依赖项和操作系统环境。
从依赖关系管理的角度看没有太大区别
由于提到了 python,我认为您的意思是 “编译成一个二进制文件”,而不一定是 “静态链接”。
这个二进制文件可能是静态链接的,也可能是链接到系统库的。不过,很多时候链接的唯一系统库就是 libc。
是的,我也希望这种方式能越来越普遍,而不是像 python 那样。
对于 Python,可以看看 python-build-standalone[1] 中的 musl 编译,它们是静态链接的。
我还在这里[2]提供了一个静态链接实用程序的小集合。
[1] https://github.com/astral-sh/python-build-standalone
[2] https://github.com/supriyo-biswas/static-builds
你说的 “安装和使用的噩梦 ”到底是什么意思?
他们使用 Windows。s
Python 有适用于 windows 的官方安装程序,在微软商店中发布,还可以通过 UV 拉出,在 Powershell 中工作起来轻而易举。
我们还停留在 50 年前的计算模式。
理想情况下,所有内容都是静态链接的,但文件系统会对重要部分进行标记和删除。
尽管共享库的概念由来已久,但直到 SunOS 4.x 和 System V 第 3 版才在 Unix 系统中引入共享库。1988 年的 Sun 论文:https://www.cs.cornell.edu/courses/cs414/2001FA/sharedlib.pd…
它们仍然会在 RAM 的页面缓存中被复制……这正是静态链接的真正问题所在。
作为 fedora 的用户,这究竟能给我带来什么?我的意思是,我可以理解它是为了密封构建,但为什么呢?
可重现的构建可以提高软件质量。
如果我们相信我们有一个可重现的构建,这就构成了一个大的测试用例,让我们对整个软件栈的确定性有信心。
为了验证该测试用例,我们实际上必须多次重复构建。
如果我们发现了差异,就说明出了问题。
例如,假设正在使用的编译器存在一个错误,即它依赖于某个单元化变量的值。这可能会在生成的代码中显示出来。
没有可重现的编译,编译结果当然总会有差异:我们无法通过重复编译来发现问题所在。
(无论如何,人们都会在不可重现的构建之间进行差异分析。例如,反汇编新旧二进制文件,然后进行文本差异,验证只有一些预期的变化才会出现,比如内嵌了构建日期的字符串文字。如果你有可重现的构建,你就不需要做这样的事情来检测变化。
可重现的构建将强化工具链和周边实用程序。它们将消除联编系统中的不稳定因素,如带有竞赛条件的并行 Makefile,或进入链接作业的对象文件的不确定顺序等。
我不了解这方面的知识,但在我看来,这可能对安全有好处?这样你就能知道组件是否被篡改过?
这在所有 Redhat 变体中都已存在。RPM/DNF 对已安装的二进制文件进行了校验,并对软件包和软件源进行了 GPG 签名。在这个生态系统中,我唯一不满的就是把 GPG 公钥放在镜像中。人们应该从非镜像中获取这些密钥,否则任何技术不高的攻击者都可以直接替换密钥,然后重新签署所有内容。这虽然会被发现,但不会马上被发现。
还可以使用 Tripwire、OSSEC 及其替代工具,甚至是自制工具来捕获更改,这些工具通常会为生产批准的软件包创建经过签名的清单。
是的!对 SolarWinds Orion 的攻击是对其构建过程的攻击。经过验证的可重现构建会检测到 subversion,因为构建不会匹配(除非攻击者设法检测并侵入所有构建过程)。
完全相同的二进制文件可以在所有平台上以完全相同的方式被入侵。
如果我理解正确的话,这就需要释放发布者的私钥,对吗?
什么?
宾果。我们曾用这种方法捕获了一个篡改我们代码的病毒。
相关信息,请参见 Ken Thompson:
http://genius.cat-v.org/ken-thompson/texts/trusting-trust/
你知道什么让我没有信心吗?更新软件,但结果呢,还是打印出相同的构建日期?当然,几个小时后,在几十个文件的深处,我发现了一些可重现性错误,只是硬编码了而已。
到目前为止,可重现性构建主要集中在前者,而你提到的这些错误和供应链攻击则为零。
有些所谓的用例毫无意义。你更新了编译器。哦不,所有代码都不一样了?享受 16 小时的深度挖掘吧,你会发现有人根据英特尔 x64 架构参考手册第 7893 页给出的周期时间调整了代码生成。
他们应该从正在构建的分支的最高提交日期开始设置软件包的构建天数。这不可能在下一个版本启动时不会改变。如果你在任何人的可重现软件包系统或发行版中看到这样的行为,你就有理由投诉了。
我认为构建主机或基础架构的某些相关部分受到攻击的可能性并不小。
在我的印象中,可重现的构建可以提高安全性,因为它有助于更明显地表明软件包在构建系统的后期阶段没有被篡改。
* 编辑,链接文章中引用了这段话:
> Jędrzejewski-Szmek说,可重现的构建的好处之一是有助于检测和减少对Fedora构建者的任何形式的供应链攻击,并允许其他人执行独立验证,确保软件包源与Fedora提供的二进制文件相匹配。
您最需要担心的供应链攻击并不是有人侵入 Fedora 编译器。
而是对上游软件包本身的攻击。
由于项目合并了恶意行为者的贡献,可重现的构建绝对无法捕捉到类似一年前 XZ 软件包被入侵的情况。
下游软件包系统或操作系统发行版只会将恶意更新转化为精美的可重现构建。
不要让完美成为优秀的敌人;这并不能防止上游问题的发生,但它消除了一个可能发生危害的地方。
我并不是说不要可重现性构建;只是这只是一个不重要的理由,几乎没有必要。
可重现的构建是一件显而易见的好事,构建农场的安全性只是一个注脚。
你的注脚就是我的软肋。
再硬也是硬。
可复制的构建可以解决 xz 问题。目前的水平无法解决这个问题,但 github 可以做一些事情来创建可下载软件包的脚本表,从而实现可重现性。Fedora 可以检出 Git 哈希值,而不是下载提供的压缩包,这样就能绕过这个问题,再次获得可重现的构建。
以上都是值得考虑的事情。
不过,我不确定你能写出什么代码,既能掩盖问题,又能美观大方。
而任何旨在捕捉上游问题(如 XZ 漏洞)的代码都无法检测到 Fedora 软件包构建环境中的漏洞。两者都需要。
如果构建是可重现的,发行版可以做的一件事就是拥有多个构建农场,由完全不同的操作员负责,这样就没有共享访问权限和共享机密。这样就可以比较每个构建场中每个软件包的构建结果,如果结果不同,就可以怀疑有人篡改。
因此,它可以帮助你更早地发现篡改行为,甚至还能防止篡改行为的传播,这取决于你还做了什么。
Bingo。
更好的安全性!恶意行为者只需更改 OpenSSL 源代码或二进制文件中的几个字节,就能完全破坏它(即禁用证书检查)。
可重现的构建消除了验证二进制文件的单点故障–现在任何人都能做到这一点,而不仅仅是拥有私钥的人。
这是防止恶意软件潜入供应链的众多工具之一。
请记住,编译器可以被设置后门来安装恶意代码。比特慧/签名等同并不意味着软件不含恶意软件。
没错,但我们每增加一个步骤,其他步骤也会变得更难。肯-汤普森的 “信任信赖 ”编译器不太可能检测到现代 gcc,更不可能成功引入后门。即使你一开始使用的是那种被破解的 gcc,几年后,当最新的 gcc 无法再为使用被破解编译器的人构建程序时,也很有可能被发现。(现在再加上 clang 和使用 clang 的人……)
我们可能永远无法达到完美,但我们朝着这个方向迈出的步伐越多,就越有可能达到在现实世界中无法妥协的地步。
在这种攻击中,编译器不是可重现的人工制品?还是 “反向破坏 ”使用了其他技术?
他们的观点是,你需要像 https://bootstrappable.org/ 这样的东西(确实存在)。
谁能简要说明一下一般的构建可重复性?
我们的目标是,当你编译相同的源代码、环境和指令时,最终结果是完全相同的。
然而,特定硬件的优化会自然而然地抵消这一既定目标,我不知道如何才能避免因小失大。
我明白为什么很多方面都需要可重现的构建,但所提出的要求似乎与现实不符。
最基本的是硬件,硬件可能会宣传自己并不具备的功能,或者不以相同的方式执行相同的指令,还有其他细微差别,这些都会破坏确定性这一属性,自然也会玷污整个堆栈,因为计算机在很大程度上依赖于突现设计。
这些特性往往隐藏在层层抽象中,并且/或者可能被分割成依赖于体系结构与独立于体系结构(独立的)的部分,但它们依然存在。
可重现性构建的大部分(如果不是全部)有益特性都依赖于环境被限制在确定性范围内,而现实情况是,制造商要确保这些东西保持在随机范围内。
> 硬件特定的优化自然会否定这一既定目标
发行版软件包在其构建服务器上编译,并分发给使用各种系统的用户;因此,从本质上讲,它不应该使用针对构建者硬件的特定优化。
在基于源代码的发行版(如 Gentoo)上,用户添加的优化标记会得到不同的输出结果。但让相同的硬件/编译标记产生相同的输出仍有价值。
> 不过,特定硬件的优化会自然而然地否定这一既定目标
这些被视为不同的构建工件,也是可重现的。
那么问题的关键在于,如果 M 台机器中的 N 台产生了相同的输出,那么我们就有机会质疑为什么在其他机器上会产生不同的输出。如果构建无法重现,那就只能束手就擒了。
不清楚你是否也在谈论编译器优化–可重现的构建必须有一个固定的目标。
在谈到优化时,我更多地是从 LLVM 类型性能优化的角度来考虑的,如果这足以说明问题的话。
可重复性与 “配置文件引导的优化 ”是相悖的。尤其是在任何涉及网络和其他不一致的 IO 上。
来自 Go 文档[0]:
> 建议直接在源码库中提交配置文件,因为配置文件是构建的输入,对于可重现(和高性能!)的构建非常重要。与源代码一起存储简化了构建体验,因为除了获取源代码之外,没有额外的步骤来获取配置文件。
我非常希望其他语言/框架也能做到这一点。
[0]: https://go.dev/doc/pgo#building
Performant 的说法与我听到的研究相反。另外,由于 PGO 配置文件数据在大多数情况下是非确定性的,即使是在与终端机器相同的硬件上编译,“直接在源代码库中提交配置文件 ”也是它们被删除或至少被排除在比较之外的原因。
这是我记得的一篇论文[1]中的一段话,因为这些配置文件几乎与机器无关。
> 不幸的是,大多数代码改进都不是独立于机器的,少数真正独立于机器的改进会与那些独立于机器的改进相互影响,导致阶段排序问题。因此,实际上不存在独立于机器的代码改进。
当我们试图复制配置文件以避免配置文件运行的成本时,我个人遇到了同一代或相邻几代 Xeon 芯片实现之间的一些差异,这可能会让我对此更敏感一些,但我个人看到性能大幅下降,甚至达到两位数,导致我们的回归测试无法进行。
在我看来,这正是您的链接提出以下建议的原因:
> 您的生产环境是您应用程序代表性配置文件的最佳来源,如收集配置文件中所述。
这与 Fedora 为 x86_64 使用一些随机或通用配置文件(可能与最终用户的特定配置文件相匹配,也可能不相匹配)截然不同。
[1] https://dl.acm.org/doi/10.5555/184716.184723
如果这些差异对您的工作负载非常重要,那就把不同类型的机器视为不同的架构,提交所有机器的配置文件数据,并(确定性地)为所有机器编译单独的版本。
无论如何,Fedora 上游都不可能为您做到这一点(可能的硬件配置太多了),所以您已经在为自己进行设置了。
只有当您使用 “实时 “数据而不是捕获的运行回放来执行 PGO 时,情况才会如此,而这是最好的做法。
这一点都不矛盾,但从系统 A 的输出将成为系统 A+1 输入的一部分的意义上讲,这将是 “单体 “的,在系统设置中组织起来很复杂,尤其是当你无法使用可以验证的语言时。但如果你有这样的工具,这绝对是可以实现的,比如你可以在 nix 中做到这一点。
这是可重复性构建的 “代价 “之一,就像伪随机数生成器必须使用预先配置好的种子一样。
这确实对实际项目造成了冲击,可能也是 “99%”被点名的部分原因,但 Fedora 也提到,由于 RPM 的工作方式,他们无法与上述可重现构建.org 官方的含义相匹配,因此我们将看看他们还需要放松哪些限制。
下面是 suse 不得不重新启用 gzip 的一个例子。
https://build.opensuse.org/request/show/499887
下面是 reproducible-builds 邮件列表中关于 PGO 的一个主题。
https://lists.reproducible-builds.org/pipermail/rb-general/2…
还有其他一些代价,比如某些项目需要摆脱并行构建,这让很多人不得不放松官方限制。PGO+LTO 的价值就是其中之一。
gcda 配置文件是不可重现的,但它们生成的代码通常是相同的。如果你仔细研究一些项目的流程,就会发现他们只是删除了 gcda 输出,然后如果代码不同,往往会尝试重建或其他方法。
虽然没有理想的解决方案,但假设上游正在进行可重现的构建,那么一种似乎相当有效的方法就是出售代码,构建可重现的构建来验证出售的代码,然后启用优化。
但我知道,并不是每个人都同意可重现性的价值主要在于避免对构建基础架构的攻击。
然而,可重现性构建与 MSO 模型检查等毫无关系……就像有些人声称的那样。大部分情况下,可重现性只是删除非确定性数据而已,就像你在这里看到的,Fedora 复制了 Debian。
https://salsa.debian.org/reproducible-builds/strip-nondeterm…
由于在编译和链接时提高地址空间随机化的粒度比在程序运行之初更容易,因此地址随机化熵的降低显然会带来成本(在我看来,降低供应链风险的代价远远大于成本),从而增加 ROP 式攻击的风险。
如果重新编译软件包或供应商是可行的,那么在编译和链接时恢复这种熵在某些情况下可能是值得的,在这种情况下进行真正的 PGO 可能也是最好的。
哟,攻击者可以访问相同的二进制文件,所以只有运行时地址随机化才有用。
为什么要这样?
难道剖析器不会输出一个 hprof 文件或其他文件,作为编译器制作发布二进制文件的输入?为什么不直接存储呢?
> 例如,Haskell 软件包目前在多线程编译时无法重现
在我看来,这并不是什么大问题。gcc 编译器甚至不支持多线程编译。在 C 语言世界里,并行性来自于并行编译多个翻译单元,而不是任何一个翻译单元都有多个线程。
“对源码包和二进制包内容的信任度都很低”。- 我想知道这是否能说服组织采用适当的工件管理流程?如果供应链攻击呈上升趋势,那么企业采用 Cloudsmith 或 jFrog 等工具进行安全工件扫描肯定比以往任何时候都更有必要。
很高兴看到这一进展!感谢所有付出努力的人。
三月份的相关新闻 https://news.ycombinator.com/item?id=43484520 (Debian 书虫的实时图像现在完全可以重现)
是的!我希望有更多的工具是确定性的。我的愿望清单中,Proxmox 配置排在首位。
想试试看是否可行吗?https://github.com/SaumonNet/proxmox-nixos?tab=readme-ov-fil…
很有意思。我正在开发与 zk 系统有关的东西,一旦完成,就会与大家分享。
99%?黛比-唐纳(Debbie Downer)说,只需要一个软件包就能把事情搞砸
有一长串晦涩难懂的软件包很少被使用,而且几乎可以肯定的是,哪些软件包是常用的,这是个幂律。可重复性通常需要软件包管理者和开发者之间的协调,而要在每个软件包上都做到这一点是不乐观的。
如果他们只是开始隔离那些长尾的晦涩软件包,那么人们就会不高兴。如果不能实现 100% 的可重复性,也会让一部分用户不高兴。鉴于聪明的用户可以有意识地避开那些没有通过可重复性测试的软件包,所以这是个双输的命题。
100% 可重复性是个不错的目标,但只要无处不在的软件包都具有可重复性,这可能就能覆盖大多数用户。如果能提供一种简单的方法来禁止不可重现的软件包,那将会非常有趣。
我相信总有一天他们会将此作为纳入官方软件仓库的一项要求。
有一个有趣的想法–除了以 99% 的软件包为目标之外,或许以 100% 的软件包为目标也是个不错的主意,比如说,以官方安装介质中的软件包为目标?(如果他们已经达到了这个目标,我甚至不会感到惊讶,但将其明确化并记录下来还是有价值的)
如果这是我的选择,我还是更愿意玩 100:1 的俄罗斯轮盘赌,而不是 1:1。
“我所看到的只有 1%的彻底失败”–到处都是坏爸爸
Linux 用户继续逍遥于软件包安全范式之外,而 NPM、PyPI、cargo 等(比如上周上了头条的那个 VSCode 扩展注册表)则认为他们仍然可以逍遥法外,只需发布一些浪人推送的东西即可。
我注意到 “改善开发者体验 ”和 “严格管理 ”这两种理念之间存在着明显的脱节。
我认为,过去二十年的准营销/销售/招聘 DevRel 角色推动了一种无摩擦开发的说法,而从另一方面看,安全性和正确性大多被放在了次要位置(特殊行业除外)。
我认为这是市场大规模增长的结果,但我非常欢迎钟摆向后摆动一点。在关注投机性执行漏洞的同时,人们还在关注打错字的软件包,这说明我们还不够成熟。
我认为这是程序员为程序员制作工具的结果。这是我非常不喜欢的。程序员习惯于编辑配置、设置环境变量或使用自定义代码来解决问题。因此,你会得到可以通过代码(脚本或扩展)进行配置和定制的程序,以及可以做任何事情的小工具。在我看来,好软件不应该是这样设计使用的。积极的一面是,我们有一些非常好的工具–软件领域的修订控制远远超出了其他领域。但如果不是因为 Git 是程序员设计的工具,它也可以用于其他领域…… 很多开发者甚至都很难用 Git 做一些日常用例之外的事情。
依赖关系管理工具的出现,是因为对程序员来说,写一些代码比解决一个更大的问题更容易、更自然。对程序员来说,写代码比解决更大的问题更容易、更自然,写工具比写自己的版本或清理复杂的依赖关系更容易。
“安全性 “和 “便捷性 “总是需要权衡的,你永远不可能两者兼得。
我看到过一个三角形,“功能性 ”是第三点:https://blog.c3l-security.com/2019/06/balancing-functionalit…
你可以获得安全易用的工具,但它们通常必须是非常简单的东西。
Ture。那么,“方便 ”一族就不明白为什么我们其他人不想要他们认为很棒的东西。
我们有很好的中间立场,但大多数套餐经理甚至不承认其他的担忧是合理的。
这并不完全是一种直接的交易;我记得 OpenBSD 的朋友们非常推崇好的文档,也许还有好的默认设置,正是因为这样更容易正确地使用工具会让它更安全。
这是显而易见的,这里的问题是为什么每个人都要用安全来换取方便,以及还需要发生什么才能让人们开始认真对待安全问题。
关于 “还需要发生什么”: 我会说是灾难性的事情。我最近什么都没想起来。
安全是件好事,但偶尔我也会想,技术人员难道不会想象出邪恶的主谋利用数据做些什么并设法统治世界的奇妙场景吗?
而在现实中,至少在过去 5 年里,有那么多领导人(和人们)做了那么多愚蠢的事,说了那么多愚蠢的话,我觉得我们更应该害怕愚蠢的人,而不是黑客。
在过去 5 年中,几家大型医疗机构几乎所有人的敏感个人数据都遭到了泄露。如今,政治领导人是最大的问题,但这种情况可能会再次发生改变。
那么实际影响是什么呢?别误会我的意思,我并不认为这不是坏事,但话又说回来,滥用信息的行为可能已经被上述提供商做了(例如:根据以前的情况提高保险费率,利用弱势人群)。
社会的运行靠的是协议和法律,而不是(绝对的)保密。
当然,有些情况下,比如电网停电数日、人们在医院被远程杀害、核电站爆炸等,会产生不同的影响,我们可能会做到这一点,只是现在还没有发生而已。
实际影响是你的私人医疗数据落入窃贼手中,这是大多数人都不希望看到的。
这就好比大多数人在家中被盗后都会感到痛苦,因为他们认为自己的家是一个私人空间,尽管锁具制造商从未宣称过 100% 的安全性(或者小偷只是通过砸窗绕过了锁具)。
协议和法律并不能解决这个问题,因为这些东西已经无法阻止小偷了。
>这里的问题是,为什么每个人都用安全来换取便利
我不认为安全是用便利换来的。一切都始于便利性,而从那时起,安全性就一直在努力争取地位。
>人们开始认真对待安全问题的原因
只有强制执行的法律和非同小可的后果才能迫使人们认真对待安全问题。即便如此,大多数人可能还是不会这样做。
我认为事实大多恰恰相反。Linux 的打包人员正在精心雕琢他们的玩具,而其他人则大多在使用上游软件包和 docker 容器在漂亮的系统周围工作。在我的 Debian 系统上,我所关心的软件有一半都是直接从网上(curl | bash 风格)、开发者自己的 APT repo 或很可能从单独的软件包管理器(MELPA、pypi、Go cache、Maven 等)安装的。
我每天工作的三个系统(其中一个是高性能计算集群)都使用 Nix 软件包管理器,但没有一个运行 NixOS。我们可以精心设计自己的工具,并使用最新、最好的工具。
这听起来像是一种非常恼人的软件管理方式。我没有安装过任何软件。
发行版因为没有立即整合上游的变更而受到了难以置信的憎恨,真的是没有赢家
说得没错。认为所有软件都应该打包给所有发行版,而且你不应该使用最新版本的软件,这种想法显然是可笑的。它之所以看起来隐约合理,只是因为一直以来都是这么做的。
如果 Linux 已经进化出了一个更合理的系统,而有人来建议说:“不,实际上我认为每个发行版都应该有自己的软件包格式,它们都应该负责打包世界上所有的软件,而且为了稳定起见,它们也应该使用旧版本”,那么他们理所当然会被笑掉大牙。
> [……]你不应该使用最新版本软件的想法显然是可笑的。
为了实现这一目标,我们开发人员必须放弃进行破坏性修改。
我们不能有任何 “你的 python 2 代码无法在 python 3 上运行 ”的无稽之谈。
我们应该停止进行破坏性修改吗?也许吧。会吗?不。
您可以同时安装 python 2 和 python 3。应用程序应获得其所需的依赖项。发行版将依赖关系从应用程序中剥离,给开发者带来了许多问题。
我们不能允许任何 “你的 python 2 代码无法在 python 3 上运行 ”的无稽之谈
这种情况之所以会发生,只是因为发行版坚持发布 python,然后每个人都坚持使用该 python 运行自己的软件。
在另一个世界里,每个人都可以用自己的程序运行自己的 python,就不会有这个问题了。Windows 基本上就是这样解决这个问题的
在磁盘空间用完之前,这听起来不错。
当然,在我成长的那个年代,普通人还买不起硬盘–我父母不得不省吃俭用好几个月才给我买了一个软驱。
什么是发行版,只不过是以特定方式打包的软件集合?
一大堆可悲的软件包 </sotn>
nixpkgs 打包了我需要的几乎所有东西。这是一个非常大的软件包集,而且非常新鲜。这主要与文化和工具有关。我曾试图为 Debian 做贡献,但几个月后就放弃了。在我开始使用 Nix 的几天后,我就开始为 nixpkgs 做贡献了。
将每个软件包作为发行版的一部分非常有用。你可以声明式地定义你的整个系统和所有软件。我可以在 5 分钟内推出一个桌面、开发虚拟机或服务器,并对其进行全面配置。
> nixpkgs 打包了我需要的几乎所有东西。
是的,因为它们允许任何人在很少监督的情况下做出贡献。正如兰斯-维克(Lance Vick)所写[1],“Nixpkgs 就是 Linux 中的 NPM”。Solène Rapenne 写道[2]:”获取 nixpkgs 的提交权限非常容易,在我看来,供应链攻击很容易实现:有太多的提交,不可能由一个值得信任的小组来审查所有内容,而且有太多的贡献者,无法确保他们都是值得信任的。
[1] https://news.ycombinator.com/item?id=34105784
[2] https://web.archive.org/web/20240429013622/https://dataswamp…
几乎每个 PR 在合并前都会经过审核(尤其是非提交者),在典型的版本碰撞 PR 中很容易发现妥协。至少在一个大的 monorepo 中,这一切都会公开。例如,在 Debian 中,维护者几年前就可以直接将二进制文件推送到存档中(我认为这对非主版本来说仍然适用),而且即使是源代码包,人们上传它们时也很少受到监督,而且它们并不都在开放的版本控制中。
当然,Debian 的开发者/维护者会受到更严格的审查。但是,与 Debian、NPM、PyPI 或 crates.io 相比,在 nixpkgs 中有意妥协会更加明显。
NixOS(Nix?) 举个例子,有人开了个愚人节玩笑,说埃隆-马斯克赞助了 NixOS,结果他们的帖子被屏蔽了,还(差点)被停职。
目前有数以百万计的分叉,有些是分叉的分叉,因为它们被认为在文化上不够纯粹,不适合被文化清除的分叉。
希望 Determinate Systems 或 Ekela 能让这个系统真正成熟起来,并得到企业的资助,将整个系统从泥潭中拉出来。
是的,Nix 被分叉了。曾经有人试图分叉 nixpkgs,但都失败了,因为维护像 nixpkgs 这样的东西实在太费事了。Nix 被分叉问题不大,因为至少每个人都需要与 nixpkgs 兼容。我认为有多个实现是可以的,它们会带来新方向的探索(例如,其中一个项目试图在 Rust 中重新实现 Nix)。当然,Guix 也是从分叉开始的。
我同意内讧并不好。但老实说,当你只是使用 NixOS 并提交 PR 时,你并不会真正注意到它们。888/6/mtndew4brkfst
不过,一些更激烈的争论是在 RFCs repo 中或关于 RFCs repo 的争论,所以并不只是在聊天平台或论坛上发生争吵。就你的观点而言,RFC 仓库也不是每个潜在贡献者都会接触或需要接触的。
我同意你的观点,但使用这样的软件会让我感到极度不安,因为主团队会对社区成员进行苏联式的清洗,让他们静默/流放/禁言,而不是因为他们冒犯了别人,而是因为他们犯了错误思想。更糟糕的是,他们往往是多产的开发者。
讽刺的是,我能做的最接近的比较就是驾驶特斯拉。即使产品再好,你所支持的组织却恰恰相反。
我认为,Nix 团队会继续慢慢赶走有能力的人,直到腐烂使整个团队枯萎,到那时,所有人都会将上游转向 Determinate Systems 的开放核心。虽然我希望 DS 最终会走 RHEL-Fedora 路线。
>举个例子,有人开了个愚人节玩笑,说埃隆-马斯克赞助了 NixOS,结果他们的帖子被静音了,(差点?
这不可能是真的。你确定那是个无伤大雅的玩笑,而不是什么偏执的玩笑?
虽然我不同意引述者所表达的几乎所有观点,但我认为分叉正在发生,分界线包括文化规范而非严格意义上的技术分歧。
https://discourse.nixos.org/t/breaking-doge-to-recommend-nix…
同一作者在其 Reddit 主题上引用了原文,并且在那里基本上没有受到批评:
https://old.reddit.com/r/NixOS/comments/1joshae/breaking_dog…
我个人认为这令人难以置信的令人反感,同时也相当能代表 Nix 社区中一些人的谈话质量。我没有冒犯你,你只是脸皮薄,你就不能开个玩笑吗?你必须自己判断这是偏执还是狗哨,或者两者都不是。
我曾是一名普通的社区成员,在去年春天永久离开之前,在该生态系统中做过少量开源工作(项目和少量 nixpkgs PR)。我不再赞成出于任何目的使用该系统,并试图替换我使用过的每一部分。
我仍然能听到他们继续肆无忌惮地破坏自己的管理,在净化文化方面取得的进展微乎其微。他们直到上周才禁止安杜里尔在同一个官方论坛上发表招聘帖子。
难道我应该认真地相信,人们觉得这太冒犯人了,以至于发帖人因此被禁?那些哭泣的人是在假装冒犯,还是在讽刺自己?真正的坡氏定律在这里起作用了。
>我个人觉得这令人难以置信
怎么会?为什么?这显然是讽刺,写得像《洋葱》。
>而且还相当能代表尼克斯社区某些人的谈话质量
好的讽刺?至少有些成员还没有脑残到无药可救的地步。
> 我没有冒犯你,你只是脸皮薄,开不起玩笑,等等。
这显然没有冒犯性,如果这让你不高兴,那显然是你脸皮薄,开不起最平淡的玩笑。嘻皮笑脸。
>我不再赞成出于任何目的使用它,我将设法更换我使用过的它的每一部分。
看完这篇文章后,我也会告诉其他人不要使用 Nix。这个社区确实太毒了。
>我仍然能听到他们继续以各种方式把自己的管理搞得一团糟,而在文化解毒方面取得的进展却微乎其微。
除非他们清除所有神经质的左派活动家,这些人对 “代表性不足的少数群体 ”有着奇怪的癖好。
>他们直到上周才禁止安杜里尔在同一个官方论坛上发表招聘帖子。
我不知道那是谁,也不知道为什么会有这个问题,但我想这是只有左派才会哭诉的事情。
发行版/格式太多了。对于大多数用途来说,发行版软件包比 snap/flatpack/docker 要好得多,唯一困难的是发行版软件包太多,没有哪个程序能在发布步骤中写明 “已集成到软件包管理器中”。你可以在程序发布时发布一个 docker 容器–这是经常做的,但很少是应该做的。
在某些情况下,这样做也许有道理,但在很大程度上,这样做是不合理的。举个例子,如果我想构建并使用/部署一个 Python 应用程序,需要最新的 NumPy,而系统的软件包管理器中没有。这就很难证明我有理由为此找出并构建一个发行版专用软件包,而不是直接使用 PyPI 上的 Python 软件包。
关键是发行版应该提供你需要的 numpy。
如果他们做不到,因为你需要的是具有特定功能的最新主版本,那会发生什么?
他们不会。甚至绝大多数 Arch 用户都认为,“无论如何都要集成破损,并在网页更新日志中发布警告 ”的政策简直是疯了,尤其是与 SUSE Tumbleweed(也是滚动发行版)这样的发行版相比,在后者中,所有东西都会经过测试,如果出现破损,也会保持暂存状态。
> 它们没有。
我向您推荐比您稍早发布的评论: https://news.ycombinator.com/item?id=43655093
他们会这样做。
不,他们没有。没有一个正常人会说:“我宁愿在没有明确的构建警告/弃用的情况下集成一个有破坏性变更的软件包”。
是你加上了 “破坏性”。最初的说法只是说集成者会因为跟不上上游而遭到憎恨,这是事实。许多更改并不会造成破坏,而且用户也不知道哪些是破坏性的,哪些不是。
不,你的说法是,集成者会因为没有立即集成上游变更而遭到憎恨。这显然是错误的,因为用户更希望对软件包进行测试,以确定是否有破坏性的变更,并打上补丁或发出弃用警告,而不是盲目地集成变更,结果被破坏性变更扯了后腿。没有人憎恨发行版打包者稍稍延迟验证和测试。
我之所以提到 Arch,是因为很多人都讨厌他们这样做,结果把人们的腿从他们脚下拉了出来。
有些用户渴望稳定,但这与维护者因没有立即整合上游变更而招致憎恨的说法并不矛盾。特别是,发行版有不止两个用户–他们可以做不同的事情。
发行版因为过时而遭到真正的憎恨,以至于上游收到大量关于旧的和已解决的问题的错误报告。
Bottles 开发团队的工作就是最好的例子。
要解决这个问题并不容易。
根据我的经验,这主要是 Debian 稳定版的问题。
未来的分布并不均匀。
运维 randos 推崇的东西在 iOS 和 Android 上也很好用。
系统 perl 其实也不错。可惜的是,Linux 供应商并不关心新语言的系统版本。
Arch Linux 上的 system rustc 也不错。我认为在 Debian 上,系统 rustc-web 也不错。
我最近重新安装了,我没有安装 rustup,而是想试试 Arch rust 软件包。据说这不是 “正确 ”的方法,但到目前为止效果很好,我的项目都不需要每晚更新。我的项目都不需要夜间更新,更新都是在上游更新一天之后。少考虑一件事,我喜欢。
当然,商店里从来没有恶意软件…
> 在 iOS 和安卓系统上也能很好地利用游民推送的内容。
不过,应用程序商店的软件都经过严格审查。与 Fedora 或 Canonical 相比,苹果和谷歌在验证其向客户提供的软件上花费的精力要多得多、多得多、多得多。
之所以看起来像 “流浪汉”,是因为审计人员和验证软件的数据中心都隐藏在付费墙后面。
其实不然。至少在安卓系统上,他们有一些自动审核,但仅此而已。任何人工审核大多是出于商业原因。
此外,Windows 和 Mac 已经存在了几十年,但它们的审核工作却为零。是的,恶意软件确实存在,但很容易就能避免,而且还能从任何地方获得最新的软件,非常值得。
Windows 上的审查是,基本上任何没有 EV 证书签名的软件都会在用户电脑上显示可怕的 SmartScreen 警告。即使你的用户没有被警告吓倒,你的可执行文件也很有可能被 Windows Defender 错误标记,然后你就必须申请微软将你列入白名单。
在 Mac 上,任何未经签名的软件都会显示可怕的警告,用户不得不进入设置中的安全选项才能打开软件。
这并不是真正的主动行为,但这意味着如果你发送恶意软件,微软/苹果可以撤销你的证书。
如果你对 Linux 上类似于这种发行模式的东西感兴趣,我会去看看 Flatpak。它与 Windows/Mac 上的发行模式类似,但有一个额外的好处,那就是更新是集中处理的(因此你不需要在每个程序中都写入自动更新功能),而且所有程序在上传到 Flathub 之前和改变任何权限时都要经过人工审核。与 Windows 和 Mac 的 “无可怕警告 ”发布选项不同,列出软件也不需要任何费用。
> 另外,Windows 和 Mac 已经存在了几十年,但它们的审核率为零。
这不是只针对应用程序吗?所有系统软件都是由操作系统开发商提供和审核的。
是的,但发行版软件包库大多由应用程序和非系统库组成。
大多数用户只安装了少量应用程序。它们可能不是同一个,但如果你想要最新版本,flatpak 很容易设置。如果你想要 CLI 软件(nix、brew、toolbox……)的最新版本,你也不必受系统软件包管理器的束缚。
Debian 的好处在于,你可以在为下一次重大更新进行阅读的同时,享受整整两年的例行维护。主要的问题是上游开发者会在同一个补丁上进行错误修复和功能更新。
>但应用程序商店的软件都经过严格审查。与 Fedora 或 Canonical 相比,苹果和谷歌花在验证客户使用的软件上的精力要多得多、多得多、多得多,而且还差得很远。
哈哈哈!…they don’t. 他们真的没有。不过,他们确实有一些程序,让他们看起来像做了一样;我承认这一点。
我经常看到这样的倡议和文章,但没有提到 Nix。是不是因为它不够出名,不值得比较?因为对我来说,这才是标准。
我广泛使用 Nix,但 Nix 守护进程的作用并不是从固定的 OCI 容器中构建代码并关闭互联网就能实现的。当然,后者在整个行业中更为标准,而且更容易实现。Nix 并不是一种革命性的容器化技术,老实说也不是一种很好的技术。
Nix 的价值来自软件包集 nixpkgs。具有革命性意义的是,nixpgks 如何通过纯粹的函数表达式,从源代码出发,声明式地构建 Linux 发行版,并且具有可重复性。不过,nixpkgs 本身几乎就是一个完整的宇宙,它通常与其他发行版处理事情的方式不兼容,因此对 Fedora、Debian 和其他
在工作中,我们回到了 Docker 构建的方式来制作可重现的镜像。主要原因是 Nix on Arm 的交叉编译支持较差,开发人员需要为 amd64 服务进行编译,并得出映像校验和,将其放入本地运行的工具中,用于服务版本验证和可重现性。
使用 Docker 的结果相对简单。对于 Nix,即使它在 Linux Arm VM 中运行,我们也尝试过,但最终放弃了。
有趣的是,我在使用 Docker 时也有过这样的经历–主要是由于 c++ 的依赖性,而在 Nix 中却没有问题
从近期来看,将 nix 定位为应用程序开发者和发行版维护者之间的通用接口更有意义,而不是将其作为一种直接面向用户的方式,将发行版维护者完全排除在循环之外(尽管它在这方面非常有用)。
理想情况下,发行版维护者在看到一个使用 nix 打包的项目时会想: > 哦,好极了,应用程序开发者已经把它打包好了:
> 很好,应用程序开发人员采取了额外的措施来方便我的工作。
但我认为实际情况并非如此。你可以在项目中添加一个 flake 输出,以构建 .rpm 或 .deb 文件,但这并不常见。
我猜大多数情况下,发行版维护者会直接使用 cmake 或 cargo 等特定语言的编译工具,而忽略 nix 工具。只有当 nix 阻止了应用程序开发人员在构建过程中做出疯狂举动(或至少明确指出了这种疯狂举动,而不是某种 “我的机器 ”意外或某种 “没什么可看 ”的小把戏)时,他们才会从 nix 中间接受益。
如果我们想让世界变得尼克斯化,我认为我们应该减少劝说人们不要使用他们喜欢的软件包管理器,而更多地让底层软件包更加统一。
哦,我向你保证,如果你写这类东西,你很难不知道 Nix。几乎马上就会有人告诉你。
之所以没有提到 Nix(我是作者),是因为它在这里并不重要–在讨论 Fedora 正在做的事情时,可比较的发行版是 Debian 和其他使用类似打包方案的发行版。
我同意 NixOS/nixpkgs 不是一个很好的比较基础。您对应用程序开发人员使用 nix 来指定其构建(即作为 make 的替代方案,而非 Fedora 的替代方案)有什么看法吗?
引用文章内容:
> 软件包中不可重现的部分往往是 “由代码中的错误或马虎造成的”。例如,架构独立(noarch)软件包中对硬件架构的依赖 “几乎总是不必要的和/或错误”,而可重复性测试可以发现这些错误。
这正是 nix 所擅长防范的,而且如果用户不熟悉底层工具链,它也不要求用户参与其中,这一点非常方便。
例如,我可以使用下面的命令在某个提交处构建 helix,而根本不知道它是一个 rust 包。虽然它不能保证所有方面的可重复性,但如果构建依赖于任何事先不知道哈希值的比特位,它就会失败,我想这样就成功了一半。
以这种方式使用,nix 能帮助 Fedora 实现可重复性吗?还是说,在 Fedora 看来,它只是一个多余的层,需要剥离掉,这样他们就可以更直接地接入货物?
以这种方式使用 nix,对 Fedora 的可重现性工作有帮助吗?还是说,在 Fedora 看来,这是一个需要剥离的多余层,这样他们就能更直接地接入货物?
很多基于 Nix 的软件包构建都会将 Nix 存储路径直接烧入二进制文件中。如果幸运的话,只有 rpath 可以剥离,但在某些情况下,二进制文件中还会出现其他 Nix 存储路径。这对 Fedora 来说似乎毫无用处。
此外,Nix 也无法解决许多棘手的问题。(例如,由于在构建过程中使用了 hashmap,导致排序差异造成的构建非确定性)。
> 很多基于 Nix 的软件包构建会将 Nix 存储路径直接烧入二进制文件
我不知道这个,听起来像是个 bug。也许可以做些什么,让你更容易知道你的编译是否存在这种情况。
我仍然认为,通过拒绝在未指定输入的情况下编译,Nix 清除了一大堆问题,从而避免了发行版维护者的麻烦,但也许这只是我一厢情愿的想法。
我会继续使用 nix,因为当我来到一个几年没做过的项目时,不用考虑它是否能在这台机器上运行,也不用弄清楚底层语言的特定命令是什么,这种感觉很好–但如果有什么方法可以调整一下,让其他人也有这种感觉,我很想知道。
我不知道这个,听起来像是个错误。也许我们可以做些什么,让您更容易知道您的系统是否存在这种情况。
这是一项功能。例如,如果二进制文件需要加载数据文件,它需要知道完整路径,否则就会回到 FHS 文件系统布局(Nix 试图解决它的许多问题)。
我仍然认为,通过拒绝构建未指定输入的东西,
,我没有关注过传统 Linux 发行版的开发,但我很确定它们也是在只包含指定依赖的最小沙箱中构建的。例如,请参见 Mock:https://github.com/rpm-software-management/mock
与流行观点相反,Nix 的构建是不可复制的:https://luj.fr/blog/is-nixos-truly-reproducible. html
对这篇文章的描述太奇怪了,与其他关于此主题的文章相比,这篇文章的结论很明确:(a) Nix 实现了非常高的可重复性,并在这方面不断改进、 (b) 此外,Nix 的可重复性是大多数其他发行版(甚至是在某些比特可重复性指标上表现出色的发行版)所不具备的(即时间旅行–能够在不同环境中重现构建,甚至是在几个月或几年之后,因为构建环境本身的可重复性更高)。
你所链接的这篇文章非常明确地指出,无论从定性还是定量的角度来看,NixOS 都实现了高度的可重复性,甚至明确拒绝了评估绝对可重复性的可能性。
NixOS 在这方面可能不是绝对的领导者(可能是 stagex,或者是 GuixSD,如果你仅限于拥有大量软件包集的更实用的发行版的话),但它确实非常出色。
你是想链接到另一篇文章吗?
> NixOS 可能不是这里的绝对领导者(可能是 stagex,或者 GuixSD,如果你仅限于拥有大量软件包集的更实用的发行版的话),但它确实非常出色。
你能评价一下 stagex 如何吗?看起来它可能确实是同类产品中最好的,但我几乎没听人提起过它。
Bootstrappable Builds 开发人员创造了一种方法,可以从只有(注释的)机器代码的 MBR(加上大量源代码)一直开发到 Linux 发行版。在此基础上,stagex 开发了 OCI 容器。
https://stagex.tools/ https://bootstrappable.org/ https://lwn.net/Articles/983340/
高度是什么意思?要么你实现了构建的位对位可重复性,要么没有。
如果你的版本库中 99% 的软件包都能实现比特对比特的可重复性,那么你就可以认为你的发行版具有高度的可重复性。
只要有一点点想象力,就很容易想到其他衡量可重复性程度的方法,例如:
要想对不同发行版的可重复性进行有意义的比较,甚至是定量比较,其实并不难。
当然,但就真正可重现的软件包的绝对数量而言,它们超过了 Debian,因为 Debian 只针对软件包总数中较小的一部分实现了可重现性,即便如此,它们也不是 100%。关于 Fedora 有多少软件包,尤其是这 99% 的目标软件包有多少,我还没有找到可靠的数字。
无论从哪个角度看,Nix 都是领先的。
免责声明:我与 Nix、Fedora、Debian 等公司没有任何关系。我只是承认,Nix 在这一领域做了大量艰苦的工作,Fedora 和 Debian 之所以能一跃成为这一领域的佼佼者,在很大程度上要归功于 Nix 所指明的道路。
它们不是。
https://reproducible.archlinux.org/
Debian 重现了 91%-95% 的软件包(取决于体系结构) https://reproduce.debian.net/
> 免责声明:我与 Nix、Fedora、Debian 等公司没有任何关系。我只是认识到,Nix 在这一领域做了大量艰苦的工作,Fedora 和 Debian 之所以能在这一领域崭露头角,在很大程度上要归功于 Nix 所指明的道路
这完全是错误的。
2016 年,Debian 在 SUSE、Fedora 和 Arch 的贡献下率先开展了可重现性构建(Reproducible Builds)工作。NixOS 也加入了这一行列,但直到过去 4-5 年才取得了较少进展。
NixOS 的努力应归功于 Debian 项目。
来自你自己的链接:
> Arch Linux 的可重复性高达 87.7%,其中有 1794 个未知的坏软件包和 12762 个好软件包。
这相当于小于 15000 个软件包。相比之下,Nix 总共有约 10 万个软件包,他们正努力使其具有可重复性,其中约 85% 具有可重复性。Debian 也是如此–约有 3.7 万个软件包被跟踪用于可重现性构建。当绝对数字相差悬殊时,用百分比来撒谎就是一种方法。
> 这完全是错误的。2016 年,Debian 率先开展了可重现性构建工作,SUSE、Fedora 和 Arch 也做出了贡献。NixOS 也加入了这一行列,但直到过去 4-5 年才取得了较少进展。NixOS 的努力要归功于 Debian 项目。
Debian 组织了跨 Linux 发行版的广泛努力。不过,Nix 项目从一开始就是围绕可重复性设计的。它还开创了其他系统试图模仿的架构方法。我认为你严重误解了 Nix 在其中扮演的角色。
> 那是小于 15000 个软件包。相比之下,Nix 总共有约 10 万个软件包,他们正试图使其具有可重复性,其中约 85% 的软件包具有可重复性。Debian 也是如此–约有 3.7 万个软件包被跟踪用于可重现性构建。当绝对数字相差悬殊时,就可以用百分比来撒谎了。
这不是谎言。这就是软件包的目标。同样,“nixpkgs ”软件仓库打包了大量源代码存档,并将整个生态系统重新打包到自己的软件仓库中。这大大增加了软件包的数量。你不能只看平面数字。
> 然而,Nix 项目从一开始就是围绕可重复性设计的。
不是的。
> 它还开创了其他系统试图模仿的架构方法。
这没有任何关系,而且你也大大高估了 Nix 的技术细节。从根本上说,它是在 2002 年发明的,而从那时起,一切都有了进步。rpath “黑客技术并不神奇。
> 我认为你严重误解了 Nix 在其中扮演的角色。
自 2018 年以来,我一直在为可重现性构建(Reproducible Builds)做出贡献。
我认为人们普遍混淆了可重现性在这里的不同含义。Nix 最初追求的可重复性是:对相同推导的多次评估将导致相同的规范化存储 .drv。在很长一段时间里,它们并不是完全可重现的,因为评估可能取决于环境变量等。但是,薄片已经(完全)堵住了这个漏洞。因此,Nix 中的可重现性意味着,评估相同的软件包集将产生相同的编译配方(.drvs)。
但是,这并不能说明构建工件的可重复性。一个软件包集可能总是评估出相同的 drvs,但如果所有源软件包都根据随机() > 0.5 来选择构建内容,那么就根本不存在构建工件。与 Nix 相比,Debian 和 Arch 更注重这种可重复性。
可重复性的不同概念。该项目特别关注比特对比特的相同构建(如无时间戳、并行编译工件等)。而 Nix 则更注重声明性和 “可重复性”,或者其他什么好名字。
这两个概念对于不同的目的都很有用,而 Nix 并不特别擅长第一个目的。
https://reproducible-builds.org/citests/
它非常非常复杂。对于大多数 Linux 用户来说,这已经超出了他们的最大努力范围,因此它只能算是一类工具。命令式软件包的可重复性非常重要。很多其他工具都建立在 RPM/DEB 软件包之上,与 Nix 有着相似的优势,比如 Ansible。这更像是 “水涨船高”。
这是一篇关于 Fedora 的文章。
是的,我知道。但在讨论可重现软件包时,我们可以也应该借鉴现有的技术。Fedoras 系统有能力实现这个目标吗?它的构建方式正确吗?是否应该采用另一种软件包管理器来实现这一目标?
“What about Nix tho? “就是可重现构建的 “Rewrite it in Rust”。
目前,无论是 debian、fedora、arch 还是 opensuse,似乎都没有其他发行版愿意改变自己的设计来匹配 Nix 的方法。
他们有太多熟悉当前方法的人。
这甚至都不是真的。Hacker News 的读者似乎非常关注最流行的 Linux 发行版的桌面版本,但这远远不是他们的全部。带有 SLE Micro 和 Edge Image Builder 的 SUSE 是一个声明式构建系统,用于创建自己的安装镜像。如果你不想要 SLE Micro,他们甚至还为你提供了 Elemental Toolkit,可用于以声明方式创建你自己的定制发行版。我不太了解 Debian 和 Red Hat 在这方面的做法,但我知道它们有类似的工具。如果你想这么说的话,“问题 ”就在于,开发人员–如果我可以不客气地在这里说几句的话–是非常自私的。主要 Linux 厂商的目标是企业边缘计算用例,而开发人员只考虑自己用于开发的终端 PC。很多发行版工具都能为你提供声明式构建、事务性更新、不可变的服务器镜像,但如果它们不能为你的个人笔记本电脑提供同样的功能,那么这些努力对于模式化的《黑客新闻》评论员来说就是无足轻重的。
值得一提的还有 Guix,它实际上是 Nix 的克隆,但隶属于 GNU 项目,因此只使用自由软件,并选择使用 Guile 而非自定义 DSL 进行配置。当然,它并不是已经存在的发行版。
因为对于任何不关心自己电脑状况的人来说,Nix 的升级和使用都是一件非常痛苦的事情。
在 Nix 的复杂性消耗殆尽的同时,Nix 的概念也会慢慢被其他更友好的工具所吸收
Nix 之于 Linux 用户,就如同 Linux 之于普通人。
在我看来,这个目标像是一个营销 OKR。正确的技术目标应该是 “所有软件包,除了那些有正当理由(如签名)不可重现的软件包”。
如果你愿意读一下:
““这个定义排除了签名和一些元数据,只关注特定 RPM 中打包文件的有效载荷:
在谷歌 SRE,我们经常有一些技术性很强的 OKR,这些 OKR 是用一些 “9 的个数 ”制定的。比如 99.9999% 的正常运行时间之类。因此,获得两个 9 的可重复性似乎是一个合理的首要目标。我希望他们以后能增加更多的 9。
作为一个对 RHEL 稍有涉猎的人,我记得 Fedora 的所有软件包都有签名。此外,DNF/Yum 元数据也有签名。
我认为 Debian 软件包本身没有签名,但 apt 元数据有签名。
几年前,我从一个用于容器和虚拟机的 ansible 分子测试 env 设置脚本中学到了这一点;因为 “which ”并不一定安装在容器中:
dnf reads .repo files from /etc/yum.repos.d/ [1] which have various gpg options; here’s an /etc/yum.repos.d/fedora-updates.repo:
From the dnf conf docs [1], there are actually even more per-repo gpg options:
1. https://dnf.readthedocs.io/en/latest/conf_ref.html#repo-opti…
2. https://docs.ansible.com/ansible/latest/collections/ansible/… lists a gpgcakey parameter for the ansible.builtin.yum_repository module
For Debian, Ubuntu, Raspberry Pi OS and other dpkg .deb and apt distros:
signing-apt-repo-faq: https://github.com/crystall1nedev/signing-apt-repo-faq
From “New requirements for APT repository signing in 24.04” (2024) https://discourse.ubuntu.com/t/new-requirements-for-apt-repo… :
> 在 Ubuntu 24. 在 Ubuntu 24.04 中,APT 将要求版本库使用下列公钥算法之一签名:[ RSA,至少 2048 位密钥,Ed25519,Ed448 ]
> 这要归功于 Werner Koch 最近在 GnuPG 2.4 82 中的工作,允许我们在调用 gpgv 工具验证版本库时在 APT 中指定 “公钥算法断言”。
与投资沙箱相比,这简直是浪费时间,因为沙箱能真正保护用户,而不是阻止理论上的攻击。Fedora 的应用程序沙箱功能远远落后于其他操作系统(如 Android),因此这是更需要解决的问题。
默认采用安卓式的保姆沙箱(”你不能授权访问你的下载文件夹,因为我们是这么说的 “等)不太可能受到普通 Linux 发行版用户的欢迎。
此外,图形应用程序的最大选择性沙箱早已实现。只需使用 Podman,并只挂载 Wayland 套接字和任何工作文件即可。
>默认采用安卓式的保姆沙盒(”你不能访问你的下载文件夹,因为我们这么说 “等)不太可能得到普通 Linux 发行版用户的认可。
如果你这样推销的话。很多 Linux 用户都说他们关心安全问题,不想要恶意软件等。这是实现这些愿望的一步。几十年来,用户已经习惯于使用安全性设计不佳的工具,因此会有一些成长的烦恼,但人们等待的时间越长,情况就会越糟糕。
>只需使用 Podman,并只挂载 Wayland 插座和任何工作文件。
这对普通用户不起作用。安全需要可访问性。
>只需使用 Podman 并只挂载您的 Wayland 套接字和任何工作文件。
要是这么简单就好了……
为什么不呢?
所有文件都是一个大洞,你真的需要门户。你可能还需要音频。也许还需要图形加速,这取决于软件和其他有限的硬件访问。还有 dbus(但需要沙盒代理访问)。可能还需要主机的一些全局配置(字体、主题、光标)。还有……也许还有更多,但关键是这取决于软件。也许有时就是这么简单。但对于非复杂的应用程序来说,往往并非如此。
我还没见过哪种形式的桌面沙盒不是:
a) 实际上毫无用处
或者 b) 让我想把我的电脑从窗户扔出去,换成 1990 年代的设备(还是比普通的 Android 有用)。
我认为你必须同时使用沙盒和这个功能。
两者对安全都有好处,但优先顺序很重要。在安全方面最薄弱的领域应该得到最多的关注。
这是在假设有固定数量的精力和资源要在这两件事之间分配–机会成本总是存在的。
当然,Fedora 项目并不是一个纯粹的社区项目,所以我不知道这个观点在这里是否适用。但我只是想指出,优先级和机会成本并不总是像您建议的那样起作用。
Fedora 工作站默认使用的 Flatpak 在功能上已经与 Android 的沙盒系统非常相似。
如果你想通过分隔来实现安全,你应该考虑 Qubes OS,我的日常驱动程序,https://qubes-os.org。
这只能保证 vms 之间的安全。这从侧面解决了问题,人们仍然可以在同一个 Qubes 中轻松运行多个应用程序。
要像 Qubes 虚拟化那样安全地隔离一个虚拟机内的应用程序是不可能的。如果你真的关心安全问题,就不应该依赖虚拟机内部的加固。尽管如此,Qubes 确实提供了加固虚拟机的方法:https://forum.qubes-os.org/t/hardening-qubes-os/4935/3, https://forum.qubes-os.org/t/replacing-passwordless-root-wit….
人们可能希望多个应用程序协同工作。因此,在 Qubes 中设置安全性比宣布它是一个自由的系统更有意义。
如果应用程序一起工作,它们通常属于同一个安全域/信任级别。您是否有仍需将它们相互隔离的例子?
即使它们属于同一信任级别,也并不意味着如果其中一个受到威胁,我就不会在意它是否会影响到第二个。
那就在不同的虚拟机中运行它们?
除此之外,Fedora 中的任何加固功能都可以在 Qubes 上的 Fedora 虚拟机中使用。Qubes 不会强迫您使用内部没有隔离的虚拟机。
但这样文件就不能共享了。
Qubes 有这样的功能。
你刚刚还推论了为什么现在实现的沙箱对桌面来说真的毫无意义。
我把 Qubes 用作我桌面上的日常驱动程序,所以没有。
你能从中得到什么?特别是考虑到上面提到的 “协同工作的程序在同一上下文中运行”。
我从中得到了什么:https://forum.qubes-os.org/t/whats-your-system-layout-like/8…
关于如何从 Qubes 中获益的两个官方示例:
https://www.qubes-os.org/news/2022/10/28/how-to-organize-you…
和
https://blog.invisiblethings.org/2011/03/13/partitioning-my-…
另请参见: https://forum.qubes-os.org/t/how-to-pitch-qubes-os/4499/15
> Fedora 的应用程序沙箱功能
您是指 Flatpaks 还是其他?
当然,这是一种解决方案,但它仍然需要大量的工作,既要修补漏洞,又要修复应用程序,使其在安全性方面有更好的设计。
不要让完美成为优秀的敌人?Flatpak 并不完美,但多年来它的安全性一直在稳步提高。我第一次使用 Flatpak 时,大多数应用程序的沙箱都是敞开的(因为它们与沙箱不兼容)。现在,很多 Flatpak 的沙箱都受到了更多限制。