打安全补丁是对于维护计算机软件的一个重要部分, 特别是对于操作系统。对于 FreeBSD 来说, 很长的一段时间以来这都不是一件容易的事情。 补丁打在源代码上,代码需要被重新编译为二进制, 然后再重新安装编译后的程序。
FreeBSD 引入了 freebsd-update
工具之后这便不再是问题了。这个工具提供了 2 种功能。
第一,它可以把二进制的安全和勘误更新直接应用于 FreeBSD
的基本系统,而不需要重新编译和安装。第二,
这个工具还支持主要跟次要的发行版的升级。
由安全小组支持的各种体系结构和发行版都可使用二进制更新。 在升级到一个新的发行版本之前, 应先阅读一下当前发行版的声明, 因为它们可能包含有关于你期望升级版本的重要消息。 这些发行声明可以通过以下链接查阅: http://www.FreeBSD.org/releases/。
如果 crontab
中存在有用到
freebsd-update
特性的部分,
那么这些在开始以下操作前必须先被禁止。
有些用户可能希望通过调整配置文件
/etc/freebsd-update.conf
中的默认配置来更好地控制升级的过程。
可用的参数在文档中介绍的很详细,
但下面的这些可能需要进一步的解释:
这个参数是控制 FreeBSD 的哪一部分将被保持更新。
默认的是更新源代码,整个基本系统还有内核。
这些部件跟安装时的那些相同,举例来说,
在这里加入 world/games
就会允许打入游戏相关的补丁。
使用 src/bin
则是允许更新
src/bin
目录中的源代码。
最好的选择是把这个选项保留为默认值, 因为如果要修改它去包含一些指定的选项, 就需要用户列出每一个想要更新的项目。 这可能会引起可怕的后果, 因为部分的源代码和二进制程序得不到同步。
添加路径,比如
/bin
或者
/sbin
让这些指定的目录在更新过程中不被修改。
这个选项能够防止本地的修改被
freebsd-update
覆盖。
更新指定目录中的未被修改的配置文件。
用户的任何修改都会使这些文件的自动更新失效。
还有另外一个选项,
KeepModifiedMetadata
,
这个能让 freebsd-update
在合并时保存修改。
一个 freebsd-update
应该尝试合并的配置文件的列表。文件合并的过程是
一系列的 diff(1) 补丁类似于更少选项的 mergemaster(8)
合并的选项是接受,打开一个文本编辑器,或者
freebsd-update
会被中止。
在不能确定的时候,请先备份 /etc
然后接受合并。更多关于 mergemaster
的信息请参阅 第 25.7.11.1 节 “mergemaster
”。
这个目录是放置所有补丁和临时文件的。 用户做一个版本升级的话,请确认此处至少有 1 GB 的可用磁盘空间。
当设置成 yes
时,
freebsd-update
将假设这个
Components
列表时完整的,
并且对此列表以外的项目不会修改。实际上就是
freebsd-update
会尝试更新
Componets
列表里的每一个文件。
安全补丁存储在远程的机器上, 可以使用如下的命令下载并安装:
#
freebsd-update fetch
#
freebsd-update install
如果给内核打了补丁,那么系统需要重新启动。
如果一切都进展顺利,系统就应该被打好了补丁而且
freebsd-update
可由夜间
cron(8) 执行。在 /etc/crontab
中加入以下条目足以完成这项任务:
这条记录是说明每天运行一次
freebsd-update
工具。 用这种方法,
使用了 cron
参数,
freebsd-update
仅检查是否存在更新。
如果有了新的补丁,就会自动下载到本地的磁盘,
但不会自动给系统打上。root
会收到一封电子邮件告知需手动安装补丁。
如果出现了错误,可以使用下面的
freebsd-update
命令回退到上一次的修改:
#
freebsd-update rollback
完成以后如果内核或任何的内核模块被修改的话, 就需要重新启动系统。这将使 FreeBSD 装载新的二进制程序进内存。
freebsd-update
工具只能自动更新 GENERIC
内核。
如果您使用自行联编的内核, 则在 freebsd-update
安装完更新的其余部分之后需要手工重新联编和安装内核。 不过,
freebsd-update
会检测并更新位于 /boot/GENERIC
(如果存在) 中的
GENERIC
内核, 即使它不是当前 (正在运行的)
系统的内核。
保存一份 GENERIC
内核的副本到 /boot/GENERIC
是一个明智的主意。
在诊断许多问题, 以及在
第 25.2.3 节 “重大和次要的更新” 中介绍的使用
freebsd-update
更新系统时会很有用。
除非修改位于
/etc/freebsd-update.conf
中的配置,
freebsd-update
会随其他安装一起对内核的源代码进行更新。
重新联编并安装定制的内核可以以通常的方式来进行。
通过 freebsd-update
发布的更新有时并不会涉及内核。
如果在执行
freebsd-update install
的过程中内核代码没有进行变动,
就没有必要重新联编内核了。 不过, 由于
freebsd-update
每次都会更新
/usr/src/sys/conf/newvers.sh
文件,
而修订版本 (uname -r
报告的
-p
数字) 来自这个文件, 因此,
即使内核没有发生变化, 重新联编内核也可以让 uname(1) 报告准确的修订版本。
在维护许多系统时这样做会比较有帮助,
因为这一信息可以迅速反映机器上安装的软件更新情况。
这个过程会删除旧的目标文件和库,
这将使大部分的第三方应用程序无法删除。
建议将所有安装的 ports 先删除然后重新安装,或者稍后使用
ports-mgmt/portupgrade
工具升级。 大多数用户将会使用如下命令尝试编译:
#
portupgrade -af
这将确保所有的东西都会被正确的重新安装。
请注意环境变量 BATCH
设置成
yes
的话将在整个过程中对所有询问回答
yes
,这会帮助在编译过程中免去人工的介入。
如果正在使用的是定制的内核, 则升级操作会复杂一些。
您会需要将一份 GENERIC
内核的副本放到 /boot/GENERIC
。 如果系统中没有
GENERIC
内核, 可以用以下两种方法之一来安装:
如果只联编过一次内核, 则位于
/boot/kernel.old
中的内核,
就是 GENERIC
的那一个。 只需将这个目录改名为
/boot/GENERIC
即可。
假如能够直接接触机器, 则可以通过 CD-ROM 介质来安装 GENERIC
内核。 将安装盘插入光驱, 并执行下列命令:
#
mount /cdrom
#
cd /cdrom/X.Y-RELEASE
/kernels
#
./install.sh GENERIC
您需要将
替换为您正在使用的版本。
X.Y-RELEASE
GENERIC
内核默认情况下会安装到 /boot/GENERIC
。
如果前面的方法都不可用, 还可以使用源代码来重新联编和安装 GENERIC
内核:
#
cd /usr/src
#
env DESTDIR=/boot/GENERIC make kernel
#
mv /boot/GENERIC/boot/kernel/* /boot/GENERIC
#
rm -rf /boot/GENERIC/boot
如果希望 freebsd-update
能够正确地将内核识别为
GENERIC
, 您必须确保没有对
GENERIC
配置文件进行过任何变动。
此外, 建议您取消任何其他特殊的编译选项 (例如使用空的
/etc/make.conf
)。
上述步骤并不需要使用这个 GENERIC
内核来引导系统。
重大和次要的更新可以由
freebsd-update
命令后指定一个发行版本来执行,
举例来说,下面的命令将帮助你升级到 FreeBSD 8.1:
#
freebsd-update -r 8.1-RELEASE upgrade
在执行这个命令之后,freebsd-update
将会先解析配置文件和评估当前的系统以获得更新系统所需的必要信息。
然后便会显示出一个包含了已检测到与未检测到的组件列表。
例如:
此时,freebsd-update
将会尝试下载所有升级所需的文件。在某些情况下,
用户可能被问及需安装些什么和如何进行之类的问题。
当使用定制内核时, 前面的步骤会产生类似下面的警告:
MYKERNEL
" kernel, which is not a
kernel configuration distributed as part of FreeBSD 8.0-RELEASE.
This kernel will not be updated: you MUST update the kernel manually
before running "/usr/sbin/freebsd-update install"此时您可以暂时安全地无视这个警告。 更新的
GENERIC
内核将在升级过程的中间步骤中使用。
在下载完针对本地系统的补丁之后, 这些补丁会被应用到系统上。
这个过程需要消耗的时间取决于机器的速度和其负载。
这个过程中将会对配置文件所做的变动进行合并 — 这一部分需要用户的参与,
文件可能会自动合并, 屏幕上也可能会给出一个编辑器, 用于手工完成合并操作。
在处理过程中, 合并成功的结果会显示给用户。 失败或被忽略的合并,
则会导致这一过程的终止。 用户可能会希望备份一份
/etc
并在这之后手工合并重要的文件,
例如 master.passwd
和 group
。
系统至此还没有被修改,所有的补丁和合并都在另外一个目录中进行。 当所有的补丁都被成功的打上了以后,所有的配置文件都被合并后, 我们就已经完成了整个升级过程中最困难的部分, 下面就需要用户来安装这些变更了。
一旦这个步骤完成后,使用如下的命令将升级后的文件安装到磁盘上。
#
freebsd-update install
内核和内核模块会首先被打上补丁。 此时必须重新启动计算机。
如果您使用的是定制的内核, 请使用 nextboot(8)
命令来将下一次用于引导系统的内核 /boot/GENERIC
(它会被更新):
#
nextboot -k GENERIC
在使用 GENERIC
内核启动之前,
请确信它包含了用于引导系统所需的全部驱动程序 (如果您是在远程进行升级操作,
还应确信网卡驱动也是存在的)。 特别要注意的情形是,
如果之前的内核中静态联编了通常以内核模块形式存在的驱动程序, 一定要通过
/boot/loader.conf
机制来将这些模块加载到
GENERIC
内核的基础上。 此外,
您可能也希望临时取消不重要的服务、
磁盘和网络挂载等等, 直到升级过程完成为止。
现在可以用更新后的内核引导系统了:
#
shutdown -r now
在系统重新上线后,需要再次运行 freebsd-update
。
升级的状态被保存着,这样 freebsd-update
就无需重头开始,但是会删除所有旧的共享库和目标文件。
执行如下命令继续这个阶段的升级:
#
freebsd-update install
取决与是否有库的版本更新,通常只有 2 个而不是 3 个安装阶段。
现在需要重新编译和安装第三方软件。
这么做的原因是某些已安装的软件可能依赖于在升级过程中已删除的库。
可使用 ports-mgmt/portupgrade
自动化这个步骤,以如下的命令开始:
#
portupgrade -f ruby
#
rm /var/db/pkg/pkgdb.db
#
portupgrade -f ruby18-bdb
#
rm /var/db/pkg/pkgdb.db /usr/ports/INDEX-*.db
#
portupgrade -af
一旦这个完成了以后,再最后一次运行
freebsd-update
来结束升级过程。
执行如下命令处理升级中的所有细节:
#
freebsd-update install
如果您临时用过 GENERIC
内核来引导系统,
现在是按照通常的方法重新联编并安装新的定制内核的时候了。
重新启动机器进入新版本的 FreeBSD 升级过程至此就完成了。
freebsd-update
工具也可被用来对着一个已知完好的 FreeBSD 拷贝测试当前的版本。
这个选项评估当前的系统工具,库和配置文件。
使用以下的命令开始对照:
#
freebsd-update IDS >> outfile.ids
这个命令的名称是 IDS,
它并不是一个像
security/snort
这样的入侵检测系统的替代品。因为
freebsd-update
在磁盘上存储数据,
很显然它们有被篡改的可能。
当然也可以使用一些方法来降低被篡改的可能性,比如设置
kern.securelevel
和不使用时把
freebsd-update
数据放在只读文件系统上,例如 DVD 或
安全存放的外置 USB 磁盘上。
现在系统将会被检查,生成一份包含了文件和它们的 sha256(1)
哈希值的清单,已知发行版中的值与当前系统中安装的值将会被打印到屏幕上。
这就是为什么输出被送到了 outfile.ids
文件。
它滚动的太块无法用肉眼对照,而且会很快填满控制台的缓冲区。
这个文件中有非常长的行,但输出的格式很容易分析。 举例来说,要获得一份与发行版中不同哈希值的文件列表, 已可使用如下的命令:
#
cat outfile.ids | awk '{ print $1 }' | more
/etc/master.passwd
/etc/motd
/etc/passwd
/etc/pf.conf这份输出时删节缩短后的,其实是有更多的文件。
其中有些文件并非人为修改,比如
/etc/passwd
被修改是因为添加了用户进系统。在某些情况下,
还有另外的一些文件,诸如内核模块与
freebsd-update
的不同是因为它们被更新过了。
为了指定的文件或目录排除在外,把它们加到
/etc/freebsd-update.conf
的
IDSIgnorePaths
选项中。
除了前面讨论过的部分之外, 这也能被当作是对升级方法的详细补充。
本文档和其它文档可从这里下载: ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.
如果对于FreeBSD有问题,请先阅读
文档,如不能解决再联系
<questions@FreeBSD.org>.
关于本文档的问题请发信联系
<doc@FreeBSD.org>.