Browse Source

fix signal return for sh/fdpic

the restorer function pointer provided in the kernel sigaction
structure is interpreted by the kernel as a raw code address, not a
function descriptor.

this commit moves the declarations of the __restore and __restore_rt
symbols to ksigaction.h so that arch versions of the file can override
them, and introduces a version for sh which declares them as objects
rather than functions.

an alternate solution would have been defining SA_RESTORER to 0 so
that the functions are not used, but this both requires executable
stack (since the sh kernel does not have a vdso page with permanent
restorer functions) and crashes on qemu user-level emulation.
Rich Felker 9 years ago
parent
commit
b61df2294f
5 changed files with 12 additions and 4 deletions
  1. 2 0
      arch/mips/ksigaction.h
  2. 8 0
      arch/sh/ksigaction.h
  3. 2 0
      src/internal/ksigaction.h
  4. 0 2
      src/signal/sh/restore.s
  5. 0 2
      src/signal/sigaction.c

+ 2 - 0
arch/mips/ksigaction.h

@@ -7,3 +7,5 @@ struct k_sigaction {
 	 * mips-specific preprocessor conditionals in sigaction.c. */
 	void (*restorer)();
 };
+
+void __restore(), __restore_rt();

+ 8 - 0
arch/sh/ksigaction.h

@@ -0,0 +1,8 @@
+struct k_sigaction {
+	void (*handler)(int);
+	unsigned long flags;
+	void *restorer;
+	unsigned mask[2];
+};
+
+extern unsigned char __restore[], __restore_rt[];

+ 2 - 0
src/internal/ksigaction.h

@@ -7,3 +7,5 @@ struct k_sigaction {
 	void (*restorer)(void);
 	unsigned mask[2];
 };
+
+void __restore(), __restore_rt();

+ 0 - 2
src/signal/sh/restore.s

@@ -1,5 +1,4 @@
 .global __restore
-.type   __restore, @function
 __restore:
 	mov   #119, r3  !__NR_sigreturn
 	trapa #31
@@ -11,7 +10,6 @@ __restore:
 	or    r0, r0
 
 .global __restore_rt
-.type   __restore_rt, @function
 __restore_rt:
 	mov   #100, r3  !__NR_rt_sigreturn
 	add   #73, r3

+ 0 - 2
src/signal/sigaction.c

@@ -6,8 +6,6 @@
 #include "libc.h"
 #include "ksigaction.h"
 
-void __restore(), __restore_rt();
-
 static int unmask_done;
 static unsigned long handler_set[_NSIG/(8*sizeof(long))];