rpath

コンピュータサイエンスにおいて、rpathは実行ファイルまたはライブラリにハードコードされた実行時検索パスを指します。ダイナミックリンクローダーは、 rpathを使用して必要なライブラリを検索します。

具体的には、共有ライブラリへのパスを実行可能ファイル(または別の共有ライブラリ)のヘッダーにエンコードします。このRPATHヘッダー値(実行可能ファイルおよびリンク可能ファイルのフォーマットのヘッダー標準でこのように呼ばれています)は、システムのデフォルトの動的リンク検索パスを上書きまたは補完する場合があります。

実行可能ファイルまたは共有ライブラリのrpathは、ELF.dynamic実行可能ファイルまたは共有ライブラリのセクションにおけるオプションのエントリであり、属性と呼ばれるタイプを持ちます。このエントリは、リンカーによってリンク時にここに保存されます。やなどのツールは、後からこのエントリを作成または変更できます。 DT_RPATHDT_RPATHchrpathpatchelf

背景

現代のコンピュータ実行ファイルは、コードの重複を減らすために、独立した読み込み可能なファイルである動的ライブラリを使用しています。このような実行ファイルを実行すると、ダイナミックリンカーはld.so動的ライブラリのエントリを参照し、実行プログラムが使用できるようにロードします。ライブラリは様々な場所に配置される可能性があるため、ELF形式にはライブラリの場所 DT_RPATHを指定するためのエントリが含まれています。ld.so

ELF用の各種ダイナミックリンカーは、それぞれ異なる方法でこのDT_RPATH属性を実装しています。主な違いは以下のとおりです。

  • DT_RUNPATHrpath のより制限されたバージョンである新しいエントリの処理。
  • 経由で相対パスが使用可能かどうか$ORIGIN
  • $PLATFORM、などの他の変数$LIBが使用可能かどうか。

GNU ld.so

GNU Cライブラリのダイナミックリンカーは、以下の順序で共有ライブラリを検索します。[ 1 ]

  1. DT_RPATHバイナリの動的セクション属性内のパス(コロンで区切られた)(存在する場合)で、DT_RUNPATH属性は存在しません。
  2. LD_LIBRARY_PATH実行ファイルがバイナリでない限り、環境変数 内の (コロンで区切られた) パスはsetuid/setgid無視されます。LD_LIBRARY_PATHオプション--library-path(例/lib/ld-linux.so.2 --library-path $HOME/mylibs myprogram) を使用して動的リンカーを呼び出すことによって上書きできます。
  3. DT_RUNPATHバイナリの動的セクション属性内のパス(コロンで区切られたもの)(存在する場合)。
  4. ldconfigキャッシュファイル(通常は にあります)に基づいて検索します。/etc/ld.so.cacheこのファイルには、拡張ライブラリパス( によって設定/etc/ld.so.conf)で以前に見つかった候補ライブラリのコンパイル済みリストが含まれています。ただし、バイナリが-z nodefaultlibリンカーオプションでリンクされている場合は、デフォルトのライブラリパスにあるライブラリはスキップされます。
  5. 信頼されたデフォルト パスで/lib、次に を実行します/usr/lib。バイナリが-z nodefaultlibリンカー オプションを使用してリンクされている場合、この手順はスキップされます。

これらすべての場所で共有ライブラリが見つからない場合、「共有オブジェクト ファイルを開けません: そのようなファイルまたはディレクトリはありません」というエラーが発生します。

注:

  • readelf -d <binary_name> | grep 'R.*PATH'バイナリファイルのRPATHまたはRUNPATHを表示します。例えばgcc-Wl,-rpath,/custom/rpath/では、RPATHを で指定できます。
  • --inhibit-rpath LISTダイナミックリンカーのオプションは、LIST内のオブジェクト名の属性を無視するように指示します。LIST内のメインプログラムを指定するには、空文字列を指定しますDT_RPATHDT_RUNPATH
  • 環境変数で指定されたライブラリLD_PRELOADと、その後にリストされているライブラリが、/etc/ld.so.preload検索開始前にロードされます。プリロードは、要求されたライブラリの通常の機能の一部(またはすべて)を置き換えるために使用することも、あるいは単に見つからないライブラリを提供するために使用することもできます。
  • 静的ライブラリはリンク時に検索され、ELF ファイルにリンクされますが、実行時には検索されません。

相対パスは特別なトークン によってサポートされており$ORIGIN、実行時に実行ファイルのディレクトリに展開されます。例えば、-Wl,-rpath,$ORIGINは実行ファイルが存在するディレクトリを rpath に追加します。これにより、異なるフォルダ間で自由に移動できるバイナリを作成できます。

GNU ldの役割

GNUリンカー(GNU ld)は「new-dtags」と呼ばれる機能を実装しており、これを使うとLD_LIBRARY_PATH環境変数よりも優先順位の低いrpathを挿入することができる。 [ 2 ]

リンカー(--enable-new-dtags)でnew-dtags機能が有効になっている場合、GNU は属性ldを設定するだけでなく、同じ文字列を属性にDT_RPATHも設定します。実行時に動的リンカーが属性を見つけると、その属性の値を無視します。その結果、最初に属性がチェックされ、属性内のパスは後でのみ検索されます。 DT_RUNPATHDT_RUNPATHDT_RPATHLD_LIBRARY_PATHDT_RUNPATH

ld動的リンカーはDT_RUNPATH、とは異なり、推移的な依存関係の場所を検索しませんDT_RPATH[ 3 ]

リンカーに を指定する代わりに-rpath、環境変数をLD_RUN_PATH設定して同じ効果を得ることもできます。

Solaris ld.so

Solaris、特にSunOS/lib/ld.so 5.8などのシステムの動的リンカーは、属性を参照する前に、変数で指定されたディレクトリ内のライブラリを検索します。 動的ライブラリの読み込みを最初に導入したのはSun Microsystemsです。その後、Sunはldにrpathオプションを追加し、セキュリティ強化機能として必須ライブラリで使用しました。GNU ldも同様の方法で、Sunスタイルの動的ライブラリをサポートしました。 LD_LIBRARY_PATHDT_RPATH

$ORIGINがサポートされています。[ 4 ]

他のダイナミックリンカーでは

ELF 形式:

  • muslの ld.so はDT_RUNPATHと同じように処理します。 、rpath/runpath、そしてデフォルトパスのDT_RPATH順で処理されます。 を理解します。LD_LIBRARY_PATH$ORIGIN
  • bionic libc の ld.so は、いかなる形式の rpath も認識しません。
  • FreeBSD ld.so は の非継承性と低い優先順位を尊重しますDT_RUNPATH。また も処理します$ORIGIN[ 5 ]

非ELF形式:

  • Mach -O形式にも同様のrpathシステムがあり、 で指定されますLC_RPATH。ELFとは異なり、ライブラリ検索でrpathが考慮されるためには、ライブラリリスト内でrpathを明示的に参照する必要があります@rpath[ 6 ]

セキュリティに関する考慮事項

rpath と runpath の使用は、適用された値に攻撃者の制御下にあるディレクトリが含まれる場合、セキュリティリスクをもたらす可能性があります。これには、定義された値が攻撃者が書き込み可能な場所を明示的に参照している場合だけでなく$ORIGIN、 を介して相対パスが使用されている場合や、ディレクトリステートメントが未設定の場合も含まれます。これは、バイナリを騙して、攻撃者の制御下にあるいずれかのディレクトリから悪意のあるライブラリをロードさせるのに利用できます。これは特に setUID バイナリの場合に危険です。なぜなら、これらのバイナリは別の(通常はより高い権限レベル、多くの場合は root)ユーザーとして実行されるからです。[ 7 ]

参考文献

  • chrpathDT_RPATH -実行可能ファイルの属性を変更し、それをDT_RUNPATH属性に変換するツール
  • FreeBSD devel/chrpath ポート- 既存の ELF バイナリの DT_RPATH を変更するためのツール
  • patchELF - ELFDT_RUNPATH実行可能ファイルの動的リンカーと属性を変更するための小さなユーティリティ。