Loading...
1// SPDX-License-Identifier: GPL-2.0-or-later
2/* Signal support for 32-bit kernel builds
3 *
4 * Copyright (C) 2001 Matthew Wilcox <willy at parisc-linux.org>
5 * Copyright (C) 2006 Kyle McMartin <kyle at parisc-linux.org>
6 *
7 * Code was mostly borrowed from kernel/signal.c.
8 * See kernel/signal.c for additional Copyrights.
9 */
10
11#include <linux/compat.h>
12#include <linux/module.h>
13#include <linux/unistd.h>
14#include <linux/init.h>
15#include <linux/sched.h>
16#include <linux/syscalls.h>
17#include <linux/types.h>
18#include <linux/errno.h>
19
20#include <linux/uaccess.h>
21
22#include "signal32.h"
23
24#define DEBUG_COMPAT_SIG 0
25#define DEBUG_COMPAT_SIG_LEVEL 2
26
27#if DEBUG_COMPAT_SIG
28#define DBG(LEVEL, ...) \
29 ((DEBUG_COMPAT_SIG_LEVEL >= LEVEL) \
30 ? printk(__VA_ARGS__) : (void) 0)
31#else
32#define DBG(LEVEL, ...)
33#endif
34
35long
36restore_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf,
37 struct pt_regs *regs)
38{
39 long err = 0;
40 compat_uint_t compat_reg;
41 compat_uint_t compat_regt;
42 int regn;
43
44 /* When loading 32-bit values into 64-bit registers make
45 sure to clear the upper 32-bits */
46 DBG(2,"restore_sigcontext32: PER_LINUX32 process\n");
47 DBG(2,"restore_sigcontext32: sc = 0x%p, rf = 0x%p, regs = 0x%p\n", sc, rf, regs);
48 DBG(2,"restore_sigcontext32: compat_sigcontext is %#lx bytes\n", sizeof(*sc));
49 for(regn=0; regn < 32; regn++){
50 err |= __get_user(compat_reg,&sc->sc_gr[regn]);
51 regs->gr[regn] = compat_reg;
52 /* Load upper half */
53 err |= __get_user(compat_regt,&rf->rf_gr[regn]);
54 regs->gr[regn] = ((u64)compat_regt << 32) | (u64)compat_reg;
55 DBG(3,"restore_sigcontext32: gr%02d = %#lx (%#x / %#x)\n",
56 regn, regs->gr[regn], compat_regt, compat_reg);
57 }
58 DBG(2,"restore_sigcontext32: sc->sc_fr = 0x%p (%#lx)\n",sc->sc_fr, sizeof(sc->sc_fr));
59 /* XXX: BE WARNED FR's are 64-BIT! */
60 err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr));
61
62 /* Better safe than sorry, pass __get_user two things of
63 the same size and let gcc do the upward conversion to
64 64-bits */
65 err |= __get_user(compat_reg, &sc->sc_iaoq[0]);
66 /* Load upper half */
67 err |= __get_user(compat_regt, &rf->rf_iaoq[0]);
68 regs->iaoq[0] = ((u64)compat_regt << 32) | (u64)compat_reg;
69 DBG(2,"restore_sigcontext32: upper half of iaoq[0] = %#lx\n", compat_regt);
70 DBG(2,"restore_sigcontext32: sc->sc_iaoq[0] = %p => %#x\n",
71 &sc->sc_iaoq[0], compat_reg);
72
73 err |= __get_user(compat_reg, &sc->sc_iaoq[1]);
74 /* Load upper half */
75 err |= __get_user(compat_regt, &rf->rf_iaoq[1]);
76 regs->iaoq[1] = ((u64)compat_regt << 32) | (u64)compat_reg;
77 DBG(2,"restore_sigcontext32: upper half of iaoq[1] = %#lx\n", compat_regt);
78 DBG(2,"restore_sigcontext32: sc->sc_iaoq[1] = %p => %#x\n",
79 &sc->sc_iaoq[1],compat_reg);
80 DBG(2,"restore_sigcontext32: iaoq is %#lx / %#lx\n",
81 regs->iaoq[0],regs->iaoq[1]);
82
83 err |= __get_user(compat_reg, &sc->sc_iasq[0]);
84 /* Load the upper half for iasq */
85 err |= __get_user(compat_regt, &rf->rf_iasq[0]);
86 regs->iasq[0] = ((u64)compat_regt << 32) | (u64)compat_reg;
87 DBG(2,"restore_sigcontext32: upper half of iasq[0] = %#lx\n", compat_regt);
88
89 err |= __get_user(compat_reg, &sc->sc_iasq[1]);
90 /* Load the upper half for iasq */
91 err |= __get_user(compat_regt, &rf->rf_iasq[1]);
92 regs->iasq[1] = ((u64)compat_regt << 32) | (u64)compat_reg;
93 DBG(2,"restore_sigcontext32: upper half of iasq[1] = %#lx\n", compat_regt);
94 DBG(2,"restore_sigcontext32: iasq is %#lx / %#lx\n",
95 regs->iasq[0],regs->iasq[1]);
96
97 err |= __get_user(compat_reg, &sc->sc_sar);
98 /* Load the upper half for sar */
99 err |= __get_user(compat_regt, &rf->rf_sar);
100 regs->sar = ((u64)compat_regt << 32) | (u64)compat_reg;
101 DBG(2,"restore_sigcontext32: upper_half & sar = %#lx\n", compat_regt);
102 DBG(2,"restore_sigcontext32: sar is %#lx\n", regs->sar);
103 DBG(2,"restore_sigcontext32: r28 is %ld\n", regs->gr[28]);
104
105 return err;
106}
107
108/*
109 * Set up the sigcontext structure for this process.
110 * This is not an easy task if the kernel is 64-bit, it will require
111 * that we examine the process personality to determine if we need to
112 * truncate for a 32-bit userspace.
113 */
114long
115setup_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf,
116 struct pt_regs *regs, int in_syscall)
117{
118 compat_int_t flags = 0;
119 long err = 0;
120 compat_uint_t compat_reg;
121 compat_uint_t compat_regb;
122 int regn;
123
124 if (on_sig_stack((unsigned long) sc))
125 flags |= PARISC_SC_FLAG_ONSTACK;
126
127 if (in_syscall) {
128
129 DBG(1,"setup_sigcontext32: in_syscall\n");
130
131 flags |= PARISC_SC_FLAG_IN_SYSCALL;
132 /* Truncate gr31 */
133 compat_reg = (compat_uint_t)(regs->gr[31]);
134 /* regs->iaoq is undefined in the syscall return path */
135 err |= __put_user(compat_reg, &sc->sc_iaoq[0]);
136 DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n",
137 &sc->sc_iaoq[0], compat_reg);
138
139 /* Store upper half */
140 compat_reg = (compat_uint_t)(regs->gr[31] >> 32);
141 err |= __put_user(compat_reg, &rf->rf_iaoq[0]);
142 DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg);
143
144
145 compat_reg = (compat_uint_t)(regs->gr[31]+4);
146 err |= __put_user(compat_reg, &sc->sc_iaoq[1]);
147 DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n",
148 &sc->sc_iaoq[1], compat_reg);
149 /* Store upper half */
150 compat_reg = (compat_uint_t)((regs->gr[31]+4) >> 32);
151 err |= __put_user(compat_reg, &rf->rf_iaoq[1]);
152 DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg);
153
154 /* Truncate sr3 */
155 compat_reg = (compat_uint_t)(regs->sr[3]);
156 err |= __put_user(compat_reg, &sc->sc_iasq[0]);
157 err |= __put_user(compat_reg, &sc->sc_iasq[1]);
158
159 /* Store upper half */
160 compat_reg = (compat_uint_t)(regs->sr[3] >> 32);
161 err |= __put_user(compat_reg, &rf->rf_iasq[0]);
162 err |= __put_user(compat_reg, &rf->rf_iasq[1]);
163
164 DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg);
165 DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg);
166 DBG(1,"setup_sigcontext32: iaoq %#lx / %#lx\n",
167 regs->gr[31], regs->gr[31]+4);
168
169 } else {
170
171 compat_reg = (compat_uint_t)(regs->iaoq[0]);
172 err |= __put_user(compat_reg, &sc->sc_iaoq[0]);
173 DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n",
174 &sc->sc_iaoq[0], compat_reg);
175 /* Store upper half */
176 compat_reg = (compat_uint_t)(regs->iaoq[0] >> 32);
177 err |= __put_user(compat_reg, &rf->rf_iaoq[0]);
178 DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg);
179
180 compat_reg = (compat_uint_t)(regs->iaoq[1]);
181 err |= __put_user(compat_reg, &sc->sc_iaoq[1]);
182 DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n",
183 &sc->sc_iaoq[1], compat_reg);
184 /* Store upper half */
185 compat_reg = (compat_uint_t)(regs->iaoq[1] >> 32);
186 err |= __put_user(compat_reg, &rf->rf_iaoq[1]);
187 DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg);
188
189
190 compat_reg = (compat_uint_t)(regs->iasq[0]);
191 err |= __put_user(compat_reg, &sc->sc_iasq[0]);
192 DBG(2,"setup_sigcontext32: sc->sc_iasq[0] = %p <= %#x\n",
193 &sc->sc_iasq[0], compat_reg);
194 /* Store upper half */
195 compat_reg = (compat_uint_t)(regs->iasq[0] >> 32);
196 err |= __put_user(compat_reg, &rf->rf_iasq[0]);
197 DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg);
198
199
200 compat_reg = (compat_uint_t)(regs->iasq[1]);
201 err |= __put_user(compat_reg, &sc->sc_iasq[1]);
202 DBG(2,"setup_sigcontext32: sc->sc_iasq[1] = %p <= %#x\n",
203 &sc->sc_iasq[1], compat_reg);
204 /* Store upper half */
205 compat_reg = (compat_uint_t)(regs->iasq[1] >> 32);
206 err |= __put_user(compat_reg, &rf->rf_iasq[1]);
207 DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg);
208
209 /* Print out the IAOQ for debugging */
210 DBG(1,"setup_sigcontext32: ia0q %#lx / %#lx\n",
211 regs->iaoq[0], regs->iaoq[1]);
212 }
213
214 err |= __put_user(flags, &sc->sc_flags);
215
216 DBG(1,"setup_sigcontext32: Truncating general registers.\n");
217
218 for(regn=0; regn < 32; regn++){
219 /* Truncate a general register */
220 compat_reg = (compat_uint_t)(regs->gr[regn]);
221 err |= __put_user(compat_reg, &sc->sc_gr[regn]);
222 /* Store upper half */
223 compat_regb = (compat_uint_t)(regs->gr[regn] >> 32);
224 err |= __put_user(compat_regb, &rf->rf_gr[regn]);
225
226 /* DEBUG: Write out the "upper / lower" register data */
227 DBG(2,"setup_sigcontext32: gr%02d = %#x / %#x\n", regn,
228 compat_regb, compat_reg);
229 }
230
231 /* Copy the floating point registers (same size)
232 XXX: BE WARNED FR's are 64-BIT! */
233 DBG(1,"setup_sigcontext32: Copying from regs to sc, "
234 "sc->sc_fr size = %#lx, regs->fr size = %#lx\n",
235 sizeof(regs->fr), sizeof(sc->sc_fr));
236 err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
237
238 compat_reg = (compat_uint_t)(regs->sar);
239 err |= __put_user(compat_reg, &sc->sc_sar);
240 DBG(2,"setup_sigcontext32: sar is %#x\n", compat_reg);
241 /* Store upper half */
242 compat_reg = (compat_uint_t)(regs->sar >> 32);
243 err |= __put_user(compat_reg, &rf->rf_sar);
244 DBG(2,"setup_sigcontext32: upper half sar = %#x\n", compat_reg);
245 DBG(1,"setup_sigcontext32: r28 is %ld\n", regs->gr[28]);
246
247 return err;
248}
1/* Signal support for 32-bit kernel builds
2 *
3 * Copyright (C) 2001 Matthew Wilcox <willy at parisc-linux.org>
4 * Copyright (C) 2006 Kyle McMartin <kyle at parisc-linux.org>
5 *
6 * Code was mostly borrowed from kernel/signal.c.
7 * See kernel/signal.c for additional Copyrights.
8 *
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24
25#include <linux/compat.h>
26#include <linux/module.h>
27#include <linux/unistd.h>
28#include <linux/init.h>
29#include <linux/sched.h>
30#include <linux/syscalls.h>
31#include <linux/types.h>
32#include <linux/errno.h>
33
34#include <asm/uaccess.h>
35
36#include "signal32.h"
37#include "sys32.h"
38
39#define DEBUG_COMPAT_SIG 0
40#define DEBUG_COMPAT_SIG_LEVEL 2
41
42#if DEBUG_COMPAT_SIG
43#define DBG(LEVEL, ...) \
44 ((DEBUG_COMPAT_SIG_LEVEL >= LEVEL) \
45 ? printk(__VA_ARGS__) : (void) 0)
46#else
47#define DBG(LEVEL, ...)
48#endif
49
50inline void
51sigset_32to64(sigset_t *s64, compat_sigset_t *s32)
52{
53 s64->sig[0] = s32->sig[0] | ((unsigned long)s32->sig[1] << 32);
54}
55
56inline void
57sigset_64to32(compat_sigset_t *s32, sigset_t *s64)
58{
59 s32->sig[0] = s64->sig[0] & 0xffffffffUL;
60 s32->sig[1] = (s64->sig[0] >> 32) & 0xffffffffUL;
61}
62
63static int
64put_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
65{
66 compat_sigset_t s;
67
68 if (sz != sizeof *set) panic("put_sigset32()");
69 sigset_64to32(&s, set);
70
71 return copy_to_user(up, &s, sizeof s);
72}
73
74static int
75get_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
76{
77 compat_sigset_t s;
78 int r;
79
80 if (sz != sizeof *set) panic("put_sigset32()");
81
82 if ((r = copy_from_user(&s, up, sz)) == 0) {
83 sigset_32to64(set, &s);
84 }
85
86 return r;
87}
88
89int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, compat_sigset_t __user *oset,
90 unsigned int sigsetsize)
91{
92 sigset_t old_set, new_set;
93 int ret;
94
95 if (set && get_sigset32(set, &new_set, sigsetsize))
96 return -EFAULT;
97
98 KERNEL_SYSCALL(ret, sys_rt_sigprocmask, how, set ? (sigset_t __user *)&new_set : NULL,
99 oset ? (sigset_t __user *)&old_set : NULL, sigsetsize);
100
101 if (!ret && oset && put_sigset32(oset, &old_set, sigsetsize))
102 return -EFAULT;
103
104 return ret;
105}
106
107
108int sys32_rt_sigpending(compat_sigset_t __user *uset, unsigned int sigsetsize)
109{
110 int ret;
111 sigset_t set;
112
113 KERNEL_SYSCALL(ret, sys_rt_sigpending, (sigset_t __user *)&set, sigsetsize);
114
115 if (!ret && put_sigset32(uset, &set, sigsetsize))
116 return -EFAULT;
117
118 return ret;
119}
120
121long
122sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, struct sigaction32 __user *oact,
123 size_t sigsetsize)
124{
125 struct k_sigaction32 new_sa32, old_sa32;
126 struct k_sigaction new_sa, old_sa;
127 int ret = -EINVAL;
128
129 if (act) {
130 if (copy_from_user(&new_sa32.sa, act, sizeof new_sa32.sa))
131 return -EFAULT;
132 new_sa.sa.sa_handler = (__sighandler_t)(unsigned long)new_sa32.sa.sa_handler;
133 new_sa.sa.sa_flags = new_sa32.sa.sa_flags;
134 sigset_32to64(&new_sa.sa.sa_mask, &new_sa32.sa.sa_mask);
135 }
136
137 ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
138
139 if (!ret && oact) {
140 sigset_64to32(&old_sa32.sa.sa_mask, &old_sa.sa.sa_mask);
141 old_sa32.sa.sa_flags = old_sa.sa.sa_flags;
142 old_sa32.sa.sa_handler = (__sighandler_t32)(unsigned long)old_sa.sa.sa_handler;
143 if (copy_to_user(oact, &old_sa32.sa, sizeof old_sa32.sa))
144 return -EFAULT;
145 }
146 return ret;
147}
148
149int
150do_sigaltstack32 (const compat_stack_t __user *uss32, compat_stack_t __user *uoss32, unsigned long sp)
151{
152 compat_stack_t ss32, oss32;
153 stack_t ss, oss;
154 stack_t *ssp = NULL, *ossp = NULL;
155 int ret;
156
157 if (uss32) {
158 if (copy_from_user(&ss32, uss32, sizeof ss32))
159 return -EFAULT;
160
161 ss.ss_sp = (void __user *)(unsigned long)ss32.ss_sp;
162 ss.ss_flags = ss32.ss_flags;
163 ss.ss_size = ss32.ss_size;
164
165 ssp = &ss;
166 }
167
168 if (uoss32)
169 ossp = &oss;
170
171 KERNEL_SYSCALL(ret, do_sigaltstack, (const stack_t __user *)ssp, (stack_t __user *)ossp, sp);
172
173 if (!ret && uoss32) {
174 oss32.ss_sp = (unsigned int)(unsigned long)oss.ss_sp;
175 oss32.ss_flags = oss.ss_flags;
176 oss32.ss_size = oss.ss_size;
177 if (copy_to_user(uoss32, &oss32, sizeof *uoss32))
178 return -EFAULT;
179 }
180
181 return ret;
182}
183
184long
185restore_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf,
186 struct pt_regs *regs)
187{
188 long err = 0;
189 compat_uint_t compat_reg;
190 compat_uint_t compat_regt;
191 int regn;
192
193 /* When loading 32-bit values into 64-bit registers make
194 sure to clear the upper 32-bits */
195 DBG(2,"restore_sigcontext32: PER_LINUX32 process\n");
196 DBG(2,"restore_sigcontext32: sc = 0x%p, rf = 0x%p, regs = 0x%p\n", sc, rf, regs);
197 DBG(2,"restore_sigcontext32: compat_sigcontext is %#lx bytes\n", sizeof(*sc));
198 for(regn=0; regn < 32; regn++){
199 err |= __get_user(compat_reg,&sc->sc_gr[regn]);
200 regs->gr[regn] = compat_reg;
201 /* Load upper half */
202 err |= __get_user(compat_regt,&rf->rf_gr[regn]);
203 regs->gr[regn] = ((u64)compat_regt << 32) | (u64)compat_reg;
204 DBG(3,"restore_sigcontext32: gr%02d = %#lx (%#x / %#x)\n",
205 regn, regs->gr[regn], compat_regt, compat_reg);
206 }
207 DBG(2,"restore_sigcontext32: sc->sc_fr = 0x%p (%#lx)\n",sc->sc_fr, sizeof(sc->sc_fr));
208 /* XXX: BE WARNED FR's are 64-BIT! */
209 err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr));
210
211 /* Better safe than sorry, pass __get_user two things of
212 the same size and let gcc do the upward conversion to
213 64-bits */
214 err |= __get_user(compat_reg, &sc->sc_iaoq[0]);
215 /* Load upper half */
216 err |= __get_user(compat_regt, &rf->rf_iaoq[0]);
217 regs->iaoq[0] = ((u64)compat_regt << 32) | (u64)compat_reg;
218 DBG(2,"restore_sigcontext32: upper half of iaoq[0] = %#lx\n", compat_regt);
219 DBG(2,"restore_sigcontext32: sc->sc_iaoq[0] = %p => %#x\n",
220 &sc->sc_iaoq[0], compat_reg);
221
222 err |= __get_user(compat_reg, &sc->sc_iaoq[1]);
223 /* Load upper half */
224 err |= __get_user(compat_regt, &rf->rf_iaoq[1]);
225 regs->iaoq[1] = ((u64)compat_regt << 32) | (u64)compat_reg;
226 DBG(2,"restore_sigcontext32: upper half of iaoq[1] = %#lx\n", compat_regt);
227 DBG(2,"restore_sigcontext32: sc->sc_iaoq[1] = %p => %#x\n",
228 &sc->sc_iaoq[1],compat_reg);
229 DBG(2,"restore_sigcontext32: iaoq is %#lx / %#lx\n",
230 regs->iaoq[0],regs->iaoq[1]);
231
232 err |= __get_user(compat_reg, &sc->sc_iasq[0]);
233 /* Load the upper half for iasq */
234 err |= __get_user(compat_regt, &rf->rf_iasq[0]);
235 regs->iasq[0] = ((u64)compat_regt << 32) | (u64)compat_reg;
236 DBG(2,"restore_sigcontext32: upper half of iasq[0] = %#lx\n", compat_regt);
237
238 err |= __get_user(compat_reg, &sc->sc_iasq[1]);
239 /* Load the upper half for iasq */
240 err |= __get_user(compat_regt, &rf->rf_iasq[1]);
241 regs->iasq[1] = ((u64)compat_regt << 32) | (u64)compat_reg;
242 DBG(2,"restore_sigcontext32: upper half of iasq[1] = %#lx\n", compat_regt);
243 DBG(2,"restore_sigcontext32: iasq is %#lx / %#lx\n",
244 regs->iasq[0],regs->iasq[1]);
245
246 err |= __get_user(compat_reg, &sc->sc_sar);
247 /* Load the upper half for sar */
248 err |= __get_user(compat_regt, &rf->rf_sar);
249 regs->sar = ((u64)compat_regt << 32) | (u64)compat_reg;
250 DBG(2,"restore_sigcontext32: upper_half & sar = %#lx\n", compat_regt);
251 DBG(2,"restore_sigcontext32: sar is %#lx\n", regs->sar);
252 DBG(2,"restore_sigcontext32: r28 is %ld\n", regs->gr[28]);
253
254 return err;
255}
256
257/*
258 * Set up the sigcontext structure for this process.
259 * This is not an easy task if the kernel is 64-bit, it will require
260 * that we examine the process personality to determine if we need to
261 * truncate for a 32-bit userspace.
262 */
263long
264setup_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf,
265 struct pt_regs *regs, int in_syscall)
266{
267 compat_int_t flags = 0;
268 long err = 0;
269 compat_uint_t compat_reg;
270 compat_uint_t compat_regb;
271 int regn;
272
273 if (on_sig_stack((unsigned long) sc))
274 flags |= PARISC_SC_FLAG_ONSTACK;
275
276 if (in_syscall) {
277
278 DBG(1,"setup_sigcontext32: in_syscall\n");
279
280 flags |= PARISC_SC_FLAG_IN_SYSCALL;
281 /* Truncate gr31 */
282 compat_reg = (compat_uint_t)(regs->gr[31]);
283 /* regs->iaoq is undefined in the syscall return path */
284 err |= __put_user(compat_reg, &sc->sc_iaoq[0]);
285 DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n",
286 &sc->sc_iaoq[0], compat_reg);
287
288 /* Store upper half */
289 compat_reg = (compat_uint_t)(regs->gr[31] >> 32);
290 err |= __put_user(compat_reg, &rf->rf_iaoq[0]);
291 DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg);
292
293
294 compat_reg = (compat_uint_t)(regs->gr[31]+4);
295 err |= __put_user(compat_reg, &sc->sc_iaoq[1]);
296 DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n",
297 &sc->sc_iaoq[1], compat_reg);
298 /* Store upper half */
299 compat_reg = (compat_uint_t)((regs->gr[31]+4) >> 32);
300 err |= __put_user(compat_reg, &rf->rf_iaoq[1]);
301 DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg);
302
303 /* Truncate sr3 */
304 compat_reg = (compat_uint_t)(regs->sr[3]);
305 err |= __put_user(compat_reg, &sc->sc_iasq[0]);
306 err |= __put_user(compat_reg, &sc->sc_iasq[1]);
307
308 /* Store upper half */
309 compat_reg = (compat_uint_t)(regs->sr[3] >> 32);
310 err |= __put_user(compat_reg, &rf->rf_iasq[0]);
311 err |= __put_user(compat_reg, &rf->rf_iasq[1]);
312
313 DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg);
314 DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg);
315 DBG(1,"setup_sigcontext32: iaoq %#lx / %#lx\n",
316 regs->gr[31], regs->gr[31]+4);
317
318 } else {
319
320 compat_reg = (compat_uint_t)(regs->iaoq[0]);
321 err |= __put_user(compat_reg, &sc->sc_iaoq[0]);
322 DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n",
323 &sc->sc_iaoq[0], compat_reg);
324 /* Store upper half */
325 compat_reg = (compat_uint_t)(regs->iaoq[0] >> 32);
326 err |= __put_user(compat_reg, &rf->rf_iaoq[0]);
327 DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg);
328
329 compat_reg = (compat_uint_t)(regs->iaoq[1]);
330 err |= __put_user(compat_reg, &sc->sc_iaoq[1]);
331 DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n",
332 &sc->sc_iaoq[1], compat_reg);
333 /* Store upper half */
334 compat_reg = (compat_uint_t)(regs->iaoq[1] >> 32);
335 err |= __put_user(compat_reg, &rf->rf_iaoq[1]);
336 DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg);
337
338
339 compat_reg = (compat_uint_t)(regs->iasq[0]);
340 err |= __put_user(compat_reg, &sc->sc_iasq[0]);
341 DBG(2,"setup_sigcontext32: sc->sc_iasq[0] = %p <= %#x\n",
342 &sc->sc_iasq[0], compat_reg);
343 /* Store upper half */
344 compat_reg = (compat_uint_t)(regs->iasq[0] >> 32);
345 err |= __put_user(compat_reg, &rf->rf_iasq[0]);
346 DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg);
347
348
349 compat_reg = (compat_uint_t)(regs->iasq[1]);
350 err |= __put_user(compat_reg, &sc->sc_iasq[1]);
351 DBG(2,"setup_sigcontext32: sc->sc_iasq[1] = %p <= %#x\n",
352 &sc->sc_iasq[1], compat_reg);
353 /* Store upper half */
354 compat_reg = (compat_uint_t)(regs->iasq[1] >> 32);
355 err |= __put_user(compat_reg, &rf->rf_iasq[1]);
356 DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg);
357
358 /* Print out the IAOQ for debugging */
359 DBG(1,"setup_sigcontext32: ia0q %#lx / %#lx\n",
360 regs->iaoq[0], regs->iaoq[1]);
361 }
362
363 err |= __put_user(flags, &sc->sc_flags);
364
365 DBG(1,"setup_sigcontext32: Truncating general registers.\n");
366
367 for(regn=0; regn < 32; regn++){
368 /* Truncate a general register */
369 compat_reg = (compat_uint_t)(regs->gr[regn]);
370 err |= __put_user(compat_reg, &sc->sc_gr[regn]);
371 /* Store upper half */
372 compat_regb = (compat_uint_t)(regs->gr[regn] >> 32);
373 err |= __put_user(compat_regb, &rf->rf_gr[regn]);
374
375 /* DEBUG: Write out the "upper / lower" register data */
376 DBG(2,"setup_sigcontext32: gr%02d = %#x / %#x\n", regn,
377 compat_regb, compat_reg);
378 }
379
380 /* Copy the floating point registers (same size)
381 XXX: BE WARNED FR's are 64-BIT! */
382 DBG(1,"setup_sigcontext32: Copying from regs to sc, "
383 "sc->sc_fr size = %#lx, regs->fr size = %#lx\n",
384 sizeof(regs->fr), sizeof(sc->sc_fr));
385 err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
386
387 compat_reg = (compat_uint_t)(regs->sar);
388 err |= __put_user(compat_reg, &sc->sc_sar);
389 DBG(2,"setup_sigcontext32: sar is %#x\n", compat_reg);
390 /* Store upper half */
391 compat_reg = (compat_uint_t)(regs->sar >> 32);
392 err |= __put_user(compat_reg, &rf->rf_sar);
393 DBG(2,"setup_sigcontext32: upper half sar = %#x\n", compat_reg);
394 DBG(1,"setup_sigcontext32: r28 is %ld\n", regs->gr[28]);
395
396 return err;
397}
398
399int
400copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from)
401{
402 compat_uptr_t addr;
403 int err;
404
405 if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
406 return -EFAULT;
407
408 err = __get_user(to->si_signo, &from->si_signo);
409 err |= __get_user(to->si_errno, &from->si_errno);
410 err |= __get_user(to->si_code, &from->si_code);
411
412 if (to->si_code < 0)
413 err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
414 else {
415 switch (to->si_code >> 16) {
416 case __SI_CHLD >> 16:
417 err |= __get_user(to->si_utime, &from->si_utime);
418 err |= __get_user(to->si_stime, &from->si_stime);
419 err |= __get_user(to->si_status, &from->si_status);
420 default:
421 err |= __get_user(to->si_pid, &from->si_pid);
422 err |= __get_user(to->si_uid, &from->si_uid);
423 break;
424 case __SI_FAULT >> 16:
425 err |= __get_user(addr, &from->si_addr);
426 to->si_addr = compat_ptr(addr);
427 break;
428 case __SI_POLL >> 16:
429 err |= __get_user(to->si_band, &from->si_band);
430 err |= __get_user(to->si_fd, &from->si_fd);
431 break;
432 case __SI_RT >> 16: /* This is not generated by the kernel as of now. */
433 case __SI_MESGQ >> 16:
434 err |= __get_user(to->si_pid, &from->si_pid);
435 err |= __get_user(to->si_uid, &from->si_uid);
436 err |= __get_user(to->si_int, &from->si_int);
437 break;
438 }
439 }
440 return err;
441}
442
443int
444copy_siginfo_to_user32 (compat_siginfo_t __user *to, siginfo_t *from)
445{
446 compat_uptr_t addr;
447 compat_int_t val;
448 int err;
449
450 if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
451 return -EFAULT;
452
453 /* If you change siginfo_t structure, please be sure
454 this code is fixed accordingly.
455 It should never copy any pad contained in the structure
456 to avoid security leaks, but must copy the generic
457 3 ints plus the relevant union member.
458 This routine must convert siginfo from 64bit to 32bit as well
459 at the same time. */
460 err = __put_user(from->si_signo, &to->si_signo);
461 err |= __put_user(from->si_errno, &to->si_errno);
462 err |= __put_user((short)from->si_code, &to->si_code);
463 if (from->si_code < 0)
464 err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
465 else {
466 switch (from->si_code >> 16) {
467 case __SI_CHLD >> 16:
468 err |= __put_user(from->si_utime, &to->si_utime);
469 err |= __put_user(from->si_stime, &to->si_stime);
470 err |= __put_user(from->si_status, &to->si_status);
471 default:
472 err |= __put_user(from->si_pid, &to->si_pid);
473 err |= __put_user(from->si_uid, &to->si_uid);
474 break;
475 case __SI_FAULT >> 16:
476 addr = ptr_to_compat(from->si_addr);
477 err |= __put_user(addr, &to->si_addr);
478 break;
479 case __SI_POLL >> 16:
480 err |= __put_user(from->si_band, &to->si_band);
481 err |= __put_user(from->si_fd, &to->si_fd);
482 break;
483 case __SI_TIMER >> 16:
484 err |= __put_user(from->si_tid, &to->si_tid);
485 err |= __put_user(from->si_overrun, &to->si_overrun);
486 val = (compat_int_t)from->si_int;
487 err |= __put_user(val, &to->si_int);
488 break;
489 case __SI_RT >> 16: /* Not generated by the kernel as of now. */
490 case __SI_MESGQ >> 16:
491 err |= __put_user(from->si_uid, &to->si_uid);
492 err |= __put_user(from->si_pid, &to->si_pid);
493 val = (compat_int_t)from->si_int;
494 err |= __put_user(val, &to->si_int);
495 break;
496 }
497 }
498 return err;
499}
500
501asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig,
502 struct compat_siginfo __user *uinfo)
503{
504 siginfo_t info;
505
506 if (copy_siginfo_from_user32(&info, uinfo))
507 return -EFAULT;
508
509 /* Not even root can pretend to send signals from the kernel.
510 Nor can they impersonate a kill(), which adds source info. */
511 if (info.si_code >= 0)
512 return -EPERM;
513 info.si_signo = sig;
514
515 /* POSIX.1b doesn't mention process groups. */
516 return kill_proc_info(sig, &info, pid);
517}
518