Linux の機能が、別の機能によって 'd されたプロセスにどのように渡されるかを理解しようとしていますexec()
。私が読んだところによると、exec 後に機能を保持するには、継承可能なセットに含まれている必要があります。ただし、そのセットがどのように設定されるかはわかりません。
私の目標は、通常はルート権限が必要なプログラムを一般ユーザーとして実行できるようにすることです。必要な権限は、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_OVERRIDE
CAP_INHERITABLE
execl
#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
、継承可能なセットに追加できるように、許可されたセットを必要とします。 - ラッパーのプロセス継承可能セットはファイル継承可能セットとは異なるため、ファイルに +i を設定しても意味がありません。ラッパーは/ を使用して明示的
CAP_DAC_OVERRIDE
に追加する必要があります。CAP_INHERITABLE
cap_set_flag
cap_set_proc
- ファイルが継承可能なセットに を
net
持っている必要があります。CAP_DAC_OVERRIDE
そうすることで、実際にラッパーからそのCAP_PERMITTED
セットに機能を継承できるようになります。また、自動的に に昇格されるように、有効ビットを設定する必要もありますCAP_EFFECTIVE
。
答え2
両方必要だと思います:
setcap cap_dac_override+pe ./registerdns
setcap cap_dac_override+i /usr/bin/net
フラグpe
がオンの場合registerdns
、プログラムを実行すると機能が取得されます。i
フラグがオンの場合net
、呼び出し元のプログラムから機能を継承できます。