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
CodePudding user response:
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