18.2. FreeBSD Update

寄稿: Tom Rhodes. ベースとなったノートの提供: Colin Percival.

セキュリティパッチを適用することは、コンピュータソフトウェア、 特にオペレーティングシステムを管理する上で重要な役割を果たします。 しかしながら、FreeBSD においては、 このプロセスは簡単なものではありませんでした。 ソースコードにパッチを当て、コードからバイナリを再構築し、 バイナリを再びインストールする必要がありました。

現在では FreeBSD に freebsd-update と呼ばれるユーティリティが追加され、状況は変わりました。 このユーティリティは 2 つの機能を持っています。 第一に、FreeBSD ベースシステムのビルドやインストールを行うことなく、 バイナリによってセキュリティおよび eratta アップデートできます。 第二に、このユーティリティはマイナーおよびメジャーリリースのアップグレードに対応しています。

注意: バイナリアップデートは、 セキュリティチームがサポートしているすべてのアーキテクチャとリリースで利用できます。 新しいリリースにアップデートする前に、現在のリリースのアナウンスに目を通し、 アップデートしようとしているリリースに対して重要な情報がないかどうかを確認してください。 これらのアナウンスは http://www.FreeBSD.org/ja/releases/ で確認できます。

もし crontab の中に freebsd-update の機能が含まれていたら、 以下の作業を行うまでは無効にしておいてください。

18.2.1. 設定ファイル

設定ファイル /etc/freebsd-update.conf をデフォルトからきめ細かく調整して、 アップデートプロセスを制御するユーザもいます。 この作業は良く文書化されていますが、 以下のいくつかの項目については説明が必要でしょう。

# Components of the base system which should be kept updated.
Components src world kernel

このパラメータは、FreeBSD のどの部分を最新に維持するかを設定します。 デフォルトではソースコード、ベースシステム全体、そしてカーネルをアップデートします。 Components に設定できる項目は、インストール時に選択できるものと同じです。 たとえば、ここで world/games を追加すると、 game にパッチが当たるようになります。 src/bin を追加すると、 src/bin ソースコードのアップデートを許可します。

この部分についてはデフォルトのままにしておき、 アップデートしたい項目をユーザがリストに加える形にするのがベストでしょう。 ソースコードとバイナリが同期していないと、 悲惨な結果をもたらす可能性があります。

# Paths which start with anything matching an entry in an IgnorePaths
# statement will be ignored.
IgnorePaths

アップデートで変更されてはいけない特定のディレクトリ、 /bin/sbin 等のパスを追加してください。 このオプションは、ローカルの変更点を freebsd-update が上書きすることを防ぐ目的にも利用できます。

# Paths which start with anything matching an entry in an UpdateIfUnmodified
# statement will only be updated if the contents of the file have not been
# modified by the user (unless changes are merged; see below).
UpdateIfUnmodified /etc/ /var/ /root/ /.cshrc /.profile

指定したディレクトリにある設定ファイルを、 ローカルで変更されていない場合のみアップデートします。 ユーザがこれらのファイルを変更していると、 これらのファイルの自動アップデートは無効になります。 他に、KeepModifiedMetadata という別のオプションが存在します。 このオプションは、freebsd-update がマージ中に変更点を保存するようにします。

# When upgrading to a new FreeBSD release, files which match MergeChanges
# will have any local changes merged into the version from the new release.
MergeChanges /etc/ /var/named/etc/

freebsd-update がマージすべきファイルが存在するディレクトリの一覧です。 ファイルのマージのプロセスは、 mergemaster(8) と同様 diff(1) パッチの連続です。 マージを承認するか、エディタを起動するか、 freebsd-update を中断するかどうかを選んでください。 もし、心配な点があれば、 /etc をバックアップしてからマージを承認してください。 mergemaster コマンドの詳細な情報については、 項18.7.11.1 で確認してください。

# Directory in which to store downloaded updates and temporary
# files used by FreeBSD Update.
# WorkDir /var/db/freebsd-update

ここではすべてのパッチや一次ファイルを置くディレクトリを指定しています。 バージョンをアップグレードするのであれば、 この場所には少なくともギガバイトの空き容量が必要です。

# When upgrading between releases, should the list of Components be
# read strictly (StrictComponents yes) or merely as a list of components
# which *might* be installed of which FreeBSD Update should figure out
# which actually are installed and upgrade those (StrictComponents no)?
# StrictComponents no

yes に設定すると、 freebsd-updateComponents のリストが完全に正しいと判断し、 このリスト以外の変更点については取り扱いません。 freebsd-update は、効率的に Components リストに属するファイルをアップデートします。

18.2.2. セキュリティパッチ

セキュリティパッチはリモートマシンに保存されており、 以下のコマンドを実行すると、ダウンロードしてインストールします。

# freebsd-update fetch
# freebsd-update install

カーネルにパッチが当たった場合には、システムを再起動する必要があります。 すべてがうまく実行でき、システムにパッチが当たるようであれば、 毎晩の cron(8) ジョブとして freebsd-update を実行してもよいでしょう。 このタスクを実行できるようにするには、 以下のエントリを /etc/crobntab に追加してください。

@daily                                  root    freebsd-update cron

このエントリは、毎日一度 freebsd-update ユーティリティを実行することを意味します。 このように cron に記述すると、 freebsd-update はアップデートが存在するときだけ確認します。 パッチが存在すると、 自動的にローカルディスクにダウンロードされますが、適用はされません。 ダウンロードされたパッチを手動でインストールすることが必要で、このことは root 宛てにメールで通知されます。

うまく行かなかった場合には、freebsd-update を以下のように実行すると、最後の変更までロールバックできます。

# freebsd-update rollback

カーネルまたはカーネルモジュールがアップデートされた場合には、 完了後にシステムを再起動してください。 この作業によって、FreeBSD がバイナリをメモリに読み込みます。

freebsd-update ユーティリティが自動的にアップデートするカーネルは GENERIC のみです。 カスタムカーネルを使っている場合には、freebsd-update が他の部分をアップデートした後、 カーネルを再構築し、もう一度インストールする必要があります。 GENERIC カーネルが /boot/GENERIC に存在する場合には、 freebsd-update により (現在のシステムで実行されているカーネルでなくとも) アップデートされます。

注意: GENERIC カーネルを、常に /boot/GENERIC に置いておくことは良い考えです。 さまざまな問題を解決する際や、 項18.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) がシステムの正確なパッチレベルを報告するようになります。 各システムにインストールされているアップデートをすばやく把握できるようになるので、 特に複数のシステムを管理するときに助けとなります。

18.2.3. メジャーおよびマイナーバージョンのアップグレード

FreeBSD のマイナーバージョン間のアップグレード、 たとえば、FreeBSD�9.0 から FreeBSD�9.1 へのアップグレードは、 マイナーバージョン アップグレードと呼ばれます。 通常は、マイナーバージョンのアップグレードを行った後でも、 インストールされているアプリケーションは問題なく動きます。

メジャーバージョン アップグレードは、 FreeBSD�8.X から FreeBSD�9.X へのアップグレードといった、 FreeBSD のメジャーバージョンが変わるようなアップグレードのことです。 メジャーバージョンのアップグレードでは、 古いオブジェクトファイルやライブラリが削除され、 これらに依存する多くのサードパーティ製アプリケーションに影響を与える可能性があります。 インストールされているすべての ports を削除して再インストールするか、 メジャーアップグレード後、 ports-mgmt/portupgrade ユーティリティを使ってアップグレードすることが推奨されています。 インストールされているアプリケーションのブルートフォース的な再構築は、 以下のコマンドにより行うことができます。

# portupgrade -af

このコマンドは、すべての ports を適切に再インストールしようとします。 BATCH 環境変数を yes に設定しておくと、 アップデートプロセスの途中の質問に対し yes と答えるようになるので、 ビルドプロセスでの手動操作を省略できます。

18.2.3.1. カスタムカーネルの取り扱い

カスタムカーネルを使用している場合には、アップグレードのプロセスは、 幾分複雑となります。 アップグレードの手順は FreeBSD のバージョンによって変わります。

18.2.3.1.1. FreeBSD�8.X 以前のシステムにおけるカスタムカーネル

GENERIC カーネルが /boot/GENERIC に置かれている必要があります。 もし GENERIC カーネルがシステムに存在しない場合には、 以下のどれかの方法で用意してください。

  • ただ一度だけカスタムカーネルを構築したのであれば、 /boot/kernel.oldGENERIC カーネルそのものです。 ただ単にこのディレクトリの名前を /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 カーネルで再起動する必要はありません。

18.2.3.1.2. FreeBSD�9.X 以降のシステムにおけるカスタムカーネル

  • ただ一度だけカスタムカーネルを構築したのであれば、 /boot/kernel.oldGENERIC カーネルそのものです。 ただ単にこのディレクトリの名前を /boot/kernel へと変更してください。

  • コンピュータへの物理的なアクセスが可能であれば、 CD-ROM メディアから GENERIC カーネルをインストールできます。 インストールディスクを挿入して、以下のコマンドを実行してください。

    # mount /cdrom
    # cd /cdrom/usr/freebsd-dist
    # tar -C/ -xvf kernel.txz boot/kernel/kernel
    
  • 上記の方法が失敗するのであれば、 GENERIC カーネルをソースから再構築して、 インストールしてください。

    # cd /usr/src
    # make kernel
    

    freebsd-update は、このカーネルを GENERIC カーネルとして扱います。 GENERIC コンフィグレーションファイルは、 とにかく変更してはいけません。 また、特別なオプションを指定しない (/etc/make.conf が空であることが望ましい) で構築してください。

この時点で GENERIC カーネルで再起動する必要はありません。

18.2.3.2. アップグレードを行う

freebsd-update によるメジャー、またはマイナーバージョンのアップデートでは、 リリースバージョンをターゲットにして実行します。 たとえば、FreeBSD�8.1 にアップデートするには以下のコマンドを実行してください。

# freebsd-update -r 8.1-RELEASE upgrade

コマンドを実行すると、freebsd-update は設定ファイルと現在のシステムを評価し、 システムをアップデートするために必要な情報を収集します。 画面には、どのコンポーネントが認識され、 どのコンポーネントが認識されていないかといったリストが表示されます。 たとえば以下のように表示されます。

Looking up update.FreeBSD.org mirrors... 1 mirrors found.
Fetching metadata signature for 8.0-RELEASE from update1.FreeBSD.org... done.
Fetching metadata index... done.
Inspecting system... done.

The following components of FreeBSD seem to be installed:
kernel/smp src/base src/bin src/contrib src/crypto src/etc src/games
src/gnu src/include src/krb5 src/lib src/libexec src/release src/rescue
src/sbin src/secure src/share src/sys src/tools src/ubin src/usbin
world/base world/info world/lib32 world/manpages

The following components of FreeBSD do not seem to be installed:
kernel/generic world/catpages world/dict world/doc world/games
world/proflibs

Does this look reasonable (y/n)? y

ここで、freebsd-update はアップグレードに必要なすべてのファイルをダウンロードします。 何をインストールし、どのように進むかといった質問をされることもあります。

カスタムカーネルを使っていると、 上記のステップで以下のような警告が表示されます。

WARNING: This system is running a "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.passwdgroup のような重要なファイルを後で手動でマージする方もいます。

注意: すべてのパッチは別のディレクトリでマージされており、 まだ、システムには反映されていません。 すべてのパッチが正しく適用され、 すべての設定ファイルがマージされてプロセスがスムーズに進んでいる時には、 ユーザによる変更点のコミットは必要ありません。

このプロセスが終わったら、 以下のコマンドを用いて、アップグレードをディスクに反映してください。

# 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

注意: 使用しているライブラリのバージョン番号の付けられ方によって、 3 つのインストールフェーズが 2 つになる場合もあります。

18.2.3.3. メジャーバージョンアップグレード後の ports の再構築

メジャーバージョンアップグレードを行った後では、 すべてのサードパーティ製のソフトウェアを再構築し、 再インストールする必要があります。 この作業が必要なのは、インストールされているソフトウェアが、 アップグレードの際に削除されたライブラリに依存している可能性があるためです。 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 を立ち上げてください。 これでアップグレードのプロセスは完了です。

18.2.4. システムの状態の比較

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.confIDSIgnorePaths オプションに追加してください。

以前に議論した方法とは別に、 このシステムを入念なアップグレード方法の一部として用いることができます。

本文書、および他の文書は ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/ からダウンロードできます。

FreeBSD に関する質問がある場合には、ドキュメント を読んだ上で <[email protected]> まで (英語で) 連絡してください。
本文書に関する質問については、<[email protected]> まで電子メールを (英語で) 送ってください。