gpt4 book ai didi

c - 原始克隆系统调用

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:42:01 25 4
gpt4 key购买 nike

我正在尝试使用原始克隆系统,但找不到任何合适的文档。我试图编写一个小程序来尝试它,但这最终导致了段错误。

我不明白我哪里错了。

这是一个小应用程序:

define STACK_SIZE 0x10000
define BUFSIZE 200

#define _GNU_SOURCE

void hello (){
fprintf(stderr,"Hello word\n");
_exit(0);
}


int main()
{

int res;
void *stack = mmap(0, STACK_SIZE, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
pid_t ptid, tid;

printf("Stack %p\n", stack + STACK_SIZE);
memset(stack, 0, STACK_SIZE);

res= syscall(SYS_clone,CLONE_SIGHAND|CLONE_FS|CLONE_VM|CLONE_FILES,stack + STACK_SIZE, &tid,&ptid,NULL );

if (!res)
hello();

printf("Clone result %x\n", res);
waitpid(-1, NULL, __WALL);

return 0;
}

最佳答案

child 从空堆栈中弹出返回地址,从未映射的地址读取。

注意:答案假定 x86_64 ISA,其中 call 将返回地址放在堆栈上。将其与 AArch64 进行对比,其中链接寄存器可能保存返回地址。

详情

根据 clone 的手册页,“子进程中的执行从调用点继续”。然而,尽 pipe 项和父项最初执行相同的指令,但它们不共享堆栈,并且 ret 指令在父项和子项中的行为不同。

在 GDB 下运行应用程序显示 SIGSEGV 发生在 syscall 函数的 ret 指令处。

Thread 2 received signal SIGSEGV, Segmentation fault.
[Switching to LWP 415]
syscall () at ../sysdeps/unix/sysv/linux/x86_64/syscall.S:40
(gdb) x/i $pc
=> 0x7ffff7ee0745 <syscall+37>: retq

ret 从堆栈中弹出返回地址。堆栈为空的子级无法执行它,而父级成功返回到 main 函数。

您可以通过提供 stack + STACK_SIZE - 8 作为第三个系统调用参数来修复未映射的访问。然而,潜在的问题仍然存在:零初始化堆栈不存储返回地址。下图说明了这个问题。

simplified syscallsyscall+... 的意思是“系统调用中的某处”,以免使地址困惑。

解决方案

Macattack 的回答已经提到了克隆的包装器。按照 uclibc 的思路实现特定于拱门的包装器一个。

关于c - 原始克隆系统调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17604458/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com