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
また、net
実行可能ファイル自体のcap_dac_override
機能に継承可能フラグを設定してみました。
~ $ 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
プログラムは他にもいくつかのことを行いますが、ユーザーに広範囲の権限を与えるのは危険な場合があります。
私は明らかに継承の仕組みを誤解しています。ラッパーをセットアップして、機能を置換プロセスに渡して使用できるようにする方法を理解できていないようです。私は、manページと、それがどのように機能するかについての無数の他のドキュメントを読みましたすべきと私はそれが説明していることをやっていると思っていました。
ラッパーに+ iを設定しても、ラッパープロセスのCAP_INHERITABLE
セットに機能が追加されないことがわかります。 exec
を通過しました。したがって、execl
を呼び出す前に、CAP_DAC_OVERRIDE
をCAP_INHERITABLE
に手動で追加する必要がありました。
#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
私は今何が起こっているのかを完全に理解していると思います:
CAP_DAC_OVERRIDE
が必要です。CAP_DAC_OVERRIDE
/CAP_INHERITABLE
を使用して、cap_set_flag
にcap_set_proc
を明示的に追加する必要があります。net
ファイルは、実際にラッパーからCAP_DAC_OVERRIDE
セットに機能を継承できるように、継承可能なセットにCAP_PERMITTED
が含まれている必要があります。また、自動的にCAP_EFFECTIVE
にプロモートされるように、有効ビットを設定する必要があります。両方が必要だと思います。
setcap cap_dac_override+pe ./registerdns
setcap cap_dac_override+i /usr/bin/net
pe
のregisterdns
フラグは、プログラムを実行すると機能が取得されることを示します。 i
のnet
フラグは、呼び出し元のプログラムから機能を継承できることを示しています。