exec経由で機能を渡す

exec経由で機能を渡す

exec()他のプロセスがすでに処理しているプロセスにLinux機能がどのように渡されるかを理解したいと思います。私が読んだことによれば、exec以降の特定の機能を維持するために継承可能なセットにする必要があります。しかし、コレクションがどのように満たされるのかはよくわかりません。

私の目標は、通常、root権限を必要とする一般ユーザーとしてプログラムを実行できることです。必要な機能は、cap_dac_override個人ファイルを読み取ることができる必要があることです。他の機能を提供したくありません。

これは私のラッパーです。

#include <unistd.h>

int main(int argc, char *argv[]) {
    return execl("/usr/bin/net", "net", "ads", "dns", "register", "-P", NULL);
}

これは、生成された実行可能ファイルにsetuid権限を設定するときに機能します。

~ $ sudo chown root: ./registerdns
~ $ sudo chmod u+s ./registerdns
~ $ ./registerdns 
Successfully registered hostname with DNS

しかし、setuidの代わりに関数を使用したいと思います。cap_dac_overrideラッパーに関数を設定しようとしています。

~ $ sudo setcap cap_dac_override=eip ./registerdns
~ $ ./registerdns 
Failed to open /var/lib/samba/private/secrets.tdb
ERROR: Unable to open secrets database

cap_dac_overrideまた、実行可能ファイル自体の関数に継承可能フラグを設定してみましたnet

~ $ sudo setcap cap_dac_override=eip ./registerdns
~ $ sudo setcap cap_dac_override=i /usr/bin/net
~ $ ./registerdns 
Failed to open /var/lib/samba/private/secrets.tdb
ERROR: Unable to open secrets database

正確なパラメータセットでのみ機能を使用できるように、ラッパーを使用する必要があります。プログラムは、netユーザーに多すぎる権限が与えられた場合に危険にさらされる可能性のあるいくつかのタスクも実行します。

私は継承がどのように機能するのかはっきりと誤解しました。ラッパーがその機能を使用できるように交換プロセスに渡すようにラッパーを設定する方法がわからないようです。私はそれを使用する方法のマニュアルページと他の多くのドキュメントを読んだ。しなければならない働きながら私はそれが説明することをしていると思いました。

答え1

ラッパーに+iを設定するといいえラッパープロセスのコレクションに機能を追加してCAP_INHERITABLE渡さないようにしますexec。したがって、呼び出す前に手動で追加する必要がありますCAP_DAC_OVERRIDECAP_INHERITABLEexecl

#include <sys/capability.h>
#include <stdio.h>
#include <unistd.h>

int main(int argc, char **argv[]) {
    cap_t caps = cap_get_proc();
    printf("Capabilities: %s\n", cap_to_text(caps, NULL));
    cap_value_t newcaps[1] = { CAP_DAC_OVERRIDE, };
    cap_set_flag(caps, CAP_INHERITABLE, 1, newcaps, CAP_SET);
    cap_set_proc(caps);
    printf("Capabilities: %s\n", cap_to_text(caps, NULL));
    cap_free(caps);
    return execl("/usr/bin/net", "net", "ads", "dns", "register", "-P", NULL);
}

cap_dac_overrideまた、許可されたファイル機能設定を追加し、/usr/bin/net有効なビットを設定する必要がありました。

~ $ sudo setcap cap_dac_override=p ./registerdns
~ $ sudo setcap cap_dac_override=ei /usr/bin/net
~ $ ./registerdns
Capabilities = cap_dac_override+p
Capabilities = cap_dac_override+ip
Successfully registered hostname with DNS

私は今何が起こっているのかを正確に理解したと思います。

  1. CAP_DAC_OVERRIDEラッパーは、継承可能なセットに追加できるように、許可されたセットになければなりません。
  2. ラッパーのプロセス継承可能セットはファイル継承可能セットとは異なるため、ファイルに+iを設定することは役に立ちません。 /を使用してラッパーを明示的CAP_DAC_OVERRIDEに追加する必要があります。CAP_INHERITABLEcap_set_flagcap_set_proc
  3. ファイルが実際にラッパーの機能をそのセットに継承できるように、継承可能なセットにnet含める必要があります。また、自動的に昇格するには有効なビットセットが必要です。CAP_DAC_OVERRIDECAP_PERMITTEDCAP_EFFECTIVE

答え2

私の考えには両方が必要だと思います。

setcap cap_dac_override+pe ./registerdns
setcap cap_dac_override+i /usr/bin/net

pe上記の記号は、registerdnsプログラムを実行するとその機能が得られることを示しています。ionフラグは、net呼び出し元プログラムから機能を継承できることを示します。

関連情報