新しい名前空間でプロセスを作成しようとしています。これを行うには、適切なフラグでclone(2)を使用する必要があります。これには、親PIDを印刷するためのレプリケーションシステムコールとprintf()ステートメントがあります。
printf("clone() = %ld\n", (long)getpid());
printf("PID: %ld\n", (long)getpid());
struct utsname utsname;
uname(&utsname);
printf("parent namespace hostname: %s\n", utsname.nodename);
clone(child_main(&process_struct, checkpoint), stack + process_struct.Stack,
CLONE_NEWCGROUP
|CLONE_NEWIPC
|CLONE_NEWNET
|CLONE_NEWNS
|CLONE_NEWPID
|CLONE_NEWUTS|SIGCHLD, &process_struct)
child_main() 関数の場合、子関数はホスト名を設定し、子プロセスの PID を出力します。問題は、システムのホスト名が名前空間のホスト名だけでなくPIDも変更することです。これは、子プロセスのPIDが親プロセスのPIDと同じであることです。名前空間内の子プロセスのPIDは1でなければならず、対応するPPIDは0(親プロセスがないことを意味する)なので、sethostname(2)は必ず子プロセス名前空間にのみ影響します。
int child_main(struct process *process, int *checkpoint){
char c;
fprintf(stderr,"=> IPC setup...");
//double check the IPC
close(checkpoint[1]);
fprintf(stderr,"Done\n");
if ( sethostname(process->Hostname, strlen(process->Hostname)){
//close(process->File_descriptor);
return -1;
}
printf("PID: %ld\n", (long)getpid());
struct utsname utsname;
uname(&utsname);
printf("child namespace hostname: %s\n", utsname.nodename);
// startup the IPC pipes
read(checkpoint[0], &c, 1);
char* argv[]={(char*)0};
if(execve("/bin/bash", argv, NULL) == -1 ){
fprintf(stderr,"--> Launching process Failed %m\n");
return -1;
}
return 0;
}
答え1
glibcclone()
ラッパーは関数ポインタを最初の引数として使用します。
関数ポインタを渡さず(親プロセスの呼び出しからint
戻り値を渡します)。child_main
今後クローンを呼び出します)。最初の引数(あなたから返された)にポインタをchild_main
渡すと、-1が返され、に設定されますが、戻り値を確認していないようです。NULL
0
child_main
errno
EINVAL
clone()
マンページから:
EINVAL
または が NULL として指定されている場合、glibc ラッパー関数によってclone()
返されます。fn
child_stack
したがって、child_main
親プロセスで実行され、子プロセスや名前空間は作成されず、ホストchild_main
名は初期名前空間、つまりシステム全体に設定されます。