aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKyle McMartin <kyle@parisc-linux.org>2006-01-15 14:10:29 -0500
committerKyle McMartin <kyle@duet.int.mcmartin.ca>2006-01-22 20:57:42 -0500
commitf671c45df23005692daa200aba768c642fb14ef2 (patch)
treefbc882669f06171cd1a8be2ad7b99f062a6e1e57
parent16541c8745e28f62b3dcb6cb354b73c9c01ea178 (diff)
[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>
-rw-r--r--arch/parisc/kernel/ptrace.c8
-rw-r--r--arch/parisc/kernel/signal.c2
-rw-r--r--arch/parisc/kernel/signal32.c102
-rw-r--r--arch/parisc/kernel/signal32.h127
-rw-r--r--include/asm-parisc/compat_ucontext.h3
-rw-r--r--include/asm-parisc/rt_sigframe.h4
6 files changed, 232 insertions, 14 deletions
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index 27160e8bf15b..413292f1a4a3 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -91,7 +91,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
91 int copied; 91 int copied;
92 92
93#ifdef __LP64__ 93#ifdef __LP64__
94 if (is_compat_task(child)) { 94 if (personality(child->personality) == PER_LINUX32) {
95 unsigned int tmp; 95 unsigned int tmp;
96 96
97 addr &= 0xffffffffL; 97 addr &= 0xffffffffL;
@@ -123,7 +123,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
123 case PTRACE_POKEDATA: 123 case PTRACE_POKEDATA:
124 ret = 0; 124 ret = 0;
125#ifdef __LP64__ 125#ifdef __LP64__
126 if (is_compat_task(child)) { 126 if (personality(child->personality) == PER_LINUX32) {
127 unsigned int tmp = (unsigned int)data; 127 unsigned int tmp = (unsigned int)data;
128 DBG("sys_ptrace(POKE%s, %d, %lx, %lx)\n", 128 DBG("sys_ptrace(POKE%s, %d, %lx, %lx)\n",
129 request == PTRACE_POKETEXT ? "TEXT" : "DATA", 129 request == PTRACE_POKETEXT ? "TEXT" : "DATA",
@@ -146,7 +146,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
146 case PTRACE_PEEKUSR: { 146 case PTRACE_PEEKUSR: {
147 ret = -EIO; 147 ret = -EIO;
148#ifdef __LP64__ 148#ifdef __LP64__
149 if (is_compat_task(child)) { 149 if (personality(child->personality) == PER_LINUX32) {
150 unsigned int tmp; 150 unsigned int tmp;
151 151
152 if (addr & (sizeof(int)-1)) 152 if (addr & (sizeof(int)-1))
@@ -205,7 +205,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
205 goto out_tsk; 205 goto out_tsk;
206 } 206 }
207#ifdef __LP64__ 207#ifdef __LP64__
208 if (is_compat_task(child)) { 208 if (personality(child->personality) == PER_LINUX32) {
209 if (addr & (sizeof(int)-1)) 209 if (addr & (sizeof(int)-1))
210 goto out_tsk; 210 goto out_tsk;
211 if ((addr = translate_usr_offset(addr)) < 0) 211 if ((addr = translate_usr_offset(addr)) < 0)
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
index 3a25a7bd673e..05767e83cf2d 100644
--- a/arch/parisc/kernel/signal.c
+++ b/arch/parisc/kernel/signal.c
@@ -317,7 +317,7 @@ setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
317 317
318 if(personality(current->personality) == PER_LINUX32) { 318 if(personality(current->personality) == PER_LINUX32) {
319 DBG(1,"setup_rt_frame: frame->info = 0x%p\n", &compat_frame->info); 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 DBG(1,"SETUP_RT_FRAME: 1\n"); 321 DBG(1,"SETUP_RT_FRAME: 1\n");
322 compat_val = (compat_int_t)current->sas_ss_sp; 322 compat_val = (compat_int_t)current->sas_ss_sp;
323 err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_sp); 323 err |= __put_user(compat_val, &compat_frame->uc.uc_stack.ss_sp);
diff --git a/arch/parisc/kernel/signal32.c b/arch/parisc/kernel/signal32.c
index 0792e20efef3..a6b4231cafa1 100644
--- a/arch/parisc/kernel/signal32.c
+++ b/arch/parisc/kernel/signal32.c
@@ -31,7 +31,6 @@
31#include <linux/types.h> 31#include <linux/types.h>
32#include <linux/errno.h> 32#include <linux/errno.h>
33 33
34#include <asm/compat_signal.h>
35#include <asm/uaccess.h> 34#include <asm/uaccess.h>
36 35
37#include "signal32.h" 36#include "signal32.h"
@@ -398,3 +397,104 @@ setup_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __
398 397
399 return err; 398 return err;
400} 399}
400
401int
402copy_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
445int
446copy_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 }
499 return err;
500}
diff --git a/arch/parisc/kernel/signal32.h b/arch/parisc/kernel/signal32.h
index 4d1569e717cc..e39b38a67a87 100644
--- a/arch/parisc/kernel/signal32.h
+++ b/arch/parisc/kernel/signal32.h
@@ -20,8 +20,34 @@
20#define _PARISC64_KERNEL_SIGNAL32_H 20#define _PARISC64_KERNEL_SIGNAL32_H
21 21
22#include <linux/compat.h> 22#include <linux/compat.h>
23#include <asm/compat_signal.h> 23
24#include <asm/compat_rt_sigframe.h> 24typedef compat_uptr_t compat_sighandler_t;
25
26typedef 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
35struct 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 */
42struct 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};
25 51
26/* ELF32 signal handling */ 52/* ELF32 signal handling */
27 53
@@ -29,6 +55,103 @@ struct k_sigaction32 {
29 struct compat_sigaction sa; 55 struct compat_sigaction sa;
30}; 56};
31 57
58typedef 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
110int copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from);
111int 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 */
119struct 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
133struct 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)
154
32void sigset_32to64(sigset_t *s64, compat_sigset_t *s32); 155void sigset_32to64(sigset_t *s64, compat_sigset_t *s32);
33void sigset_64to32(compat_sigset_t *s32, sigset_t *s64); 156void sigset_64to32(compat_sigset_t *s32, sigset_t *s64);
34int do_sigaltstack32 (const compat_stack_t __user *uss32, 157int do_sigaltstack32 (const compat_stack_t __user *uss32,
diff --git a/include/asm-parisc/compat_ucontext.h b/include/asm-parisc/compat_ucontext.h
index a1228a3d2071..2f7292afde3c 100644
--- a/include/asm-parisc/compat_ucontext.h
+++ b/include/asm-parisc/compat_ucontext.h
@@ -1,8 +1,7 @@
1#ifndef _ASM_PARISC_COMPAT_UCONTEXT_H 1#ifndef _ASM_PARISC_COMPAT_UCONTEXT_H
2#define _ASM_PARISC_COMPAT_UCONTEXT_H 2#define _ASM_PARISC_COMPAT_UCONTEXT_H
3 3
4#include<linux/compat.h> 4#include <linux/compat.h>
5#include<asm/compat_signal.h>
6 5
7/* 32-bit ucontext as seen from an 64-bit kernel */ 6/* 32-bit ucontext as seen from an 64-bit kernel */
8struct compat_ucontext { 7struct compat_ucontext {
diff --git a/include/asm-parisc/rt_sigframe.h b/include/asm-parisc/rt_sigframe.h
index 5623c032b64c..f0dd3b30f6c4 100644
--- a/include/asm-parisc/rt_sigframe.h
+++ b/include/asm-parisc/rt_sigframe.h
@@ -1,10 +1,6 @@
1#ifndef _ASM_PARISC_RT_SIGFRAME_H 1#ifndef _ASM_PARISC_RT_SIGFRAME_H
2#define _ASM_PARISC_RT_SIGFRAME_H 2#define _ASM_PARISC_RT_SIGFRAME_H
3 3
4#ifdef CONFIG_COMPAT
5#include <asm/compat_rt_sigframe.h>
6#endif
7
8#define SIGRETURN_TRAMP 4 4#define SIGRETURN_TRAMP 4
9#define SIGRESTARTBLOCK_TRAMP 5 5#define SIGRESTARTBLOCK_TRAMP 5
10#define TRAMP_SIZE (SIGRETURN_TRAMP + SIGRESTARTBLOCK_TRAMP) 6#define TRAMP_SIZE (SIGRETURN_TRAMP + SIGRESTARTBLOCK_TRAMP)