2017-07-17 10 views
2

私は、raw cloneシステムコールを使用して、pid 0コードを関数にリファクタリングする必要がないようにしています。 Linuxはスタックを16バイト必要とし、libcはptidとctidを格納するためにおそらく16ビットを予約します。次のコードは、整列されたスタックを作成し、子から抜け出します。 libcのラッパーによってクローン化された子を待ってから、生のシステムコールを使用するときに、プログラムがsegfaultするたびに同じバッファで未処理のシステムコールを使用しました。添付ファイルはstraceからの出力です。何も見落とさない限り、システムコールの引数は両方とも同じです。 他に少なくとも1つの質問Raw Clone system callがあります.OPには同様の問題があるようですが、残念ながら、受け入れられた回答では、システムコールの代わりにlibcクローンラッパーが使用されます。Rawクローンシステムコールが正しく機能しない

#define _GNU_SOURCE 

#include <sched.h> 
#include <stdalign.h> 
#include <unistd.h> 
#include <stdlib.h> 
#include <stdio.h> 
#include <syscall.h> 
#include <signal.h> 
#include <stdint.h> 
#include <errno.h> 
#include <string.h> 
#include <sys/wait.h> 

int test(void*c) 
{ 
    quick_exit(0); 
} 

int main(void) 
{ 
    alignas (16) unsigned char stack[4096] = {0}; 
    printf("Top of stack %p\n", stack+sizeof(stack)); 
    printf("Top of stack minus 16 %p\n", stack+sizeof(stack)-16); 
    pid_t pid = clone(test, stack+sizeof(stack), CLONE_VM|SIGCHLD, 0, 0, 0, 0); 

    wait(NULL); 

    memset(stack, 0, sizeof stack); 

    pid = syscall(SYS_clone, CLONE_VM|SIGCHLD, stack+sizeof(stack)-16); 
    if (pid == 0) 
     quick_exit(0); 
wait(NULL); 
    quick_exit(0); 
} 

straceの出力:

[email protected]:~$ strace ./a.out 
execve("./a.out", ["./a.out"], [/* 57 vars */]) = 0 
brk(NULL)        = 0x55b1e58ee000 
access("/etc/ld.so.nohwcap", F_OK)  = -1 ENOENT (No such file or directory) 
mmap(NULL, 12288, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f70303a0000 
access("/etc/ld.so.preload", R_OK)  = -1 ENOENT (No such file or directory) 
open("/opt/google/chrome/tls/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 
stat("/opt/google/chrome/tls/x86_64", 0x7ffcc0e2e400) = -1 ENOENT (No such file or directory) 
open("/opt/google/chrome/tls/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 
stat("/opt/google/chrome/tls", 0x7ffcc0e2e400) = -1 ENOENT (No such file or directory) 
open("/opt/google/chrome/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 
stat("/opt/google/chrome/x86_64", 0x7ffcc0e2e400) = -1 ENOENT (No such file or directory) 
open("/opt/google/chrome/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 
stat("/opt/google/chrome", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0 
open("/opt/google/chrome/lib/tls/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 
stat("/opt/google/chrome/lib/tls/x86_64", 0x7ffcc0e2e400) = -1 ENOENT (No such file or directory) 
open("/opt/google/chrome/lib/tls/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 
stat("/opt/google/chrome/lib/tls", 0x7ffcc0e2e400) = -1 ENOENT (No such file or directory) 
open("/opt/google/chrome/lib/x86_64/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 
stat("/opt/google/chrome/lib/x86_64", 0x7ffcc0e2e400) = -1 ENOENT (No such file or directory) 
open("/opt/google/chrome/lib/libc.so.6", O_RDONLY|O_CLOEXEC) = -1 ENOENT (No such file or directory) 
stat("/opt/google/chrome/lib", 0x7ffcc0e2e400) = -1 ENOENT (No such file or directory) 
open("/etc/ld.so.cache", O_RDONLY|O_CLOEXEC) = 3 
fstat(3, {st_mode=S_IFREG|0644, st_size=171231, ...}) = 0 
mmap(NULL, 171231, PROT_READ, MAP_PRIVATE, 3, 0) = 0x7f7030376000 
close(3)        = 0 
access("/etc/ld.so.nohwcap", F_OK)  = -1 ENOENT (No such file or directory) 
open("/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3 
read(3, "\177ELF\2\1\1\3\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\20\5\2\0\0\0\0\0"..., 832) = 832 
fstat(3, {st_mode=S_IFREG|0755, st_size=1856752, ...}) = 0 
mmap(NULL, 3959200, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x7f702fdb7000 
mprotect(0x7f702ff74000, 2097152, PROT_NONE) = 0 
mmap(0x7f7030174000, 24576, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x1bd000) = 0x7f7030174000 
mmap(0x7f703017a000, 14752, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7f703017a000 
close(3)        = 0 
mmap(NULL, 8192, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x7f7030374000 
arch_prctl(ARCH_SET_FS, 0x7f7030374700) = 0 
mprotect(0x7f7030174000, 16384, PROT_READ) = 0 
mprotect(0x55b1e46da000, 4096, PROT_READ) = 0 
mprotect(0x7f70303a3000, 4096, PROT_READ) = 0 
munmap(0x7f7030376000, 171231)   = 0 
fstat(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 8), ...}) = 0 
brk(NULL)        = 0x55b1e58ee000 
brk(0x55b1e590f000)      = 0x55b1e590f000 
write(1, "Top of stack 0x7ffcc0e2ecd0\n", 28Top of stack 0x7ffcc0e2ecd0 
) = 28 
write(1, "Top of stack minus 16 0x7ffcc0e2"..., 37Top of stack minus 16 0x7ffcc0e2ecc0 
) = 37 
clone(child_stack=0x7ffcc0e2ecc0, flags=CLONE_VM|SIGCHLD) = 122458 
wait4(-1, NULL, 0, NULL)    = 122458 
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=122458, si_uid=1000, si_status=0, si_utime=0, si_stime=0} --- 
clone(child_stack=0x7ffcc0e2ecc0, flags=CLONE_VM|SIGCHLD) = 122459 
exit_group(0 <unfinished ...> 
+++ killed by SIGSEGV +++ 
Segmentation fault (core dumped) 

答えて

5

syscallcloneの特別な知識を持っていません。これは、関数が新しく作成されたスレッドで復帰しようとすると、スタックされたスタックから復帰アドレス(ゼロ)を読み込むことを意味します。これは、スタックに0以外のビットパターンを書き込んだり、子が親を壊さないようにCLONE_VMを落とした方がより明らかです。

+0

戻り値を格納しないようにコンパイラに指示する方法はありますか?私は無効にキャストしようとしましたが、うまくいきませんでした。 – clockley1

+0

これは、返り値*ではなく、 'syscall'関数自体が返り値*アドレス*を格納するところです。 'syscall'関数の実装を変更せずにこれを変更する方法はなく、変更がどのように見えるかはっきりしません(' vfork'で使われているようなものかもしれません)。より高度な 'クローン'インターフェースを改善する方がいいでしょう。 –

+0

ありがとう、ありがとう+1 .. – clockley1

関連する問題