リンカーとライブラリ

関連する依存関係の配置

通常、バンドルされていない製品は、独立した固有の場所にインストールされるように設計されています。この製品は、バイナリ、共有オブジェクト、および関連構成ファイルからなります。たとえば、バンドルされていない製品 ABC は、次の配置をとる場合があります。

図 C–1 バンドルされていない依存関係

バンドルされない依存関係の例。

製品が、/opt の元にインストールされるように設計されていると想定します。通常、ユーザーは、PATH に製品バイナリの位置を示す /opt/ABC/bin を追加する必要があります。各バイナリは、バイナリ内に直接記録された実行パスを使用して、その依存する相手を探します。アプリケーション abc の場合、これは次のようになります。


% dump -Lv abc
  [1]    NEEDED  libA.so.1
  [2]    RUNPATH /opt/ABC/lib

同様に、libA.so.1 の依存関係でも、次のようになります。


% dump -Lv libA.so.1
  [1]    NEEDED  libB.so.1
  [2]    RUNPATH /opt/ABC/lib

この依存関係の表現は、製品が推奨されているデフォルト以外のディレクトリにインストールされるまで正常に作動します。

動的トークン $ORIGIN は、オブジェクトが存在するディレクトリを表わします。この機能は、カーネルによってプロセス開始時に実行時リンカーに提供された新しい補助ベクトルに対応しています。詳細は、getexecname(3C) のマニュアルページを参照してください。この機構を使用すると、バンドルされていないアプリケーションを再定義して、$ORIGIN との相対位置で依存対象の位置を示すことができます。


% dump -Lv abc
  [1]    NEEDED  libA.so.1
  [2]    RUNPATH $ORIGIN/../lib

また、$ORIGIN との関係で libA.so.1 の依存関係を定義することもできます。


% dump -Lv libA.so.1
  [1]    NEEDED  libB.so.1
  [2]    RUNPATH $ORIGIN

この製品が /usr/local/ABC 内にインストールされ、ユーザーの PATH/usr/local/ABC/bin が追加された場合、アプリケーション abc を呼び出すと次のように、パス名検索でその依存関係が探されます。


% ldd -s abc
.....
  find object=libA.so.1; required by abc
    search path=$ORIGIN/../lib  (RPATH from file abc) 
      trying path=/usr/local/ABC/lib/libA.so.1
        libA.so.1 =>     /usr/local/ABC/lib/libA.so.1
 
  find object=libB.so.1; required by /usr/local/ABC/lib/libA.so.1
    search path=$ORIGIN  (RPATH from file /usr/local/ABC/lib/libA.so.1)
      trying path=/usr/local/ABC/lib/libB.so.1
        libB.so.1 =>     /usr/local/ABC/lib/libB.so.1

バンドルされていない製品間の依存関係

依存関係の場所に関する別の問題としては、バンドルされていない製品が別のバンドルされていない製品の共有オブジェクトに対して依存関係を持つときの、基本となるモデルを作成する方法が挙げられます。

たとえば、バンドルされていない製品 XYZ は製品 ABC に対して依存関係を持つ場合があります。この依存関係は、次の図に示すようにホストパッケージインストールスクリプトによって ABC 製品のインストール位置へのシンボリックリンクを生成することで確立できます。

図 C–2 バンドルされていない製品の相互依存関係

バンドルされていない製品の相互依存関係の例。

XYZ 製品のバイナリと共有オブジェクトは安定した参照位置としてシンボリックリンクを使用して、ABC 製品への依存関係を表わします。アプリケーション xyz の場合、これは次のようになります。


% dump -Lv xyz
  [1]    NEEDED  libX.so.1
  [2]    NEEDED  libA.so.1
  [3]    RUNPATH $ORIGIN/../lib:$ORIGIN/../ABC/lib

libX.so.1 の依存関係でも同様に、次のようになります。


% dump -Lv libX.so.1
  [1]    NEEDED  libY.so.1
  [2]    NEEDED  libC.so.1
  [3]    RUNPATH $ORIGIN:$ORIGIN/../ABC/lib

この製品が /usr/local/XYZ 内にインストールされている場合は、次のシンボリックリンクを確立するために、インストール後実行スクリプトが必要です。


% ln -s ../ABC /usr/local/XYZ/ABC

ユーザーの PATH/usr/local/XYZ/bin が追加される場合、アプリケーション xyz の呼び出しによって、次のようにパス名検索でその依存関係が探されます。


% ldd -s xyz
.....
  find object=libX.so.1; required by xyz
    search path=$ORIGIN/../lib:$ORIGIN/../ABC/lib  (RPATH from file xyz)
      trying path=/usr/local/XYZ/lib/libX.so.1
        libX.so.1 =>     /usr/local/XYZ/lib/libX.so.1
 
  find object=libA.so.1; required by xyz
    search path=$ORIGIN/../lib:$ORIGIN/../ABC/lib  (RPATH from file xyz)
      trying path=/usr/local/XYZ/lib/libA.so.1
      trying path=/usr/local/ABC/lib/libA.so.1
        libA.so.1 =>     /usr/local/ABC/lib/libA.so.1
 
  find object=libY.so.1; required by /usr/local/XYZ/lib/libX.so.1
     search path=$ORIGIN:$ORIGIN/../ABC/lib \
                (RPATH from file /usr/local/XYZ/lib/libX.so.1)
      trying path=/usr/local/XYZ/lib/libY.so.1
        libY.so.1 =>     /usr/local/XYZ/lib/libY.so.1
 
  find object=libC.so.1; required by /usr/local/XYZ/lib/libX.so.1
     search path=$ORIGIN:$ORIGIN/../ABC/lib \
                (RPATH from file /usr/local/XYZ/lib/libX.so.1)
      trying path=/usr/local/XYZ/lib/libC.so.1
      trying path=/usr/local/ABC/lib/libC.so.1
        libC.so.1 =>     /usr/local/ABC/lib/libC.so.1
 
  find object=libB.so.1; required by /usr/local/ABC/lib/libA.so.1
     search path=$ORIGIN  (RPATH from file /usr/local/ABC/lib/libA.so.1)
       trying path=/usr/local/ABC/lib/libB.so.1
        libB.so.1 =>     /usr/local/ABC/lib/libB.so.1

セキュリティ

セキュアプロセスでは、$ORIGIN 文字列の拡張は、それがトラストディレクトリに拡張されるときに限り許可されます。他の相対パス名は、セキュリティリスクを伴います。

$ORIGIN/../lib のようなパスは一定の場所 (実行可能プログラムの場所で特定される) を指しているように見えますが、それは正しくありません。同じファイルシステム内の書き込み可能なディレクトリにより、$ORIGIN を使用するセキュアプログラムが不当に利用される可能性があります。

次の例は、$ORIGIN がセキュアプロセス内で任意に拡張された場合、セキュリティ侵入が生じる可能性があることを示しています。


% cd /worldwritable/dir/in/same/fs
% mkdir bin lib
% ln $ORIGIN/bin/program bin/program
% cp ~/crooked-libc.so.1 lib/libc.so.1
% bin/program
..... using crooked-libc.so.1

ユーティリティ crle(1) を使用すれば、セキュアアプリケーションによる $ORIGIN の使用を可能するトラストディレクトリを指定できます。この方法を使用する場合には、管理者は、ターゲットディレクトリを悪意のある侵入から適切に保護する必要があります。