Browse Source

fix wrong sigaction syscall ABI on mips*, or1k, microblaze, riscv64

we wrongly defined a dummy SA_RESTORER flag on these archs, despite
the kernel interface not actually having such a feature. on archs
which lack SA_RESTORER, the kernel sigaction structure also lacks the
restorer function pointer member, which means the signal mask appears
at a different offset. the kernel was thereby interpreting the bits of
the code address as part of the signal set to be masked while handling
the signal.

this patch removes the erroneous SA_RESTORER definitions from archs
which do not have it, makes access to the member conditional on
whether SA_RESTORER is defined for the arch, and removes the
now-unused asm for the affected archs.

because there are reportedly versions of qemu-user which also use the
wrong ABI here, the old ksigaction struct size is preserved with an
unused member at the end. this is harmless and mitigates the risk of
such a bug turning into a buffer overflow onto the sigaction
function's stack.
master
Rich Felker 4 years ago
parent
commit
269d193820
  1. 1
      arch/microblaze/bits/signal.h
  2. 1
      arch/mips/bits/signal.h
  3. 5
      arch/mips/ksigaction.h
  4. 1
      arch/mips64/bits/signal.h
  5. 2
      arch/mips64/ksigaction.h
  6. 1
      arch/mipsn32/bits/signal.h
  7. 2
      arch/mipsn32/ksigaction.h
  8. 1
      arch/or1k/bits/signal.h
  9. 1
      arch/riscv64/bits/signal.h
  10. 5
      src/internal/ksigaction.h
  11. 15
      src/signal/mips/restore.s
  12. 11
      src/signal/mips64/restore.s
  13. 11
      src/signal/mipsn32/restore.s
  14. 5
      src/signal/sigaction.c

1
arch/microblaze/bits/signal.h

@ -46,7 +46,6 @@ typedef struct __ucontext {
#define SA_RESTART 0x10000000
#define SA_NODEFER 0x40000000
#define SA_RESETHAND 0x80000000
#define SA_RESTORER 0x04000000
#endif

1
arch/mips/bits/signal.h

@ -66,7 +66,6 @@ typedef struct __ucontext {
#define SA_RESTART 0x10000000
#define SA_NODEFER 0x40000000
#define SA_RESETHAND 0x80000000
#define SA_RESTORER 0x04000000
#undef SIG_BLOCK
#undef SIG_UNBLOCK

5
arch/mips/ksigaction.h

@ -4,10 +4,7 @@ struct k_sigaction {
unsigned flags;
void (*handler)(int);
unsigned long mask[4];
/* The following field is past the end of the structure the
* kernel will read or write, and exists only to avoid having
* mips-specific preprocessor conditionals in sigaction.c. */
void (*restorer)();
void *unused;
};
hidden void __restore(), __restore_rt();

1
arch/mips64/bits/signal.h

@ -85,7 +85,6 @@ typedef struct __ucontext {
#define SA_RESTART 0x10000000
#define SA_NODEFER 0x40000000
#define SA_RESETHAND 0x80000000
#define SA_RESTORER 0x04000000
#undef SIG_BLOCK
#undef SIG_UNBLOCK

2
arch/mips64/ksigaction.h

@ -4,7 +4,7 @@ struct k_sigaction {
unsigned flags;
void (*handler)(int);
unsigned long mask[2];
void (*restorer)();
void *unused;
};
hidden void __restore(), __restore_rt();

1
arch/mipsn32/bits/signal.h

@ -85,7 +85,6 @@ typedef struct __ucontext {
#define SA_RESTART 0x10000000
#define SA_NODEFER 0x40000000
#define SA_RESETHAND 0x80000000
#define SA_RESTORER 0x04000000
#undef SIG_BLOCK
#undef SIG_UNBLOCK

2
arch/mipsn32/ksigaction.h

@ -4,7 +4,7 @@ struct k_sigaction {
unsigned flags;
void (*handler)(int);
unsigned long mask[4];
void (*restorer)();
void *unused;
};
hidden void __restore(), __restore_rt();

1
arch/or1k/bits/signal.h

@ -43,7 +43,6 @@ typedef struct __ucontext {
#define SA_RESTART 0x10000000
#define SA_NODEFER 0x40000000
#define SA_RESETHAND 0x80000000
#define SA_RESTORER 0x04000000
#endif

1
arch/riscv64/bits/signal.h

@ -76,7 +76,6 @@ typedef struct __ucontext
#define SA_RESTART 0x10000000
#define SA_NODEFER 0x40000000
#define SA_RESETHAND 0x80000000
#define SA_RESTORER 0x04000000
#endif

5
src/internal/ksigaction.h

@ -6,8 +6,13 @@
struct k_sigaction {
void (*handler)(int);
unsigned long flags;
#ifdef SA_RESTORER
void (*restorer)(void);
#endif
unsigned mask[2];
#ifndef SA_RESTORER
void *unused;
#endif
};
hidden void __restore(), __restore_rt();

15
src/signal/mips/restore.s

@ -1,15 +0,0 @@
.set noreorder
.global __restore_rt
.hidden __restore_rt
.type __restore_rt,@function
__restore_rt:
li $2, 4193
syscall
.global __restore
.hidden __restore
.type __restore,@function
__restore:
li $2, 4119
syscall

11
src/signal/mips64/restore.s

@ -1,11 +0,0 @@
.set noreorder
.global __restore_rt
.global __restore
.hidden __restore_rt
.hidden __restore
.type __restore_rt,@function
.type __restore,@function
__restore_rt:
__restore:
li $2,5211
syscall

11
src/signal/mipsn32/restore.s

@ -1,11 +0,0 @@
.set noreorder
.global __restore_rt
.global __restore
.hidden __restore_rt
.hidden __restore
.type __restore_rt,@function
.type __restore,@function
__restore_rt:
__restore:
li $2,6211
syscall

5
src/signal/sigaction.c

@ -44,8 +44,11 @@ int __libc_sigaction(int sig, const struct sigaction *restrict sa, struct sigact
}
}
ksa.handler = sa->sa_handler;
ksa.flags = sa->sa_flags | SA_RESTORER;
ksa.flags = sa->sa_flags;
#ifdef SA_RESTORER
ksa.flags |= SA_RESTORER;
ksa.restorer = (sa->sa_flags & SA_SIGINFO) ? __restore_rt : __restore;
#endif
memcpy(&ksa.mask, &sa->sa_mask, _NSIG/8);
}
int r = __syscall(SYS_rt_sigaction, sig, sa?&ksa:0, old?&ksa_old:0, _NSIG/8);

Loading…
Cancel
Save