authorgravatar for contact@taylor.fishtaylor.fish <contact@taylor.fish> 2025-06-21 21:47:58-07:00
committergravatar for contact@taylor.fishtaylor.fish <contact@taylor.fish> 2025-06-21 21:47:58-07:00
log79807468e747bac056cfea4340065e49a5d97120
tree7e5e328c249d73527b425c3c45df20c542c876d3
parent75d0ec9c0476da61c6f32b3d386d8844faaeb1c5

Fix illegal behavior from syscalls on powerpc64le

On powerpc64le Linux, the registers used for passing syscall parameters (r4-r8, as well as r0 for the syscall number) are volatile, or caller-saved. However, Zig's syscall wrappers for this architecture do not include all such registers in the list of clobbers, leading the compiler to assume these registers will maintain their values after the syscall completes. In practice, this resulted in a segfault when allocating memory with `std.heap.SmpAllocator`, which calls `std.os.linux.sched_getaffinity`. The third parameter to `sched_getaffinity` is a pointer to a `cpu_set_t` and is stored in register r5. After the syscall, the code attempts to access data in the `cpu_set_t`, but because the compiler doesn't realize the value of r5 may have changed, it uses r5 as the memory address, which in practice resulted in a memory access at address 0x8. This commit adds all volatile registers to the list of clobbers.

1 files changed, 7 insertions(+), 7 deletions(-)

lib/std/os/linux/powerpc64.zig+7-7
...@@ -22,7 +22,7 @@ pub fn syscall0(number: SYS) usize {...@@ -22,7 +22,7 @@ pub fn syscall0(number: SYS) usize {
22 \\ 1:22 \\ 1:
23 : [ret] "={r3}" (-> usize),23 : [ret] "={r3}" (-> usize),
24 : [number] "{r0}" (@intFromEnum(number)),24 : [number] "{r0}" (@intFromEnum(number)),
25 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"25 : "memory", "cr0", "r0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
26 );26 );
27}27}
2828
...@@ -35,7 +35,7 @@ pub fn syscall1(number: SYS, arg1: usize) usize {...@@ -35,7 +35,7 @@ pub fn syscall1(number: SYS, arg1: usize) usize {
35 : [ret] "={r3}" (-> usize),35 : [ret] "={r3}" (-> usize),
36 : [number] "{r0}" (@intFromEnum(number)),36 : [number] "{r0}" (@intFromEnum(number)),
37 [arg1] "{r3}" (arg1),37 [arg1] "{r3}" (arg1),
38 : "memory", "cr0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"38 : "memory", "cr0", "r0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
39 );39 );
40}40}
4141
...@@ -49,7 +49,7 @@ pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {...@@ -49,7 +49,7 @@ pub fn syscall2(number: SYS, arg1: usize, arg2: usize) usize {
49 : [number] "{r0}" (@intFromEnum(number)),49 : [number] "{r0}" (@intFromEnum(number)),
50 [arg1] "{r3}" (arg1),50 [arg1] "{r3}" (arg1),
51 [arg2] "{r4}" (arg2),51 [arg2] "{r4}" (arg2),
52 : "memory", "cr0", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"52 : "memory", "cr0", "r0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
53 );53 );
54}54}
5555
...@@ -64,7 +64,7 @@ pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {...@@ -64,7 +64,7 @@ pub fn syscall3(number: SYS, arg1: usize, arg2: usize, arg3: usize) usize {
64 [arg1] "{r3}" (arg1),64 [arg1] "{r3}" (arg1),
65 [arg2] "{r4}" (arg2),65 [arg2] "{r4}" (arg2),
66 [arg3] "{r5}" (arg3),66 [arg3] "{r5}" (arg3),
67 : "memory", "cr0", "r6", "r7", "r8", "r9", "r10", "r11", "r12"67 : "memory", "cr0", "r0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
68 );68 );
69}69}
7070
...@@ -80,7 +80,7 @@ pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize)...@@ -80,7 +80,7 @@ pub fn syscall4(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize)
80 [arg2] "{r4}" (arg2),80 [arg2] "{r4}" (arg2),
81 [arg3] "{r5}" (arg3),81 [arg3] "{r5}" (arg3),
82 [arg4] "{r6}" (arg4),82 [arg4] "{r6}" (arg4),
83 : "memory", "cr0", "r7", "r8", "r9", "r10", "r11", "r12"83 : "memory", "cr0", "r0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
84 );84 );
85}85}
8686
...@@ -97,7 +97,7 @@ pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize,...@@ -97,7 +97,7 @@ pub fn syscall5(number: SYS, arg1: usize, arg2: usize, arg3: usize, arg4: usize,
97 [arg3] "{r5}" (arg3),97 [arg3] "{r5}" (arg3),
98 [arg4] "{r6}" (arg4),98 [arg4] "{r6}" (arg4),
99 [arg5] "{r7}" (arg5),99 [arg5] "{r7}" (arg5),
100 : "memory", "cr0", "r8", "r9", "r10", "r11", "r12"100 : "memory", "cr0", "r0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
101 );101 );
102}102}
103103
...@@ -123,7 +123,7 @@ pub fn syscall6(...@@ -123,7 +123,7 @@ pub fn syscall6(
123 [arg4] "{r6}" (arg4),123 [arg4] "{r6}" (arg4),
124 [arg5] "{r7}" (arg5),124 [arg5] "{r7}" (arg5),
125 [arg6] "{r8}" (arg6),125 [arg6] "{r8}" (arg6),
126 : "memory", "cr0", "r9", "r10", "r11", "r12"126 : "memory", "cr0", "r0", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12"
127 );127 );
128}128}
129129