x86_64 Linux Syscall Numbers Go Where?

Which register do x86_64 Linux syscall numbers go in? Feel free to look it up if you're not a human compiler backend.

The answer is...

eax! (not rax)

If you checked any of these sources, you're wrong!

In fact, the only source I can find that gets this right is the syscall(2) Linux man page, and that's because I patched it!

x86_64 syscall numbers get sign-extended from 32 to 64 bits in the kernel syscall entry point. ARM64 also does this, but this seems to be pretty well-known; the man page has documented this since 2020.

This is probably not useful for anything. I guess maybe you could bypass syscall filters implemented with PTRACE_SYSCALL and PTRACE_GETREGS, though I'm not sure why you would filter syscalls this way instead of using seccomp.

The interesting part of this, in my opinion, is that students everywhere learn that syscall numbers go in a 64-bit register, and, as far as I can tell, nobody bothered to check what would happen when a syscall number actually uses all those bits.

Or at least, nobody bothered to write it up.