Il 28/02/23 15:14, Sergey Bugaev ha scritto:
On Tue, Feb 28, 2023 at 4:26 PM Luca Dariz <[email protected]> wrote:
+ /* check if we need to place some arguments on the stack */
+_syscall64_args_stack:
+ mov EXT(mach_trap_table)(%rax),%r10 /* get number of arguments */
+ subq $6,%r10 /* the first 6 args are already in place */
+ jl _syscall64_call /* skip argument copy if >6 args */
jle?
Right, I didn't test a 6-args syscall.
+
+ movq R_UESP(%rbx),%r11 /* get user stack pointer */
+ addq $8,%r11 /* Skip user return address */
+
+ mov $USER_DS,%r12 /* use user data segment for accesses */
+ mov %r12,%fs
+
+ lea (%r11,%r10,8),%r11 /* point past last argument */
Do I understand it right that for the most interesting syscall (which
takes 7 args!), I *am* supposed to pass the 7th arg on the stack (in
mem[rsp + 8]) -- unlike on Linux?
I think on Linux all syscalls have <= 6 arguments, so they will never
use the stack for the 7th arg. This use of the stack is due to x86_64
calling conventions, and since we have a syscall with 11 args
(syscall_vm_map) I don't see currently a better way to pass the extra
args. (but I don't exclude there is one :))
Or in other words: do I understand it right that the ABI here is:
- syscall number in rax
- arguments are passed just as per x86_64 calling convention, except
the 4th arg is in r10 and not rcx
- return value is in rax
correct
- rcx and r11 are additionally clobbered -- or not?
They will still contain RIP and EFLAGS on return, so they have a special
treatment compared to the usual calling conventions, but they can
probably be considered clobbered for this purpose.
- nothing else is clobbered, in particular not rflags (or is the
"reserved" half of rflags clobbered?) and not the registers that
contain args
if we follow the usual calling conventions, the registers containing
args are clobbered. In fact, in the code I set them to 0 before sysret,
to avoid the risk of them containing sensitive information from the
syscall execution.
In the syscall invoker in syscall_sw.h the special syscall conventions
should be masked in a regular function, so from userspace the mach_msg()
or syscall_vm_allocate() or any other syscall should be just like a
regular function. I've done some testing but I didn't test it with
glibc, so this stub might need to be improved.
Luca