PageRenderTime 45ms CodeModel.GetById 12ms app.highlight 28ms RepoModel.GetById 1ms app.codeStats 0ms

/arch/parisc/kernel/signal32.c

https://github.com/aicjofs/android_kernel_lge_v500_20d
C | 520 lines | 369 code | 83 blank | 68 comment | 39 complexity | 2aea9f464f8731ef7616f3fbf3dbb203 MD5 | raw file
  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
 50#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
 51
 52inline void
 53sigset_32to64(sigset_t *s64, compat_sigset_t *s32)
 54{
 55	s64->sig[0] = s32->sig[0] | ((unsigned long)s32->sig[1] << 32);
 56}
 57
 58inline void
 59sigset_64to32(compat_sigset_t *s32, sigset_t *s64)
 60{
 61	s32->sig[0] = s64->sig[0] & 0xffffffffUL;
 62	s32->sig[1] = (s64->sig[0] >> 32) & 0xffffffffUL;
 63}
 64
 65static int
 66put_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
 67{
 68	compat_sigset_t s;
 69
 70	if (sz != sizeof *set) panic("put_sigset32()");
 71	sigset_64to32(&s, set);
 72
 73	return copy_to_user(up, &s, sizeof s);
 74}
 75
 76static int
 77get_sigset32(compat_sigset_t __user *up, sigset_t *set, size_t sz)
 78{
 79	compat_sigset_t s;
 80	int r;
 81
 82	if (sz != sizeof *set) panic("put_sigset32()");
 83
 84	if ((r = copy_from_user(&s, up, sz)) == 0) {
 85		sigset_32to64(set, &s);
 86	}
 87
 88	return r;
 89}
 90
 91int sys32_rt_sigprocmask(int how, compat_sigset_t __user *set, compat_sigset_t __user *oset,
 92				    unsigned int sigsetsize)
 93{
 94	sigset_t old_set, new_set;
 95	int ret;
 96
 97	if (set && get_sigset32(set, &new_set, sigsetsize))
 98		return -EFAULT;
 99	
100	KERNEL_SYSCALL(ret, sys_rt_sigprocmask, how, set ? (sigset_t __user *)&new_set : NULL,
101				 oset ? (sigset_t __user *)&old_set : NULL, sigsetsize);
102
103	if (!ret && oset && put_sigset32(oset, &old_set, sigsetsize))
104		return -EFAULT;
105
106	return ret;
107}
108
109
110int sys32_rt_sigpending(compat_sigset_t __user *uset, unsigned int sigsetsize)
111{
112	int ret;
113	sigset_t set;
114
115	KERNEL_SYSCALL(ret, sys_rt_sigpending, (sigset_t __user *)&set, sigsetsize);
116
117	if (!ret && put_sigset32(uset, &set, sigsetsize))
118		return -EFAULT;
119
120	return ret;
121}
122
123long
124sys32_rt_sigaction(int sig, const struct sigaction32 __user *act, struct sigaction32 __user *oact,
125                 size_t sigsetsize)
126{
127	struct k_sigaction32 new_sa32, old_sa32;
128	struct k_sigaction new_sa, old_sa;
129	int ret = -EINVAL;
130
131	if (act) {
132		if (copy_from_user(&new_sa32.sa, act, sizeof new_sa32.sa))
133			return -EFAULT;
134		new_sa.sa.sa_handler = (__sighandler_t)(unsigned long)new_sa32.sa.sa_handler;
135		new_sa.sa.sa_flags = new_sa32.sa.sa_flags;
136		sigset_32to64(&new_sa.sa.sa_mask, &new_sa32.sa.sa_mask);
137	}
138
139	ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
140
141	if (!ret && oact) {
142		sigset_64to32(&old_sa32.sa.sa_mask, &old_sa.sa.sa_mask);
143		old_sa32.sa.sa_flags = old_sa.sa.sa_flags;
144		old_sa32.sa.sa_handler = (__sighandler_t32)(unsigned long)old_sa.sa.sa_handler;
145		if (copy_to_user(oact, &old_sa32.sa, sizeof old_sa32.sa))
146			return -EFAULT;
147	}
148	return ret;
149}
150
151int 
152do_sigaltstack32 (const compat_stack_t __user *uss32, compat_stack_t __user *uoss32, unsigned long sp)
153{
154	compat_stack_t ss32, oss32;
155	stack_t ss, oss;
156	stack_t *ssp = NULL, *ossp = NULL;
157	int ret;
158
159	if (uss32) {
160		if (copy_from_user(&ss32, uss32, sizeof ss32))
161			return -EFAULT;
162
163		ss.ss_sp = (void __user *)(unsigned long)ss32.ss_sp;
164		ss.ss_flags = ss32.ss_flags;
165		ss.ss_size = ss32.ss_size;
166
167		ssp = &ss;
168	}
169
170	if (uoss32)
171		ossp = &oss;
172
173	KERNEL_SYSCALL(ret, do_sigaltstack, (const stack_t __user *)ssp, (stack_t __user *)ossp, sp);
174
175	if (!ret && uoss32) {
176		oss32.ss_sp = (unsigned int)(unsigned long)oss.ss_sp;
177		oss32.ss_flags = oss.ss_flags;
178		oss32.ss_size = oss.ss_size;
179		if (copy_to_user(uoss32, &oss32, sizeof *uoss32))
180			return -EFAULT;
181	}
182
183	return ret;
184}
185
186long
187restore_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf,
188		struct pt_regs *regs)
189{
190	long err = 0;
191	compat_uint_t compat_reg;
192	compat_uint_t compat_regt;
193	int regn;
194	
195	/* When loading 32-bit values into 64-bit registers make
196	   sure to clear the upper 32-bits */
197	DBG(2,"restore_sigcontext32: PER_LINUX32 process\n");
198	DBG(2,"restore_sigcontext32: sc = 0x%p, rf = 0x%p, regs = 0x%p\n", sc, rf, regs);
199	DBG(2,"restore_sigcontext32: compat_sigcontext is %#lx bytes\n", sizeof(*sc));
200	for(regn=0; regn < 32; regn++){
201		err |= __get_user(compat_reg,&sc->sc_gr[regn]);
202		regs->gr[regn] = compat_reg;
203		/* Load upper half */
204		err |= __get_user(compat_regt,&rf->rf_gr[regn]);
205		regs->gr[regn] = ((u64)compat_regt << 32) | (u64)compat_reg;
206		DBG(3,"restore_sigcontext32: gr%02d = %#lx (%#x / %#x)\n", 
207				regn, regs->gr[regn], compat_regt, compat_reg);
208	}
209	DBG(2,"restore_sigcontext32: sc->sc_fr = 0x%p (%#lx)\n",sc->sc_fr, sizeof(sc->sc_fr));
210	/* XXX: BE WARNED FR's are 64-BIT! */
211	err |= __copy_from_user(regs->fr, sc->sc_fr, sizeof(regs->fr));
212		
213	/* Better safe than sorry, pass __get_user two things of
214	   the same size and let gcc do the upward conversion to 
215	   64-bits */		
216	err |= __get_user(compat_reg, &sc->sc_iaoq[0]);
217	/* Load upper half */
218	err |= __get_user(compat_regt, &rf->rf_iaoq[0]);
219	regs->iaoq[0] = ((u64)compat_regt << 32) | (u64)compat_reg;
220	DBG(2,"restore_sigcontext32: upper half of iaoq[0] = %#lx\n", compat_regt);
221	DBG(2,"restore_sigcontext32: sc->sc_iaoq[0] = %p => %#x\n", 
222			&sc->sc_iaoq[0], compat_reg);
223
224	err |= __get_user(compat_reg, &sc->sc_iaoq[1]);
225	/* Load upper half */
226	err |= __get_user(compat_regt, &rf->rf_iaoq[1]);
227	regs->iaoq[1] = ((u64)compat_regt << 32) | (u64)compat_reg;
228	DBG(2,"restore_sigcontext32: upper half of iaoq[1] = %#lx\n", compat_regt);
229	DBG(2,"restore_sigcontext32: sc->sc_iaoq[1] = %p => %#x\n", 
230			&sc->sc_iaoq[1],compat_reg);	
231	DBG(2,"restore_sigcontext32: iaoq is %#lx / %#lx\n", 
232			regs->iaoq[0],regs->iaoq[1]);		
233		
234	err |= __get_user(compat_reg, &sc->sc_iasq[0]);
235	/* Load the upper half for iasq */
236	err |= __get_user(compat_regt, &rf->rf_iasq[0]);
237	regs->iasq[0] = ((u64)compat_regt << 32) | (u64)compat_reg;
238	DBG(2,"restore_sigcontext32: upper half of iasq[0] = %#lx\n", compat_regt);
239	
240	err |= __get_user(compat_reg, &sc->sc_iasq[1]);
241	/* Load the upper half for iasq */
242	err |= __get_user(compat_regt, &rf->rf_iasq[1]);
243	regs->iasq[1] = ((u64)compat_regt << 32) | (u64)compat_reg;
244	DBG(2,"restore_sigcontext32: upper half of iasq[1] = %#lx\n", compat_regt);
245	DBG(2,"restore_sigcontext32: iasq is %#lx / %#lx\n", 
246		regs->iasq[0],regs->iasq[1]);		
247
248	err |= __get_user(compat_reg, &sc->sc_sar);
249	/* Load the upper half for sar */
250	err |= __get_user(compat_regt, &rf->rf_sar);
251	regs->sar = ((u64)compat_regt << 32) | (u64)compat_reg;	
252	DBG(2,"restore_sigcontext32: upper_half & sar = %#lx\n", compat_regt);	
253	DBG(2,"restore_sigcontext32: sar is %#lx\n", regs->sar);		
254	DBG(2,"restore_sigcontext32: r28 is %ld\n", regs->gr[28]);
255	
256	return err;
257}
258
259/*
260 * Set up the sigcontext structure for this process.
261 * This is not an easy task if the kernel is 64-bit, it will require
262 * that we examine the process personality to determine if we need to
263 * truncate for a 32-bit userspace.
264 */
265long
266setup_sigcontext32(struct compat_sigcontext __user *sc, struct compat_regfile __user * rf, 
267		struct pt_regs *regs, int in_syscall)		 
268{
269	compat_int_t flags = 0;
270	long err = 0;
271	compat_uint_t compat_reg;
272	compat_uint_t compat_regb;
273	int regn;
274	
275	if (on_sig_stack((unsigned long) sc))
276		flags |= PARISC_SC_FLAG_ONSTACK;
277	
278	if (in_syscall) {
279		
280		DBG(1,"setup_sigcontext32: in_syscall\n");
281		
282		flags |= PARISC_SC_FLAG_IN_SYSCALL;
283		/* Truncate gr31 */
284		compat_reg = (compat_uint_t)(regs->gr[31]);
285		/* regs->iaoq is undefined in the syscall return path */
286		err |= __put_user(compat_reg, &sc->sc_iaoq[0]);
287		DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n",
288				&sc->sc_iaoq[0], compat_reg);
289		
290		/* Store upper half */
291		compat_reg = (compat_uint_t)(regs->gr[31] >> 32);
292		err |= __put_user(compat_reg, &rf->rf_iaoq[0]);
293		DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg);
294		
295		
296		compat_reg = (compat_uint_t)(regs->gr[31]+4);
297		err |= __put_user(compat_reg, &sc->sc_iaoq[1]);
298		DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n",
299				&sc->sc_iaoq[1], compat_reg);
300		/* Store upper half */
301		compat_reg = (compat_uint_t)((regs->gr[31]+4) >> 32);
302		err |= __put_user(compat_reg, &rf->rf_iaoq[1]);
303		DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg);
304		
305		/* Truncate sr3 */
306		compat_reg = (compat_uint_t)(regs->sr[3]);
307		err |= __put_user(compat_reg, &sc->sc_iasq[0]);
308		err |= __put_user(compat_reg, &sc->sc_iasq[1]);		
309		
310		/* Store upper half */
311		compat_reg = (compat_uint_t)(regs->sr[3] >> 32);
312		err |= __put_user(compat_reg, &rf->rf_iasq[0]);
313		err |= __put_user(compat_reg, &rf->rf_iasq[1]);		
314		
315		DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg);
316		DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg);		
317		DBG(1,"setup_sigcontext32: iaoq %#lx / %#lx\n",				
318			regs->gr[31], regs->gr[31]+4);
319		
320	} else {
321		
322		compat_reg = (compat_uint_t)(regs->iaoq[0]);
323		err |= __put_user(compat_reg, &sc->sc_iaoq[0]);
324		DBG(2,"setup_sigcontext32: sc->sc_iaoq[0] = %p <= %#x\n",
325				&sc->sc_iaoq[0], compat_reg);
326		/* Store upper half */
327		compat_reg = (compat_uint_t)(regs->iaoq[0] >> 32);
328		err |= __put_user(compat_reg, &rf->rf_iaoq[0]);	
329		DBG(2,"setup_sigcontext32: upper half iaoq[0] = %#x\n", compat_reg);
330		
331		compat_reg = (compat_uint_t)(regs->iaoq[1]);
332		err |= __put_user(compat_reg, &sc->sc_iaoq[1]);
333		DBG(2,"setup_sigcontext32: sc->sc_iaoq[1] = %p <= %#x\n",
334				&sc->sc_iaoq[1], compat_reg);
335		/* Store upper half */
336		compat_reg = (compat_uint_t)(regs->iaoq[1] >> 32);
337		err |= __put_user(compat_reg, &rf->rf_iaoq[1]);
338		DBG(2,"setup_sigcontext32: upper half iaoq[1] = %#x\n", compat_reg);
339		
340		
341		compat_reg = (compat_uint_t)(regs->iasq[0]);
342		err |= __put_user(compat_reg, &sc->sc_iasq[0]);
343		DBG(2,"setup_sigcontext32: sc->sc_iasq[0] = %p <= %#x\n",
344				&sc->sc_iasq[0], compat_reg);
345		/* Store upper half */
346		compat_reg = (compat_uint_t)(regs->iasq[0] >> 32);
347		err |= __put_user(compat_reg, &rf->rf_iasq[0]);
348		DBG(2,"setup_sigcontext32: upper half iasq[0] = %#x\n", compat_reg);
349		
350		
351		compat_reg = (compat_uint_t)(regs->iasq[1]);
352		err |= __put_user(compat_reg, &sc->sc_iasq[1]);
353		DBG(2,"setup_sigcontext32: sc->sc_iasq[1] = %p <= %#x\n",
354				&sc->sc_iasq[1], compat_reg);
355		/* Store upper half */
356		compat_reg = (compat_uint_t)(regs->iasq[1] >> 32);
357		err |= __put_user(compat_reg, &rf->rf_iasq[1]);
358		DBG(2,"setup_sigcontext32: upper half iasq[1] = %#x\n", compat_reg);
359
360		/* Print out the IAOQ for debugging */		
361		DBG(1,"setup_sigcontext32: ia0q %#lx / %#lx\n", 
362			regs->iaoq[0], regs->iaoq[1]);
363	}
364
365	err |= __put_user(flags, &sc->sc_flags);
366	
367	DBG(1,"setup_sigcontext32: Truncating general registers.\n");
368	
369	for(regn=0; regn < 32; regn++){
370		/* Truncate a general register */
371		compat_reg = (compat_uint_t)(regs->gr[regn]);
372		err |= __put_user(compat_reg, &sc->sc_gr[regn]);
373		/* Store upper half */
374		compat_regb = (compat_uint_t)(regs->gr[regn] >> 32);
375		err |= __put_user(compat_regb, &rf->rf_gr[regn]);
376
377		/* DEBUG: Write out the "upper / lower" register data */
378		DBG(2,"setup_sigcontext32: gr%02d = %#x / %#x\n", regn, 
379				compat_regb, compat_reg);
380	}
381	
382	/* Copy the floating point registers (same size)
383	   XXX: BE WARNED FR's are 64-BIT! */	
384	DBG(1,"setup_sigcontext32: Copying from regs to sc, "
385	      "sc->sc_fr size = %#lx, regs->fr size = %#lx\n",
386		sizeof(regs->fr), sizeof(sc->sc_fr));
387	err |= __copy_to_user(sc->sc_fr, regs->fr, sizeof(regs->fr));
388
389	compat_reg = (compat_uint_t)(regs->sar);
390	err |= __put_user(compat_reg, &sc->sc_sar);
391	DBG(2,"setup_sigcontext32: sar is %#x\n", compat_reg);
392	/* Store upper half */
393	compat_reg = (compat_uint_t)(regs->sar >> 32);
394	err |= __put_user(compat_reg, &rf->rf_sar);	
395	DBG(2,"setup_sigcontext32: upper half sar = %#x\n", compat_reg);
396	DBG(1,"setup_sigcontext32: r28 is %ld\n", regs->gr[28]);
397
398	return err;
399}
400
401int
402copy_siginfo_from_user32 (siginfo_t *to, compat_siginfo_t __user *from)
403{
404	compat_uptr_t addr;
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(addr, &from->si_addr);
428			to->si_addr = compat_ptr(addr);
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	compat_uptr_t addr;
449	compat_int_t val;
450	int err;
451
452	if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
453		return -EFAULT;
454
455	/* If you change siginfo_t structure, please be sure
456	   this code is fixed accordingly.
457	   It should never copy any pad contained in the structure
458	   to avoid security leaks, but must copy the generic
459	   3 ints plus the relevant union member.
460	   This routine must convert siginfo from 64bit to 32bit as well
461	   at the same time.  */
462	err = __put_user(from->si_signo, &to->si_signo);
463	err |= __put_user(from->si_errno, &to->si_errno);
464	err |= __put_user((short)from->si_code, &to->si_code);
465	if (from->si_code < 0)
466		err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
467	else {
468		switch (from->si_code >> 16) {
469		case __SI_CHLD >> 16:
470			err |= __put_user(from->si_utime, &to->si_utime);
471			err |= __put_user(from->si_stime, &to->si_stime);
472			err |= __put_user(from->si_status, &to->si_status);
473		default:
474			err |= __put_user(from->si_pid, &to->si_pid);
475			err |= __put_user(from->si_uid, &to->si_uid);
476			break;
477		case __SI_FAULT >> 16:
478			addr = ptr_to_compat(from->si_addr);
479			err |= __put_user(addr, &to->si_addr);
480			break;
481		case __SI_POLL >> 16:
482			err |= __put_user(from->si_band, &to->si_band);
483			err |= __put_user(from->si_fd, &to->si_fd);
484			break;
485		case __SI_TIMER >> 16:
486			err |= __put_user(from->si_tid, &to->si_tid);
487			err |= __put_user(from->si_overrun, &to->si_overrun);
488			val = (compat_int_t)from->si_int;
489			err |= __put_user(val, &to->si_int);
490			break;
491		case __SI_RT >> 16:	/* Not generated by the kernel as of now.  */
492		case __SI_MESGQ >> 16:
493			err |= __put_user(from->si_uid, &to->si_uid);
494			err |= __put_user(from->si_pid, &to->si_pid);
495			val = (compat_int_t)from->si_int;
496			err |= __put_user(val, &to->si_int);
497			break;
498		}
499	}
500	return err;
501}
502
503asmlinkage long compat_sys_rt_sigqueueinfo(int pid, int sig,
504	struct compat_siginfo __user *uinfo)
505{
506	siginfo_t info;
507
508	if (copy_siginfo_from_user32(&info, uinfo))
509		return -EFAULT;
510
511	/* Not even root can pretend to send signals from the kernel.
512	   Nor can they impersonate a kill(), which adds source info.  */
513	if (info.si_code >= 0)
514		return -EPERM;
515	info.si_signo = sig;
516
517	/* POSIX.1b doesn't mention process groups.  */
518	return kill_proc_info(sig, &info, pid);
519}
520