特定のソフトウェアに利用可能なセキュリティ修正がある場合、通常、yum や apt-get などのパッケージ管理ツールを使用してバイナリ アップグレードを行います。
ただし、ソース コードからコンパイルしてソフトウェアをインストールした場合があります。
そのような状況では、ソフトウェアにセキュリティ修正をどのように適用しますか?
答えは、セキュリティ パッチをダウンロードして元のソース コードに適用し、ソフトウェアを再コンパイルすることです。
このチュートリアルでは、diff を使用してパッチ ファイルを作成し、patch コマンドを使用して適用する方法について説明します。
パッチ ファイルは、同じファイル (または同じソース ツリー) の 2 つのバージョンの違いを含むテキスト ファイルです。パッチファイルは、diff コマンドを使用して作成されます。
1. diff を使用してパッチ ファイルを作成する
これを理解するために、hello.c という小さな C プログラムを作成してみましょう
#include <stdio.h> int main() { printf("Hello World\n"); }
次に、hello.c を hello_new.c にコピーします
$ cp hello.c hello_new.c
以下に示すように hello_new.c を編集して、小さな変更を加えます。
#include <stdio.h> int main(int argc, char *argv[]) { printf("Hello World\n"); return 0; }
最後に、以下に示すように diff コマンドを使用してパッチ ファイルを作成します。
$ diff -u hello.c hello_new.c > hello.patch
上記のコマンドは、「hello.patch」という名前のパッチ ファイルを作成します。
--- hello.c 2014-10-07 18:17:49.000000000 +0530 +++ hello_new.c 2014-10-07 18:17:54.000000000 +0530 @@ -1,5 +1,6 @@ #include <stdio.h> -int main() { +int main(int argc, char *argv[]) { printf("Hello World\n"); + return 0; }
2.パッチ コマンドを使用してパッチ ファイルを適用
「パッチ」コマンドは、パッチ ファイルを入力として取り、1 つまたは複数の元のファイルに違いを適用して、パッチが適用されたバージョンを生成します。
patch -p[num] < patchfile patch [options] originalfile patchfile
以下に示すパッチ コマンドを使用して、hello.patch を元の hello.c ソース コードに適用します。
$ patch < hello.patch patching file hello.c
hello.patch ファイルには、パッチを適用するファイルの名前が含まれています。ファイルにパッチが適用されると、hello.c と hello_new.c の両方にコンテンツが含まれます。
3.ソース ツリーからパッチを作成する
上記の例は非常に単純であるため、1 つのファイルのみで機能します。 「openvpn」ソース コードを例として、完全なソース ツリーのパッチを作成して適用する方法を説明します。
openvpn の 2 つのバージョン、openvpn-2.3.2 と openvpn-2.3.4 をダウンロードしました。
tar -xvzf openvpn-2.3.2.tar.gz tar -xvzf openvpn-2.3.4.tar.gz
次のコマンドを使用してパッチを作成します。
diff -Naur /usr/src/openvpn-2.3.2 /usr/src/openvpn-2.3.4 > openvpn.patch
上記のコマンドは再帰的に動作して違いを見つけ、それらの違いをパッチ ファイルに配置します。
4.パッチ ファイルをソース コード ツリーに適用
次のパッチ コマンドを使用して、ソース ツリーにパッチを適用できます。
# patch -p3 < /root/openvpn.patch patching file openvpn-2.3.2/aclocal.m4 patching file openvpn-2.3.2/build/Makefile.in patching file openvpn-2.3.2/build/msvc/Makefile.in ...
/usr/src/ からコマンドを実行していることに注意してください。パッチ ファイルには、すべてのファイル名が絶対パス形式 (ルートから) で含まれています。そのため、「-p」オプションなしで /usr/src から実行すると、正しく動作しません。
-p3 は、パッチ コマンドに、パッチ ファイルに存在するファイル名から先頭の 3 つのスラッシュをスキップするように指示します。この場合、パッチ ファイルのファイル名は「/usr/src/openvpn-2.3.2/aclocal.m4」です。これは、「-p3」を指定したため、先頭に 3 つのスラッシュがあり、つまり /usr/src/ が無視されるまでです。
5. -b を使用してパッチを適用する前にバックアップを取ります
以下に示すように、-b オプションを使用してパッチ コマンドを適用する前に、元のファイルのバックアップを作成できます。
$ patch -b < hello.patch patching file hello.c
これで、元の hello.c のバックアップである「hello.c.orig」というファイル名が作成されます。
以下に示すように、-V を使用してバックアップ ファイル名の形式を決定することもできます。これで、ファイル名は「hello.c.~1~」になります。
$ patch -b -V numbered < hello.patch patching file hello.c
6.適用せずにパッチを検証する (ドライラン パッチ ファイル)
以下に示すように、–dry-run オプションを使用してファイルにパッチを適用せずに、パッチ コマンドをドライランして、エラーが発生するかどうかを確認できます。
$ patch --dry-run < hello.patch patching file hello.c
hello.c がまったく変更されていないことがわかります。
7.すでに適用されているパッチを元に戻す (パッチを元に戻す)
-R オプションを使用して、既に適用されているパッチを元に戻すことができます。
$ patch < hello.patch patching file hello.c $ ls -l hello.c -rw-r--r-- 1 lakshmanan users 94 2014-10-07 20:05 hello.c $ patch -R < hello.patch patching file hello.c $ ls -l hello.c -rw-r--r-- 1 lakshmanan users 62 2014-10-07 20:04 hello.c
-R オプションを使用すると、既に適用されているパッチが逆になっていることがファイルサイズからわかります。