android ndk vfork 缺陷

8 篇文章 0 订阅
3 篇文章 0 订阅
NDK vfork implementation:
	push	{r4, r7}
	mov	r7, #190	; 0xbe
	svc	0x00000000
	pop	{r4, r7}
	movs	r0, r0
	bxpl	lr
	b	0x1475c

bionic C vfork implentation(KitKat):
ENTRY(vfork)
    mov     ip, r7
    ldr     r7, =__NR_vfork
    swi     #0
    mov     r7, ip
    cmn     r0, #(MAX_ERRNO + 1)
    bxls    lr
    neg     r0, r0
    b       __set_errno
END(vfork)

与KitKat的vfork实现比较,感觉问题出在 push {r4, r7}
不知道NDK下个版本是否会修改vfork的实现,这样很容易导致栈内存出问题。

临时解决方法:
my_vfork.S
/* autogenerated by gensyscalls.py */
#include <asm/unistd.h>
#include <linux/err.h>
#include <machine/asm.h>


ENTRY(my_vfork)
    mov     ip, r7
    ldr     r7, =__NR_vfork
    swi     #0
    mov     r7, ip
    cmn     r0, #(MAX_ERRNO + 1)
    bxls    lr
    neg     r0, r0
    b       my_set_errno
END(my_vfork)

---------------------------------------------------------------------------------------
test.c
int my_set_errno(int n) 
{
  errno = n;
  return -1;
}

int test(char** argv)
{
    int status;
#if 0
    pid_t pid = vfork();
#else
    pid_t pid = my_vfork();
#endif
    if (pid <0)
    {
        fprintf(stderr, "vfork failed(%s)\n", strerror(errno));
        return;
    }
    if (pid == 0)
    {
         execvp(argv[0], argv);
        _exit(111);
    }else {
        pid = waitpid(0, &status, 0);
    }

    return 0;
}

==============================================================================================
使用 gdb 跟踪该缺陷

# gdb --args /data/local/tmp/vfork ls -l                    
Reading symbols from /data/local/tmp/vfork...done.
(gdb) b vfork
Breakpoint 1 at 0x9684: file bionic/libc/arch-arm/syscalls/vfork.S, line 13.
(gdb) set follow-fork-mode child 
(gdb) display /4i $pc-8
(gdb) r
Starting program: /data/local/tmp/vfork ls -l


Breakpoint 1, vfork () at bionic/libc/arch-arm/syscalls/vfork.S:13
13	bionic/libc/arch-arm/syscalls/vfork.S: No such file or directory.
1: x/4i $pc-8
   0x967c <_exit+28>:	nop			; (mov r0, r0)
   0x9680 <vfork>:	push	{r4, r7}
=> 0x9684 <vfork+4>:	mov	r7, #190	; 0xbe
   0x9688 <vfork+8>:	svc	0x00000000
(gdb) info registers 
r0             0xbeb2f8e4	3199400164
r1             0xbeb2faa8	3199400616
r2             0x0	0
r3             0xc	12
r4             0x3	3
r5             0xbeb2f970	3199400304
r6             0xbeb2f8ec	3199400172
r7             0xbeb2f8f8	3199400184
r8             0x0	0
r9             0x0	0
r10            0x0	0
r11            0xbeb2f95c	3199400284
r12            0x0	0
sp             0xbeb2f8c0	0xbeb2f8c0
lr             0x8165	33125
pc             0x9684	0x9684 <vfork+4>
cpsr           0x80000010	-2147483632
(gdb) x/4xw $sp
0xbeb2f8c0:	0x00000003	0xbeb2f8f8	0xbeb2f8e4	0xbeb2f8e4
(gdb) disassemble $pc
Dump of assembler code for function vfork:
   0x00009680 <+0>:	push	{r4, r7}
=> 0x00009684 <+4>:	mov	r7, #190	; 0xbe
   0x00009688 <+8>:	svc	0x00000000
   0x0000968c <+12>:	pop	{r4, r7}
   0x00009690 <+16>:	movs	r0, r0
   0x00009694 <+20>:	bxpl	lr
   0x00009698 <+24>:	b	0x145c4
   0x0000969c <+28>:	nop			; (mov r0, r0)
End of assembler dump.
(gdb) b *0x968c
Breakpoint 2 at 0x968c: file bionic/libc/arch-arm/syscalls/vfork.S, line 15. 
(gdb) b execvp
Breakpoint 3 at 0x9a98: file bionic/libc/unistd/exec.c, line 202.
(gdb) c
Continuing.
[New process 5934]
[Switching to process 5934]


Breakpoint 2, vfork () at bionic/libc/arch-arm/syscalls/vfork.S:15
15	in bionic/libc/arch-arm/syscalls/vfork.S
1: x/4i $pc-8
   0x9684 <vfork+4>:	mov	r7, #190	; 0xbe
   0x9688 <vfork+8>:	svc	0x00000000
=> 0x968c <vfork+12>:	pop	{r4, r7}
   0x9690 <vfork+16>:	movs	r0, r0
(gdb) x/4xw $sp      
0xbeb2f8c0:	0x00000003	0xbeb2f8f8	0xbeb2f8e4	0xbeb2f8e4
(gdb) ni
vfork () at bionic/libc/arch-arm/syscalls/vfork.S:16
16	in bionic/libc/arch-arm/syscalls/vfork.S
1: x/4i $pc-8
   0x9688 <vfork+8>:	svc	0x00000000
   0x968c <vfork+12>:	pop	{r4, r7}
=> 0x9690 <vfork+16>:	movs	r0, r0
   0x9694 <vfork+20>:	bxpl	lr
(gdb) 
17	in bionic/libc/arch-arm/syscalls/vfork.S
1: x/4i $pc-8
   0x968c <vfork+12>:	pop	{r4, r7}
   0x9690 <vfork+16>:	movs	r0, r0
=> 0x9694 <vfork+20>:	bxpl	lr
   0x9698 <vfork+24>:	b	0x145c4
(gdb) 
test (argv=0x1f78028) at jni/vfork.c:48
48	jni/vfork.c: No such file or directory.
1: x/4i $pc-8
   0x815c <test>:	push	{r0, r1, r2, r3, r4, lr}
   0x815e <test+2>:	str	r0, [sp, #4]
   0x8160 <test+4>:	blx	0x9680 <vfork>
=> 0x8164 <test+8>:	cmp	r0, #0
(gdb) 
0x00008166	48	in jni/vfork.c
1: x/4i $pc-8
   0x815e <test+2>:	str	r0, [sp, #4]
   0x8160 <test+4>:	blx	0x9680 <vfork>
   0x8164 <test+8>:	cmp	r0, #0
=> 0x8166 <test+10>:	bge.n	0x8186 <test+42>
(gdb) 
53	in jni/vfork.c
1: x/4i $pc-8
   0x817e <test+34>:	adds	r0, #168	; 0xa8
   0x8180 <test+36>:	bl	0x9d10 <fprintf>
   0x8184 <test+40>:	b.n	0x81a6 <test+74>
=> 0x8186 <test+42>:	cmp	r0, #0
(gdb) 
0x00008188	53	in jni/vfork.c
1: x/4i $pc-8
   0x8180 <test+36>:	bl	0x9d10 <fprintf>
   0x8184 <test+40>:	b.n	0x81a6 <test+74>
   0x8186 <test+42>:	cmp	r0, #0
=> 0x8188 <test+44>:	bne.n	0x819a <test+62>
(gdb) 
55	in jni/vfork.c
1: x/4i $pc-8
   0x8182 <test+38>:	stc2l	0, cr14, [r6, #60]	; 0x3c
   0x8186 <test+42>:	cmp	r0, #0
   0x8188 <test+44>:	bne.n	0x819a <test+62>
=> 0x818a <test+46>:	ldr	r3, [sp, #4]
(gdb) 
0x0000818c	55	in jni/vfork.c
1: x/4i $pc-8
   0x8184 <test+40>:	b.n	0x81a6 <test+74>
   0x8186 <test+42>:	cmp	r0, #0
   0x8188 <test+44>:	bne.n	0x819a <test+62>
   0x818a <test+46>:	ldr	r3, [sp, #4]
(gdb) 
0x0000818e	55	in jni/vfork.c
1: x/4i $pc-8
   0x8186 <test+42>:	cmp	r0, #0
   0x8188 <test+44>:	bne.n	0x819a <test+62>
   0x818a <test+46>:	ldr	r3, [sp, #4]
   0x818c <test+48>:	ldr	r0, [r3, #0]
(gdb) c
Continuing.


Breakpoint 3, execvp (name=0x1f78028 "ls", argv=0xbeb2f8e4)
    at bionic/libc/unistd/exec.c:202
202	bionic/libc/unistd/exec.c: No such file or directory.
1: x/4i $pc-8
   0x9a90 <execvp>:	push	{r4, r5, r6, r7, lr}
   0x9a92 <execvp+2>:	ldr	r5, [pc, #464]	; (0x9c64 <execvp+468>)
   0x9a94 <execvp+4>:	ldr	r4, [pc, #464]	; (0x9c68 <execvp+472>)
   0x9a96 <execvp+6>:	add	sp, r5
(gdb) info registers 
r0             0x1f78028	32997416
r1             0xbeb2f8e4	3199400164
r2             0x0	0
r3             0xbeb2f8e4	3199400164
r4             0xffffff9c	4294967196
r5             0xffffefb4	4294963124
r6             0xbeb2f8ec	3199400172
r7             0xbeb2f8f8	3199400184
r8             0x0	0
r9             0x0	0
r10            0x0	0
r11            0xbeb2f95c	3199400284
r12            0x0	0
sp             0xbeb2e868	0xbeb2e868
lr             0x8195	33173
pc             0x9a98	0x9a98 <execvp+8>
cpsr           0x80000030	-2147483600
(gdb) 

最终子进程
0x0000968c <+12>:	pop	{r4, r7}
sp 恢复,而父进程要等到子进程执行到execve才恢复执行,届时sp才能恢复,
而当子进程执行完vfork,执行进入execvp时,执行push指令压入几个寄存器,
0x9a90 <execvp>:	push	{r4, r5, r6, r7, lr}
导致父进程在vfork中压入sp的r4, r7被这里的r7,lr取代,最终子进程执行exeve后,父进程vfork从svc后继续执行
0x0000968c <+12>:	pop	{r4, r7}
弹出的r7已被修改为0x8195,导致后续栈帧被破坏,程序崩溃。

                
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值