Просмотр исходного кода

nios2: add the missing clone() argument and error checks

The nios2 __clone() had a "Sanity check arguments" comment and loaded
EINVAL into r2, but never actually tested the arguments and never
checked the syscall result. With a NULL child stack (r5 == 0) the
prologue did "subi r5, r5, 8" and then "stw r4, 4(r5)", writing to
0xfffffffc and taking a SIGSEGV before the trap was ever issued; a
NULL function pointer had the same fate. clone() with a bad stack is
required to fail with EINVAL, not crash -- the uClibc-ng-test "errno"
test does exactly this and segfaulted on nios2.

Add the two argument checks and, after the trap, the error check that
the other ports have. nios2 signals a failed syscall in r7 and returns
the (positive) error number in r2, so the error path negates r2 and
tail-calls __syscall_error, which sets errno and returns -1. This
mirrors glibc's nios2 clone.S.

Verified under qemu-system-nios2: clone(fn, NULL, 0, NULL) now returns
-1/EINVAL and the "errno" test passes instead of crashing.

Signed-off-by: Ramin Moussavi <ramin.moussavi@yacoub.de>
ramin 3 дней назад
Родитель
Сommit
0aab5ecb15
1 измененных файлов с 18 добавлено и 0 удалено
  1. 18 0
      libc/sysdeps/linux/nios2/clone.S

+ 18 - 0
libc/sysdeps/linux/nios2/clone.S

@@ -33,6 +33,8 @@
 ENTRY(__clone)
 ENTRY(__clone)
 	/* Sanity check arguments.  */
 	/* Sanity check arguments.  */
 	movi	r2, EINVAL
 	movi	r2, EINVAL
+	beq	r4, zero, .Lerror	/* No NULL function pointers.  */
+	beq	r5, zero, .Lerror	/* No NULL stack pointers.  */
 
 
 	subi	r5, r5, 8	/* Reserve argument save space.  */
 	subi	r5, r5, 8	/* Reserve argument save space.  */
 	stw	r4, 4(r5)	/* Save function pointer.  */
 	stw	r4, 4(r5)	/* Save function pointer.  */
@@ -49,11 +51,27 @@ ENTRY(__clone)
 
 
 	trap
 	trap
 
 
+	/* Check for error: nios2 flags it in r7 and returns the errno in r2.  */
+	bne	r7, zero, .Lerror
 	/* See if we're on the newly created thread.  */
 	/* See if we're on the newly created thread.  */
 	beq	r2, zero, thread_start
 	beq	r2, zero, thread_start
 	/* Successful return from the parent */
 	/* Successful return from the parent */
 	ret
 	ret
 
 
+.Lerror:
+	/* __syscall_error expects the negated error number.  */
+	sub	r4, zero, r2
+#ifdef __PIC__
+	nextpc	r22
+1:	movhi	r8, %hiadj(_gp_got - 1b)
+	addi	r8, r8, %lo(_gp_got - 1b)
+	add	r22, r22, r8
+	ldw	r8, %call(__syscall_error)(r22)
+	jmp	r8
+#else
+	jmpi	__syscall_error
+#endif
+
 thread_start:
 thread_start:
 	/* We expect the argument registers to be preserved across system
 	/* We expect the argument registers to be preserved across system
 	   calls and across task cloning, so flags should be in r4 here.  */
 	   calls and across task cloning, so flags should be in r4 here.  */