I am trying to perform the execve syscall via assembly. Before I start, I have downloaded the riscv toolchain from the github repo, and configured it using: ./configure /opt/rv32./configure --prefix=/opt/rv32 --with-arch=rv32ia --with-abi=ilp32
.
In order to execute the binaries, I'm using qemu-user (qemu-riscv32
).
Ok, so first I wrote a simple C program that performs an execve syscall. The code is the following:
#include <unistd.h>
char *args[] = {"/bin/sh", 0x0};
int main()
{
execve(args[0], args, 0x0);
}
Then I dissassembled the produced code, and what I obtained is:
00010530 <main>:
10530: ff010113 addi sp,sp,-16
10534: 00112623 sw ra,12(sp)
10538: 00812423 sw s0,8(sp)
1053c: 01010413 addi s0,sp,16
10540: a9418793 addi a5,gp,-1388 # 85df0 <args>
10544: 0007a703 lw a4,0(a5)
10548: 00000613 li a2,0
1054c: a9418593 addi a1,gp,-1388 # 85df0 <args>
10550: 00070513 mv a0,a4
10554: 304160ef jal ra,26858 <__execve>
10558: 00000793 li a5,0
1055c: 00078513 mv a0,a5
10560: 00c12083 lw ra,12(sp)
10564: 00812403 lw s0,8(sp)
10568: 01010113 addi sp,sp,16
1056c: 00008067 ret
00026858 <__execve>:
26858: 0dd00893 li a7,221
2685c: 00000073 ecall
26860: fffff8b7 lui a7,0xfffff
26864: 00a8e463 bltu a7,a0,2686c <__execve+0x14>
26868: 00008067 ret
2686c: 71d0406f j 2b788 <__syscall_error>
26870: 00008067 ret
Notice that the code has been compiled using -static
flag
Then I tried to write my assembly program that basically does the same, so I ended up with the following code:
.globl _start
.section .text
_start:
# execve syscall
la a0, shell # Pointer to '/bin/sh'
la a1, addr # Pointer to the arraythat contains '/bin/sh'
sw a0, 0(a1)
mv a2, x0 # No environment variables are needed
li a7, 0xDD # 221
ecall
# exit syscall
li a7, 0x5D # 93
ecall
.section .rodata
shell: .string "/bin/sh"
.section .data
addr: .space 4
Then, I compiled the code with the following statement: riscv32-unknown-linux-gnu-gcc -c syscall.s && riscv32-unknown-linux-gnu-ld syscall.o -o syscall
And now, when I try to execute my C code, it works perfectly, even compiling the code without -static
flag, but when I execute my assembly code it returns 242 as error code. Before that, I have been checking errno codes produced by a failed execve, but i found nothing.
In addition, I have been searching if someone has experienced the same problem but unfortunately anyone has.
Any idea? Is there something am I missing or am I wrong?
Thanks
You're not telling the kernel how many entries there are in the argv array. The rule is that argv needs to be an array of pointers whose last entry is a NULL pointer. This would also be true for the envp argument if you were supplying an envp.
I'd suggest you do this with a preinitialized array also in .rodata
, like so:
.section .rodata
shell:
.string "/bin/sh"
.balign 4
argv:
.4byte shell
.4byte 0
and then your code can be something like
.section .text
.globl _start
.type _start, @function
_start:
# execve syscall
la a0, shell # Pointer to '/bin/sh'
la a1, addr # Pointer to the array that contains '/bin/sh'
li a2, 0 # No environment variables
li a7, 0xDD # 221 = execve
ecall
# _exit syscall
# if execve returns, it failed, so pass 1 to _exit
li a0, 1
li a7, 0x5D # 93 = _exit
ecall