Reputation: 48572
Consider this GNU Assembler program, that copies one byte at a time from stdin to stdout, with a delay of one second between each:
#include <sys/syscall.h>
.global _start
_start:
movq $1, -16(%rsp)
movq $0, -8(%rsp)
movl $1, %edx
.again:
xorl %edi, %edi
leaq -17(%rsp), %rsi
movl $SYS_read, %eax
syscall
cmpq $1, %rax
jne .end
leaq -16(%rsp), %rdi
xorl %esi, %esi
movl $SYS_nanosleep, %eax
syscall
movl $1, %edi
leaq -17(%rsp), %rsi
movl $SYS_write, %eax
syscall
jmp .again
.end:
xorl %edi, %edi
movl $SYS_exit_group, %eax
syscall
It passes pointers to the red zone to syscalls, for both inputs and outputs, and also expects the rest of the red zone to be preserved across unrelated syscalls. Is this a safe use of the red zone that's guaranteed to always work, or is it UB that just happened to appear to work in my test?
Upvotes: 1
Views: 128
Reputation: 37232
Is this a safe use of the red zone that's guaranteed to always work, or is it UB that just happened to appear to work in my test?
It's guaranteed to be safe by the kernel developers.
In general (to guard against deliberately malicious software) CPUs are designed so that when you switch from a lower privilege level (user-space) to a higher privilege level (kernel) the CPU forces a stack switch (e.g. from "untrusted user-space stack" to "more trusted kernel stack"); and CPU also does the reverse (switching stacks when returning from higher privilege level to lower privilege level).
This makes it easy for kernel developers to ensure that system calls (and IRQs, etc) don't interfere with a user-space thread's red zone; but it doesn't necessarily prevent a kernel from interfering with a user-space thread's red zone (a kernel could do extra work for no reason to interfere, if the kernel developer wanted their kernel to be awful).
Upvotes: 2