[SystemZ] [Sanitizer] Bugfixes in internal_clone().

The __flags variable needs to be of type 'long' in order to get sign extended
properly.

internal_clone() uses an svc (Supervisor Call) directly (as opposed to
internal_syscall), and therefore needs to take care to set errno and return
-1 as needed.

Review: Ulrich Weigand
This commit is contained in:
Jonas Paulsson 2021-11-10 20:27:42 +01:00
parent 5f99f771ec
commit 4c32e3d967
1 changed files with 10 additions and 4 deletions

View File

@ -57,8 +57,10 @@ uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd,
uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
int *parent_tidptr, void *newtls, int *child_tidptr) {
if (!fn || !child_stack)
return -EINVAL;
if (!fn || !child_stack) {
errno = EINVAL;
return -1;
}
CHECK_EQ(0, (uptr)child_stack % 16);
// Minimum frame size.
#ifdef __s390x__
@ -71,9 +73,9 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
// And pass parameters.
((unsigned long *)child_stack)[1] = (uptr)fn;
((unsigned long *)child_stack)[2] = (uptr)arg;
register long res __asm__("r2");
register uptr res __asm__("r2");
register void *__cstack __asm__("r2") = child_stack;
register int __flags __asm__("r3") = flags;
register long __flags __asm__("r3") = flags;
register int * __ptidptr __asm__("r4") = parent_tidptr;
register int * __ctidptr __asm__("r5") = child_tidptr;
register void * __newtls __asm__("r6") = newtls;
@ -113,6 +115,10 @@ uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg,
"r"(__ctidptr),
"r"(__newtls)
: "memory", "cc");
if (res >= (uptr)-4095) {
errno = -res;
return -1;
}
return res;
}