exec を通じて権限を渡す

exec を通じて権限を渡す

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_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_OVERRIDEそうすることで、実際にラッパーからそのCAP_PERMITTEDセットに機能を継承できるようになります。また、自動的に に昇格されるように、有効ビットを設定する必要もありますCAP_EFFECTIVE

答え2

両方必要だと思います:

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

フラグpeがオンの場合registerdns、プログラムを実行すると機能が取得されます。iフラグがオンの場合net、呼び出し元のプログラムから機能を継承できます。

関連情報