%20%E5%91%BC%E3%81%B3%E5%87%BA%E3%81%97%E3%81%AE%E7%B6%99%E6%89%BF%E5%8F%AF%E8%83%BD%E3%81%AA%E9%96%A2%E6%95%B0.png)
現在、私は以下を読んでLinuxの機能を理解しようとしています。http://man7.org/linux/man-pages/man7/capability.7.html
次の機能を使用して小さなC ++アプリケーションを作成しました。CAP_DAC_READ_SEARCH+eip
この機能はアプリに適しています。しかし、私system()
の中に電話があります。
system("cat /dev/mtdX > targetFile");
この呼び出しの機能をどのように継承できますか?
編集する:
私はこれが+によって駆動されるsystem()
ことを知っています。文書では、子プロセスが親プロセスと同じ機能を持つと言われています。しかし、なぜ読む能力は遺伝しないのですか?fork()
execl()
fork()
答え1
まず、system(3)
提案したものとは異なるsystem(3)
だけでなくfork+exec
、信号構成の変更、サブプロセスの待機、および/bin/sh
ラッパーとしての使用に関連するかなり複雑な作業です(環境によって異なる場合があります)。管理者の気まぐれと仮定)機能を削除または追加し、環境変数を混乱させ、ソース初期化スクリプトやその他の面白いことを行います。execv*(2)
代わりにjustを使用すると、system(3)
これらのすべての虚偽の合併症が排除されます。
第二に、「期間別能力の変化」セクションを詳しく見てくださいexecve()
。capabilities(7)
マンページ。ここにコピーして貼り付けることはありませんが、基本的には次のように要約されます。関数は、次に追加されない限り、execve() から継承されません。周辺置くスレッド(プロセス)の継承可能なセットにすでにない場合は、それを追加できません。ワイヤー。 (ファイルメタデータの「継承可能」機能は、マスク、スレッドを制限すること)。
execve()
したがって、継承された能力を持つためにㅏ)それらを削除してください許可された到着継承可能設定(あなたは利用可能ですcapset(2)
システムコール[1])と雨)に追加周辺設定(あなたは利用可能ですprctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE)
)。
一緒に入れてください:
$ cat capexec.c
#include <sys/prctl.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/capability.h>
#include <err.h>
int main(int ac, char **av){
static char *dav[] = { "/bin/bash", 0 };
struct __user_cap_header_struct hs;
struct __user_cap_data_struct ds[2];
hs.version = 0x20080522; /*_LINUX_CAPABILITY_VERSION_3;*/
hs.pid = getpid();
if(syscall(SYS_capget, &hs, ds)) err(1, "capget");
ds[0].inheritable = ds[0].permitted;
if(syscall(SYS_capset, &hs, ds)) err(1, "capset");
if(prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_DAC_READ_SEARCH, 0, 0)) err(1, "prctl(pr_cap_ambient_raise)");
av = ac < 2 ? dav : av + 1;
execvp(*av, av);
err(1, "execvp %s", *av);
}
$ cc -Wall capexec.c -o capexec
# as root
# setcap cap_dac_read_search+ip /tmp/capexec
$ ./capexec dd if=/dev/sda of=/dev/null count=1
1+0 records in
1+0 records out
512 bytes copied, 0.000299173 s, 1.7 MB/s
[1] ドキュメントでは libcap ライブラリの使用をお勧めします。この例の一部は、libcapがなく、多くのヘッダー定義が欠落している以前のバージョンのAndroid用に作成したハックから削除されました。 libcapラッパーを使用するように変換することは、読者の練習の課題として残ります。
答え2
@mosvyに感謝します。私はlibcapを使って彼のソリューションを実装しましたが、期待どおりに動作するようです。
void inheritCapabilities()
{
cap_t caps;
caps = cap_get_proc();
if (caps == NULL)
throw "Failed to load capabilities";
printf("DEBUG: Loaded Capabilities: %s\n", cap_to_text(caps, NULL));
cap_value_t cap_list[1];
cap_list[0] = CAP_DAC_READ_SEARCH;
if (cap_set_flag(caps, CAP_INHERITABLE, 1, cap_list, CAP_SET) == -1)
throw "Failed to set inheritable";
printf("DEBUG: Loaded Capabilities: %s\n", cap_to_text(caps, NULL));
if (cap_set_proc(caps) == -1)
throw "Failed to set proc";
printf("DEBUG: Loaded Capabilities: %s\n", cap_to_text(caps, NULL));
caps = cap_get_proc();
if (caps == NULL)
throw "Failed to load capabilities";
printf("DEBUG: Loaded Capabilities: %s\n", cap_to_text(caps, NULL));
if (prctl(PR_CAP_AMBIENT, PR_CAP_AMBIENT_RAISE, CAP_DAC_READ_SEARCH, 0, 0) == -1)
throw "Failed to pr_cap_ambient_raise! Error: " + errno;
}
main() {
inheritCapabilities();
char *catargv[5];
catargv[0] = (char *)"cmd";
catargv[1] = (char *)"arg1";
catargv[2] = (char *)"arg2";
catargv[3] = (char *)"arg3";
catargv[4] = NULL;
if (execvp(catargv[0], catargv) == -1)
throw "Failed! command";
}