web-dev-qa-db-ja.com

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

また、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ページと、それがどのように機能するかについての無数の他のドキュメントを読みましたすべきと私はそれが説明していることをやっていると思っていました。

8
AdmiralNemo

ラッパーに+ iを設定しても、ラッパープロセスのCAP_INHERITABLEセットに機能が追加されないことがわかります。 execを通過しました。したがって、execlを呼び出す前に、CAP_DAC_OVERRIDECAP_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

私は今何が起こっているのかを完全に理解していると思います:

  1. ラッパーは、継承可能なセットに追加できるように、許可されたセットにCAP_DAC_OVERRIDEが必要です。
  2. ラッパーのプロセス継承可能セットはファイル継承可能セットとは異なるため、ファイルに+ iを設定しても意味がありません。ラッパーは、CAP_DAC_OVERRIDE/CAP_INHERITABLEを使用して、cap_set_flagcap_set_procを明示的に追加する必要があります。
  3. netファイルは、実際にラッパーからCAP_DAC_OVERRIDEセットに機能を継承できるように、継承可能なセットにCAP_PERMITTEDが含まれている必要があります。また、自動的にCAP_EFFECTIVEにプロモートされるように、有効ビットを設定する必要があります。
8
AdmiralNemo

両方が必要だと思います。

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

peregisterdnsフラグは、プログラムを実行すると機能が取得されることを示します。 inetフラグは、呼び出し元のプログラムから機能を継承できることを示しています。

1
Barmar