mirror of
git://git.musl-libc.org/musl
synced 2025-03-06 20:48:29 +01:00
fix failure to preserve r6 in s390x asm; per ABI it is call-saved
both __clone and __syscall_cp_asm failed to restore the original value of r6 after using it as a syscall argument register. the extent of breakage is not known, and in some cases may be mitigated by the only callers being internal to libc; if they used r6 but no longer needed its value after the call, they may not have noticed the problem. however at least posix_spawn (which uses __clone) was observed returning to the application with the wrong value in r6, leading to crash. since the call frame ABI already provides a place to spill registers, fixing this is just a matter of using it. in __clone, we also spuriously restore r6 in the child, since the parent branch directly returns to the caller. this takes the value from an uninitialized slot of the child's stack, but is harmless since there is no caller to return to in the child.
This commit is contained in:
parent
738c4e945c
commit
50c7935cd2
2 changed files with 8 additions and 0 deletions
|
@ -17,6 +17,9 @@ __clone:
|
|||
# if (!tid) syscall(SYS_exit, a(d));
|
||||
# return tid;
|
||||
|
||||
# preserve call-saved register used as syscall arg
|
||||
stg %r6, 48(%r15)
|
||||
|
||||
# create initial stack frame for new thread
|
||||
nill %r3, 0xfff8
|
||||
aghi %r3, -160
|
||||
|
@ -35,6 +38,9 @@ __clone:
|
|||
lg %r6, 160(%r15)
|
||||
svc 120
|
||||
|
||||
# restore call-saved register
|
||||
lg %r6, 48(%r15)
|
||||
|
||||
# if error or if we're the parent, return
|
||||
ltgr %r2, %r2
|
||||
bnzr %r14
|
||||
|
|
|
@ -14,6 +14,7 @@ __cp_begin:
|
|||
icm %r2, 15, 0(%r2)
|
||||
jne __cp_cancel
|
||||
|
||||
stg %r6, 48(%r15)
|
||||
stg %r7, 56(%r15)
|
||||
lgr %r1, %r3
|
||||
lgr %r2, %r4
|
||||
|
@ -26,6 +27,7 @@ __cp_begin:
|
|||
|
||||
__cp_end:
|
||||
lg %r7, 56(%r15)
|
||||
lg %r6, 48(%r15)
|
||||
br %r14
|
||||
|
||||
__cp_cancel:
|
||||
|
|
Loading…
Add table
Reference in a new issue