Commit f671c45df23005692daa200aba768c642fb14ef2

Authored by Kyle McMartin
Committed by Kyle McMartin
1 parent 16541c8745

[PARISC] Arch-specific compat signals

Add enough arch-specific compat signals code to enable parisc64
to compile and boot out of the mainline tree. There are likely still
many dragons here, but this is a start to squashing the last
big difference between the mainline tree and the parisc-linux tree.
The remaining bugs can be squashed as they come up.

Signed-off-by: Kyle McMartin <kyle@parisc-linux.org>

Showing 6 changed files with 232 additions and 14 deletions Side-by-side Diff

arch/parisc/kernel/ptrace.c
... ... @@ -91,7 +91,7 @@
91 91 int copied;
92 92  
93 93 #ifdef __LP64__
94   - if (is_compat_task(child)) {
  94 + if (personality(child->personality) == PER_LINUX32) {
95 95 unsigned int tmp;
96 96  
97 97 addr &= 0xffffffffL;
... ... @@ -123,7 +123,7 @@
123 123 case PTRACE_POKEDATA:
124 124 ret = 0;
125 125 #ifdef __LP64__
126   - if (is_compat_task(child)) {
  126 + if (personality(child->personality) == PER_LINUX32) {
127 127 unsigned int tmp = (unsigned int)data;
128 128 DBG("sys_ptrace(POKE%s, %d, %lx, %lx)\n",
129 129 request == PTRACE_POKETEXT ? "TEXT" : "DATA",
... ... @@ -146,7 +146,7 @@
146 146 case PTRACE_PEEKUSR: {
147 147 ret = -EIO;
148 148 #ifdef __LP64__
149   - if (is_compat_task(child)) {
  149 + if (personality(child->personality) == PER_LINUX32) {
150 150 unsigned int tmp;
151 151  
152 152 if (addr & (sizeof(int)-1))
... ... @@ -205,7 +205,7 @@
205 205 goto out_tsk;
206 206 }
207 207 #ifdef __LP64__
208   - if (is_compat_task(child)) {
  208 + if (personality(child->personality) == PER_LINUX32) {
209 209 if (addr & (sizeof(int)-1))
210 210 goto out_tsk;
211 211 if ((addr = translate_usr_offset(addr)) < 0)
arch/parisc/kernel/signal.c
... ... @@ -317,7 +317,7 @@
317 317  
318 318 if(personality(current->personality) == PER_LINUX32) {
319 319 DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info);
320   - err |= compat_copy_siginfo_to_user(&compat_frame->info, info);
  320 + err |= copy_siginfo_to_user32(&compat_frame->info, info);
321 321 DBG(1,"SETUP_RT_FRAME: 1\n");
322 322 compat_val = (compat_int_t)current->sas_ss_sp;
323 323 err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_sp);
arch/parisc/kernel/signal32.c
... ... @@ -31,7 +31,6 @@
31 31 #include <linux/types.h>
32 32 #include <linux/errno.h>
33 33  
34   -#include <asm/compat_signal.h>
35 34 #include <asm/uaccess.h>
36 35  
37 36 #include "signal32.h"
... ... @@ -396,6 +395,107 @@
396 395 DBG(2,"setup_sigcontext32: upper half sar = %#x\n", compat_reg);
397 396 DBG(1,"setup_sigcontext32: r28 is %ld\n", regs->gr[28]);
398 397  
  398 + return err;
  399 +}
  400 +
  401 +int
  402 +copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from)
  403 +{
  404 + unsigned long tmp;
  405 + int err;
  406 +
  407 + if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
  408 + return -EFAULT;
  409 +
  410 + err = __get_user(to->si_signo, &from->si_signo);
  411 + err |= __get_user(to->si_errno, &from->si_errno);
  412 + err |= __get_user(to->si_code, &from->si_code);
  413 +
  414 + if (to->si_code < 0)
  415 + err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
  416 + else {
  417 + switch (to->si_code >> 16) {
  418 + case __SI_CHLD >> 16:
  419 + err |= __get_user(to->si_utime, &from->si_utime);
  420 + err |= __get_user(to->si_stime, &from->si_stime);
  421 + err |= __get_user(to->si_status, &from->si_status);
  422 + default:
  423 + err |= __get_user(to->si_pid, &from->si_pid);
  424 + err |= __get_user(to->si_uid, &from->si_uid);
  425 + break;
  426 + case __SI_FAULT >> 16:
  427 + err |= __get_user(tmp, &from->si_addr);
  428 + to->si_addr = (void __user *) tmp;
  429 + break;
  430 + case __SI_POLL >> 16:
  431 + err |= __get_user(to->si_band, &from->si_band);
  432 + err |= __get_user(to->si_fd, &from->si_fd);
  433 + break;
  434 + case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
  435 + case __SI_MESGQ >> 16:
  436 + err |= __get_user(to->si_pid, &from->si_pid);
  437 + err |= __get_user(to->si_uid, &from->si_uid);
  438 + err |= __get_user(to->si_int, &from->si_int);
  439 + break;
  440 + }
  441 + }
  442 + return err;
  443 +}
  444 +
  445 +int
  446 +copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from)
  447 +{
  448 + unsigned int addr;
  449 + int err;
  450 +
  451 + if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
  452 + return -EFAULT;
  453 +
  454 + /* If you change siginfo_t structure, please be sure
  455 + this code is fixed accordingly.
  456 + It should never copy any pad contained in the structure
  457 + to avoid security leaks, but must copy the generic
  458 + 3 ints plus the relevant union member.
  459 + This routine must convert siginfo from 64bit to 32bit as well
  460 + at the same time. */
  461 + err = __put_user(from->si_signo, &to->si_signo);
  462 + err |= __put_user(from->si_errno, &to->si_errno);
  463 + err |= __put_user((short)from->si_code, &to->si_code);
  464 + if (from->si_code < 0)
  465 + err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
  466 + else {
  467 + switch (from->si_code >> 16) {
  468 + case __SI_CHLD >> 16:
  469 + err |= __put_user(from->si_utime, &to->si_utime);
  470 + err |= __put_user(from->si_stime, &to->si_stime);
  471 + err |= __put_user(from->si_status, &to->si_status);
  472 + default:
  473 + err |= __put_user(from->si_pid, &to->si_pid);
  474 + err |= __put_user(from->si_uid, &to->si_uid);
  475 + break;
  476 + case __SI_FAULT >> 16:
  477 + /* avoid type-checking warnings by copying _pad[0] in lieu of si_addr... */
  478 + err |= __put_user(from->_sifields._pad[0], &to->si_addr);
  479 + break;
  480 + case __SI_POLL >> 16:
  481 + err |= __put_user(from->si_band, &to->si_band);
  482 + err |= __put_user(from->si_fd, &to->si_fd);
  483 + break;
  484 + case __SI_TIMER >> 16:
  485 + err |= __put_user(from->si_tid, &to->si_tid);
  486 + err |= __put_user(from->si_overrun, &to->si_overrun);
  487 + addr = (unsigned long) from->si_ptr;
  488 + err |= __put_user(addr, &to->si_ptr);
  489 + break;
  490 + case __SI_RT >> 16: /* Not generated by the kernel as of now. */
  491 + case __SI_MESGQ >> 16:
  492 + err |= __put_user(from->si_uid, &to->si_uid);
  493 + err |= __put_user(from->si_pid, &to->si_pid);
  494 + addr = (unsigned long) from->si_ptr;
  495 + err |= __put_user(addr, &to->si_ptr);
  496 + break;
  497 + }
  498 + }
399 499 return err;
400 500 }
arch/parisc/kernel/signal32.h
... ... @@ -20,14 +20,137 @@
20 20 #define _PARISC64_KERNEL_SIGNAL32_H
21 21  
22 22 #include <linux/compat.h>
23   -#include <asm/compat_signal.h>
24   -#include <asm/compat_rt_sigframe.h>
25 23  
  24 +typedef compat_uptr_t compat_sighandler_t;
  25 +
  26 +typedef struct compat_sigaltstack {
  27 + compat_uptr_t ss_sp;
  28 + compat_int_t ss_flags;
  29 + compat_size_t ss_size;
  30 +} compat_stack_t;
  31 +
  32 +/* Most things should be clean enough to redefine this at will, if care
  33 + is taken to make libc match. */
  34 +
  35 +struct compat_sigaction {
  36 + compat_sighandler_t sa_handler;
  37 + compat_uint_t sa_flags;
  38 + compat_sigset_t sa_mask; /* mask last for extensibility */
  39 +};
  40 +
  41 +/* 32-bit ucontext as seen from an 64-bit kernel */
  42 +struct compat_ucontext {
  43 + compat_uint_t uc_flags;
  44 + compat_uptr_t uc_link;
  45 + compat_stack_t uc_stack; /* struct compat_sigaltstack (12 bytes)*/
  46 + /* FIXME: Pad out to get uc_mcontext to start at an 8-byte aligned boundary */
  47 + compat_uint_t pad[1];
  48 + struct compat_sigcontext uc_mcontext;
  49 + compat_sigset_t uc_sigmask; /* mask last for extensibility */
  50 +};
  51 +
26 52 /* ELF32 signal handling */
27 53  
28 54 struct k_sigaction32 {
29 55 struct compat_sigaction sa;
30 56 };
  57 +
  58 +typedef struct compat_siginfo {
  59 + int si_signo;
  60 + int si_errno;
  61 + int si_code;
  62 +
  63 + union {
  64 + int _pad[((128/sizeof(int)) - 3)];
  65 +
  66 + /* kill() */
  67 + struct {
  68 + unsigned int _pid; /* sender's pid */
  69 + unsigned int _uid; /* sender's uid */
  70 + } _kill;
  71 +
  72 + /* POSIX.1b timers */
  73 + struct {
  74 + compat_timer_t _tid; /* timer id */
  75 + int _overrun; /* overrun count */
  76 + char _pad[sizeof(unsigned int) - sizeof(int)];
  77 + compat_sigval_t _sigval; /* same as below */
  78 + int _sys_private; /* not to be passed to user */
  79 + } _timer;
  80 +
  81 + /* POSIX.1b signals */
  82 + struct {
  83 + unsigned int _pid; /* sender's pid */
  84 + unsigned int _uid; /* sender's uid */
  85 + compat_sigval_t _sigval;
  86 + } _rt;
  87 +
  88 + /* SIGCHLD */
  89 + struct {
  90 + unsigned int _pid; /* which child */
  91 + unsigned int _uid; /* sender's uid */
  92 + int _status; /* exit code */
  93 + compat_clock_t _utime;
  94 + compat_clock_t _stime;
  95 + } _sigchld;
  96 +
  97 + /* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
  98 + struct {
  99 + unsigned int _addr; /* faulting insn/memory ref. */
  100 + } _sigfault;
  101 +
  102 + /* SIGPOLL */
  103 + struct {
  104 + int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
  105 + int _fd;
  106 + } _sigpoll;
  107 + } _sifields;
  108 +} compat_siginfo_t;
  109 +
  110 +int copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from);
  111 +int copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from);
  112 +
  113 +/* In a deft move of uber-hackery, we decide to carry the top half of all
  114 + * 64-bit registers in a non-portable, non-ABI, hidden structure.
  115 + * Userspace can read the hidden structure if it *wants* but is never
  116 + * guaranteed to be in the same place. Infact the uc_sigmask from the
  117 + * ucontext_t structure may push the hidden register file downards
  118 + */
  119 +struct compat_regfile {
  120 + /* Upper half of all the 64-bit registers that were truncated
  121 + on a copy to a 32-bit userspace */
  122 + compat_int_t rf_gr[32];
  123 + compat_int_t rf_iasq[2];
  124 + compat_int_t rf_iaoq[2];
  125 + compat_int_t rf_sar;
  126 +};
  127 +
  128 +#define COMPAT_SIGRETURN_TRAMP 4
  129 +#define COMPAT_SIGRESTARTBLOCK_TRAMP 5
  130 +#define COMPAT_TRAMP_SIZE (COMPAT_SIGRETURN_TRAMP + \
  131 + COMPAT_SIGRESTARTBLOCK_TRAMP)
  132 +
  133 +struct compat_rt_sigframe {
  134 + /* XXX: Must match trampoline size in arch/parisc/kernel/signal.c
  135 + Secondary to that it must protect the ERESTART_RESTARTBLOCK
  136 + trampoline we left on the stack (we were bad and didn't
  137 + change sp so we could run really fast.) */
  138 + compat_uint_t tramp[COMPAT_TRAMP_SIZE];
  139 + compat_siginfo_t info;
  140 + struct compat_ucontext uc;
  141 + /* Hidden location of truncated registers, *must* be last. */
  142 + struct compat_regfile regs;
  143 +};
  144 +
  145 +/*
  146 + * The 32-bit ABI wants at least 48 bytes for a function call frame:
  147 + * 16 bytes for arg0-arg3, and 32 bytes for magic (the only part of
  148 + * which Linux/parisc uses is sp-20 for the saved return pointer...)
  149 + * Then, the stack pointer must be rounded to a cache line (64 bytes).
  150 + */
  151 +#define SIGFRAME32 64
  152 +#define FUNCTIONCALLFRAME32 48
  153 +#define PARISC_RT_SIGFRAME_SIZE32 (((sizeof(struct compat_rt_sigframe) + FUNCTIONCALLFRAME32) + SIGFRAME32) & -SIGFRAME32)
31 154  
32 155 void sigset_32to64(sigset_t *s64, compat_sigset_t *s32);
33 156 void sigset_64to32(compat_sigset_t *s32, sigset_t *s64);
include/asm-parisc/compat_ucontext.h
1 1 #ifndef _ASM_PARISC_COMPAT_UCONTEXT_H
2 2 #define _ASM_PARISC_COMPAT_UCONTEXT_H
3 3  
4   -#include<linux/compat.h>
5   -#include<asm/compat_signal.h>
  4 +#include <linux/compat.h>
6 5  
7 6 /* 32-bit ucontext as seen from an 64-bit kernel */
8 7 struct compat_ucontext {
include/asm-parisc/rt_sigframe.h
1 1 #ifndef _ASM_PARISC_RT_SIGFRAME_H
2 2 #define _ASM_PARISC_RT_SIGFRAME_H
3 3  
4   -#ifdef CONFIG_COMPAT
5   -#include <asm/compat_rt_sigframe.h>
6   -#endif
7   -
8 4 #define SIGRETURN_TRAMP 4
9 5 #define SIGRESTARTBLOCK_TRAMP 5
10 6 #define TRAMP_SIZE (SIGRETURN_TRAMP + SIGRESTARTBLOCK_TRAMP)