Go to main content
Oracle® Solaris 11.3 リンカーとライブラリガイド

印刷ビューの終了

更新: 2015 年 10 月
 
 

関連する依存関係の配置

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

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

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

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

$ cc -o abc abc.c -R/opt/ABC/lib -L/opt/ABC/lib -lA
$ elfdump -d abc | egrep 'NEEDED|RUNPATH'
     [0]  NEEDED           0x1b5                libA.so.1
     ....
     [4]  RUNPATH          0x1bf                /opt/ABC/lib

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

$ cc -o libA.so.1 -G -Kpic A.c -R/opt/ABC/lib -L/opt/ABC/lib -lB
$ elfdump -d libA.so.1 | egrep 'NEEDED|RUNPATH'
     [0]  NEEDED            0x96                libB.so.1
     [4]  RUNPATH           0xa0                /opt/ABC/lib

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

動的トークン $ORIGIN は、オブジェクトが存在するディレクトリに展開されます。このトークンは、フィルタ、「実行パス」、または依存関係の定義に利用できます。この機構を使用すると、バンドルされていないアプリケーションを再定義して、$ORIGIN との相対位置で依存対象の位置を示すことができます。

$ cc -o abc abc.c '-R$ORIGIN/../lib' -L/opt/ABC/lib -lA
$ elfdump -d abc | egrep 'NEEDED|RUNPATH'
     [0]  NEEDED           0x1b5                libA.so.1
     ....
     [4]  RUNPATH          0x1bf                $ORIGIN/../lib

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

$ cc -o libA.so.1 -G -Kpic A.c '-R$ORIGIN' -L/opt/ABC/lib -lB
$ elfdump -d lib/libA.so.1 | egrep 'NEEDED|RUNPATH'
     [0]  NEEDED            0x96                libB.so.1
     [4]  RUNPATH           0xa0                $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  (RUNPATH/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  (RUNPATH/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 トークンを含むオブジェクトは、シンボリックリンクを使用すると参照できます。この場合、オブジェクトの真の起点を判断するために、シンボリックリンクは完全に解決されます。

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

依存関係の場所に関するもう 1 つの問題は、バンドルされていない製品同士の依存関係を表現するモデルを、どのようにして確立するかです。

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

図 5  バンドルされていない製品の「相互依存関係」

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

XYZ 製品のバイナリおよび共有オブジェクトは、シンボリックリンクを使用して、ABC 製品との依存関係を表現できます。このリンクはその時点で、安定した参照点になります。アプリケーション xyz の場合、この「実行パス」は次のようになります。

$ cc -o xyz xyz.c '-R$ORIGIN/../lib:$ORIGIN/../ABC/lib' \
    -L/opt/ABC/lib -lX -lA
$ elfdump -d xyz | egrep 'NEEDED|RUNPATH'
     [0]  NEEDED           0x1b5               libX.so.1
     [1]  NEEDED           0x1bf               libA.so.1
     ....
     [2]  NEEDED           0x18f               libc.so.1
     [5]  RUNPATH          0x1c9               $ORIGIN/../lib:$ORIGIN/../ABC/lib

libX.so.1 の依存関係でも同様に、この実行パスは次のようになります。

$ cc -o libX.so.1 -G -Kpic X.c '-R$ORIGIN:$ORIGIN/../ABC/lib' \
    -L/opt/ABC/lib -lY -lC
$ elfdump -d libX.so.1 | egrep 'NEEDED|RUNPATH'
     [0]  NEEDED           0x96                libY.so.1
     [1]  NEEDED           0xa0                libC.so.1
     [5]  RUNPATH          0xaa                $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  (RUNPATH/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  (RUNPATH/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 \
               (RUNPATH/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 \
               (RUNPATH/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  (RUNPATH/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

注 - オブジェクトの起点は、実行時に RTLD_DI_ORIGIN フラグが付いた dlinfo(3C) を使用すると取得できます。この起点のパスを使用すると、関連製品の階層から追加ファイルにアクセスできます。

セキュリティー

セキュアなプロセスでは、$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 の使用を可能にするトラストディレクトリを指定できます。この方法を使用する場合には、管理者は、ターゲットディレクトリを悪意のある侵入から適切に保護する必要があります。