web-dev-qa-db-ja.com

環境変数を読み取るためのLinux機能?

非特権ユーザーとしてサービスを実行したいのですが、システムポート番号(つまり、1024未満)にバインドする必要があるので、setcap 'cap_net_bind_service=+ep' <path for service>を指定します。

問題は、起動時にサービスが環境変数を読み取り、何らかの理由でcap_net_bind_serviceが含まれている場合にそれを実行できないことです。したがって、実行可能ファイルの2つのコピーを使用して、1つはcap_net_bind_serviceを使用し、1つは使用せず、1つだけ使用すると、環境変数を読み取ることができます。

これは、env varsを読み取ることができるデフォルトの機能セットがあるかのようですが、cap_net_bind_serviceを指定すると、exeはその機能を失います。それは正しいですか、それとも何か他のことが起こっていますか?サービスが環境変数を読み取れるようにするには、サービスにどのような追加機能を与える必要がありますか? capability.h には、「env varの読み取りを許可する」としてジャンプするものはありませんか?

1
code9016

私はそれの底に着きました。簡単に言うと、バイナリは環境変数にアクセスするために secure_getenv を使用しています。

これは、バイナリが「セキュアな実行」モード(AT_SECURE=1)で実行されている場合、変数にアクセスする代わりにnullを返します。機能を設定すると、このモードで実行されます。

バイナリがreadelfを使用してsecure_getenvを使用していることを確認します。

readelf -a <path for service> | grep getenv
00000040ac28  004b00000007 R_X86_64_JUMP_SLO 0000000000000000 secure_getenv@GLIBC_2.17 + 0
00000040ad90  007a00000007 R_X86_64_JUMP_SLO 0000000000000000 getenv@GLIBC_2.2.5 + 0
    75: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND secure_getenv@GLIBC_2.17 (6)
   122: 0000000000000000     0 FUNC    GLOBAL DEFAULT  UND getenv@GLIBC_2.2.5 (2)

環境変数を使用して安全な実行モードで実行されていることを確認してください(皮肉なことに!)LD_DEBUG=allまたはLD_SHOW_AUXVman ld.so を参照)。

そうでない場合、LD_SHOW_AUXVAT_SECUREを0に設定して出力を生成します。セキュア実行モードで実行している場合、LD_SHOW_AUXVからの出力はありません。

通常、LD_DEBUGからの出力は、セキュリティで保護された実行モードで実行されている/されていない場合にもあります。ただし、/etc/suid-debugが存在する場合(空のファイル、タッチで作成)、LD_DEBUGは安全な実行モードで実行しているときに出力を生成します。

man getauxvalとセキュア実行モードの詳細については、 AT_SECURE を参照してください。

1
code9016