非特権ユーザーとしてサービスを実行したいのですが、システムポート番号(つまり、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の読み取りを許可する」としてジャンプするものはありませんか?
私はそれの底に着きました。簡単に言うと、バイナリは環境変数にアクセスするために 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_AUXV
( man ld.so
を参照)。
そうでない場合、LD_SHOW_AUXV
はAT_SECURE
を0に設定して出力を生成します。セキュア実行モードで実行している場合、LD_SHOW_AUXV
からの出力はありません。
通常、LD_DEBUG
からの出力は、セキュリティで保護された実行モードで実行されている/されていない場合にもあります。ただし、/etc/suid-debug
が存在する場合(空のファイル、タッチで作成)、LD_DEBUG
は安全な実行モードで実行しているときに出力を生成します。
man getauxval
とセキュア実行モードの詳細については、 AT_SECURE
を参照してください。