android ndk vfork 缺陷
2014-05-31 17:48
417 查看
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_errnoEND(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 vforkBreakpoint 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) rStarting program: /data/local/tmp/vfork ls -lBreakpoint 1, vfork () at bionic/libc/arch-arm/syscalls/vfork.S:1313 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 3199400164r1 0xbeb2faa8 3199400616r2 0x0 0r3 0xc 12r4 0x3 3r5 0xbeb2f970 3199400304r6 0xbeb2f8ec 3199400172r7 0xbeb2f8f8 3199400184r8 0x0 0r9 0x0 0r10 0x0 0r11 0xbeb2f95c 3199400284r12 0x0 0sp 0xbeb2f8c0 0xbeb2f8c0lr 0x8165 33125pc 0x9684 0x9684 <vfork+4>cpsr 0x80000010 -2147483632(gdb) x/4xw $sp0xbeb2f8c0: 0x00000003 0xbeb2f8f8 0xbeb2f8e4 0xbeb2f8e4(gdb) disassemble $pcDump 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 *0x968cBreakpoint 2 at 0x968c: file bionic/libc/arch-arm/syscalls/vfork.S, line 15. (gdb) b execvpBreakpoint 3 at 0x9a98: file bionic/libc/unistd/exec.c, line 202.(gdb) cContinuing.[New process 5934][Switching to process 5934]Breakpoint 2, vfork () at bionic/libc/arch-arm/syscalls/vfork.S:1515 in bionic/libc/arch-arm/syscalls/vfork.S1: 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) nivfork () at bionic/libc/arch-arm/syscalls/vfork.S:1616 in bionic/libc/arch-arm/syscalls/vfork.S1: 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.S1: 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:4848 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.c1: 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.c1: 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.c1: 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.c1: 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.c1: 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.c1: 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) cContinuing.Breakpoint 3, execvp (name=0x1f78028 "ls", argv=0xbeb2f8e4) at bionic/libc/unistd/exec.c:202202 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 32997416r1 0xbeb2f8e4 3199400164r2 0x0 0r3 0xbeb2f8e4 3199400164r4 0xffffff9c 4294967196r5 0xffffefb4 4294963124r6 0xbeb2f8ec 3199400172r7 0xbeb2f8f8 3199400184r8 0x0 0r9 0x0 0r10 0x0 0r11 0xbeb2f95c 3199400284r12 0x0 0sp 0xbeb2e868 0xbeb2e868lr 0x8195 33173pc 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,导致后续栈帧被破坏,程序崩溃。
相关文章推荐
- android ndk中使用gprof
- Android自动化测试中uiautomator修改uiautomatorviewer获取不到动态界面的缺陷
- Android NDK 之 NDK 预生库支持
- 二手机械设备存在环保缺陷
- Android NDK开发篇(五):Java与原生代码通信(数据操作)
- Android ndk 线程回调java层方法
- Android NDK 安装与配置
- fork与vfork的区别
- Android NDK 开发+cygwin 的安装 +eclipse cygwin配置
- 进程中fork vfork的用法
- 万能的编程语言不要习惯性地把工具当作你天性缺陷的遮羞布
- 读《C缺陷与陷阱》之-函数声明理解
- 去除警告 Android NDK: WARNING: APP_PLATFORM Android-14 Is Larger Than android:minSdkVersion 8
- Android NDK: WARNING: APP_PLATFORM android-14 is larger than android:minSdkVersion 8
- Android Build System (Android NDK)
- Android NDK开发篇(一) windows免cygwin搭建ndk环境
- java 栈和Java基础类的Stack类的源码实现,缺陷以及如何实现自己的Stack类
- 搭建Mantis 缺陷管理系统
- csdn发博文验证码缺陷
- Android SDK Android NDK Android Studio 官方下载地址