3 ms·
Just a friendly reminder that syscall() is a vararg function. Meaning, you can't just go throwing arguments at it (so maybe it's better to use this wrapper to a
by jagrsw 2y ago
Just a friendly reminder that syscall() is a vararg function. Meaning, you can't just go throwing arguments at it (so maybe it's better to use this wrapper to avoid problems instead).
For example, on a 64-bit arch, this code would be sus.
syscall(__NR_syscall_taking_6_args, 1, 2, 3, 4, 5, 6);
Quiz: why
PS: it's a common mistake, so I thought I'd save you a trip down the debugging rabbit hole.
- remram 2y agoA quiz is the opposite of saving someone effort.
- eddd-ddde 2y agoExactly, I am now morally bound to figure out the answer instead of going to work.
- oguz-ismail 2y agoThe last argument would be on the stack instead of in a register which is where the kernel expects to find the arguments. But a proper syscall implementation would handle this just fine (e.g. <https://github.com/bminor/glibc/blob/ba60be873554ecd141b55ea82647714933c0dbd4/sysdeps/unix/sysv/linux/x86_64/syscall.S https://github.com/bminor/glibc/blob/ba60be873554ecd141b55ea...>), so I don't think there's anything sus about it.
- im3w1l 2y ago> movq 8(%rsp),%r9 This is a huge edgecase but is 8(%rsp) guaranteed to be readable memory
- achierius 2y agoYes, see https://en.wikipedia.org/wiki/Red_zone_(computing) https://en.wikipedia.org/wiki/Red_zone_(computing)
- jagrsw 2y agoThe problem is something a bit else (jstarks figured it out somewhere below). I'm not a compiler/abi eng, but it seems to depend on a compiler, eg. consider this with clang-16: #include <sys/syscall.h> #include <unistd.h> #include <alloca.h> #include <string.h> void s(long a, long b, long c, long d, long e, long f, long g) { } int main(void) { long a = 0xFFFFFFFFFFFFFFFF; s(a, a, a, a, a, a, a); syscall(9999, 1, 2, 3, 4, 5, 6); return 0; } Now, strace shows: $ strace -e process_vm_readv ./a process_vm_readv(1, 0x2, 3, 0x4, 5, 18446744069414584326) = -1 EINVAL (Invalid argument) objdump -d a 117f: 48 c7 45 f0 ff ff ff movq $0xffffffffffffffff,-0x10(%rbp) 1186: ff 1187: 48 8b 7d f0 mov -0x10(%rbp),%rdi 118b: 48 8b 75 f0 mov -0x10(%rbp),%rsi 118f: 48 8b 55 f0 mov -0x10(%rbp),%rdx 1193: 48 8b 4d f0 mov -0x10(%rbp),%rcx 1197: 4c 8b 45 f0 mov -0x10(%rbp),%r8 119b: 4c 8b 4d f0 mov -0x10(%rbp),%r9 119f: 48 8b 45 f0 mov -0x10(%rbp),%rax 11a3: 48 89 04 24 mov %rax,(%rsp) 11a7: e8 94 ff ff ff call 1140 <s> 11ac: bf 36 01 00 00 mov $0x136,%edi 11b1: be 01 00 00 00 mov $0x1,%esi 11b6: ba 02 00 00 00 mov $0x2,%edx 11bb: b9 03 00 00 00 mov $0x3,%ecx 11c0: 41 b8 04 00 00 00 mov $0x4,%r8d 11c6: 41 b9 05 00 00 00 mov $0x5,%r9d 11cc: c7 04 24 06 00 00 00 movl $0x6,(%rsp) 11d3: b0 00 mov $0x0,%al 11d5: e8 56 fe ff ff call 1030 <syscall@plt> Only 4 bytes are put on the stack, but syscall will read 8. It's tricky if one doesn't control types of arguments used in vararg.
- im3w1l 2y agoI think you misunderstand. The red zone is on the opposite side of rsp. This line is trying to read an argument that may not exist, relying on the fact that this will put garbage in the register which syscall then ignores. But this only works if the memory is readable.
- Brian_K_White 2y agoI never get people who aren't grateful for pointers. Being shown which direction to walk is of no value, they must also be carried there. They didn't claim to save work, they claimed to save hitting a bug, and having to debug it. They said the word "vararg". They gave you everything.
- remram 2y agoThey are not some professor in my school, some valued colleague, or known kernel expert. They are a stranger on the internet. No, I can't be bothered to research every person that claim to have some wisdom that they won't articulate to cultivate an air of mystery. They gave me everything to dismiss their claim.
- jagrsw 2y agohttps://xkcd.com/1058/ https://xkcd.com/1058/ :)
- Brian_K_White 2y agoProfessors get paid, we got a pointer and a lesson for free. Here's a free dollar. "Only one?" They said the word "vararg". That is everything. You take that, and you say "oh shit, right, thanks for the heads up" or if you don't already know what's so special about that, you do know they obviously said that for some reason so you fucking google it. Either way, they pointed you in the right direction, and that is helpful. The further reading that you find so unbearable takes you exactly the same time to read something that has already been written and is just sitting out there to look up for free, as to read something you demand they write again on the spot bespoke for you. And since as you say they aren't a proffessor or colleague you personally know and respect, why do you care if they write out a full article or just a pointer? You just said you don't trust a rando. You don't trust their full article anyway.
- remram 2y agoHow do I know if they are "pointing me in the right direction"? Once again, you assume the conclusion that their comment is helpful and correct and meaningful, and you work backwards to excuse their poor explanation that they justified with "let's say it's a quiz". And if you don't like my reply, take your own advice and go away. Why do you care what I think of their phrasing? You're not going to get me to stop anyway, or the dozens or people who upvoted me. Or keep swearing at me and getting downvoted, whatever floats your boat.
- jstarks 2y agoI guess if the arch’s varargs conventions do something other than put each 32-bit value in a 64-bit “slot” (likely for inputs that end up on the stack, at least), then some of the arguments will not line up. Probably some of the last args will get combined into high/low parts of a 64-bit register when moved into registers to pass to the kernel. And then subsequent register inputs will get garbage from the stack. Need to cast them to long or size_t or whatever to prevent this.
- jagrsw 2y agoYes