• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/arch/tile/kernel/
1/*
2 * Copyright 2010 Tilera Corporation. All Rights Reserved.
3 *
4 *   This program is free software; you can redistribute it and/or
5 *   modify it under the terms of the GNU General Public License
6 *   as published by the Free Software Foundation, version 2.
7 *
8 *   This program is distributed in the hope that it will be useful, but
9 *   WITHOUT ANY WARRANTY; without even the implied warranty of
10 *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11 *   NON INFRINGEMENT.  See the GNU General Public License for
12 *   more details.
13 */
14
15#include <linux/sched.h>
16#include <linux/mm.h>
17#include <linux/smp.h>
18#include <linux/smp_lock.h>
19#include <linux/kernel.h>
20#include <linux/signal.h>
21#include <linux/errno.h>
22#include <linux/wait.h>
23#include <linux/unistd.h>
24#include <linux/stddef.h>
25#include <linux/personality.h>
26#include <linux/suspend.h>
27#include <linux/ptrace.h>
28#include <linux/elf.h>
29#include <linux/compat.h>
30#include <linux/syscalls.h>
31#include <linux/uaccess.h>
32#include <asm/processor.h>
33#include <asm/ucontext.h>
34#include <asm/sigframe.h>
35#include <asm/syscalls.h>
36#include <arch/interrupts.h>
37
38struct compat_sigaction {
39	compat_uptr_t sa_handler;
40	compat_ulong_t sa_flags;
41	compat_uptr_t sa_restorer;
42	sigset_t sa_mask __packed;
43};
44
45struct compat_sigaltstack {
46	compat_uptr_t ss_sp;
47	int ss_flags;
48	compat_size_t ss_size;
49};
50
51struct compat_ucontext {
52	compat_ulong_t	  uc_flags;
53	compat_uptr_t     uc_link;
54	struct compat_sigaltstack	  uc_stack;
55	struct sigcontext uc_mcontext;
56	sigset_t	  uc_sigmask;	/* mask last for extensibility */
57};
58
59#define COMPAT_SI_PAD_SIZE	((SI_MAX_SIZE - 3 * sizeof(int)) / sizeof(int))
60
61struct compat_siginfo {
62	int si_signo;
63	int si_errno;
64	int si_code;
65
66	union {
67		int _pad[COMPAT_SI_PAD_SIZE];
68
69		/* kill() */
70		struct {
71			unsigned int _pid;	/* sender's pid */
72			unsigned int _uid;	/* sender's uid */
73		} _kill;
74
75		/* POSIX.1b timers */
76		struct {
77			compat_timer_t _tid;	/* timer id */
78			int _overrun;		/* overrun count */
79			compat_sigval_t _sigval;	/* same as below */
80			int _sys_private;	/* not to be passed to user */
81			int _overrun_incr;	/* amount to add to overrun */
82		} _timer;
83
84		/* POSIX.1b signals */
85		struct {
86			unsigned int _pid;	/* sender's pid */
87			unsigned int _uid;	/* sender's uid */
88			compat_sigval_t _sigval;
89		} _rt;
90
91		/* SIGCHLD */
92		struct {
93			unsigned int _pid;	/* which child */
94			unsigned int _uid;	/* sender's uid */
95			int _status;		/* exit code */
96			compat_clock_t _utime;
97			compat_clock_t _stime;
98		} _sigchld;
99
100		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
101		struct {
102			unsigned int _addr;	/* faulting insn/memory ref. */
103#ifdef __ARCH_SI_TRAPNO
104			int _trapno;	/* TRAP # which caused the signal */
105#endif
106		} _sigfault;
107
108		/* SIGPOLL */
109		struct {
110			int _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
111			int _fd;
112		} _sigpoll;
113	} _sifields;
114};
115
116struct compat_rt_sigframe {
117	unsigned char save_area[C_ABI_SAVE_AREA_SIZE]; /* caller save area */
118	struct compat_siginfo info;
119	struct compat_ucontext uc;
120};
121
122#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
123
124long compat_sys_rt_sigaction(int sig, struct compat_sigaction __user *act,
125			     struct compat_sigaction __user *oact,
126			     size_t sigsetsize)
127{
128	struct k_sigaction new_sa, old_sa;
129	int ret = -EINVAL;
130
131	if (sigsetsize != sizeof(sigset_t))
132		goto out;
133
134	if (act) {
135		compat_uptr_t handler, restorer;
136
137		if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
138		    __get_user(handler, &act->sa_handler) ||
139		    __get_user(new_sa.sa.sa_flags, &act->sa_flags) ||
140		    __get_user(restorer, &act->sa_restorer) ||
141		    __copy_from_user(&new_sa.sa.sa_mask, &act->sa_mask,
142				     sizeof(sigset_t)))
143			return -EFAULT;
144		new_sa.sa.sa_handler = compat_ptr(handler);
145		new_sa.sa.sa_restorer = compat_ptr(restorer);
146	}
147
148	ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
149
150	if (!ret && oact) {
151		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
152		    __put_user(ptr_to_compat(old_sa.sa.sa_handler),
153			       &oact->sa_handler) ||
154		    __put_user(ptr_to_compat(old_sa.sa.sa_restorer),
155			       &oact->sa_restorer) ||
156		    __put_user(old_sa.sa.sa_flags, &oact->sa_flags) ||
157		    __copy_to_user(&oact->sa_mask, &old_sa.sa.sa_mask,
158				   sizeof(sigset_t)))
159			return -EFAULT;
160	}
161out:
162	return ret;
163}
164
165long compat_sys_rt_sigqueueinfo(int pid, int sig,
166				struct compat_siginfo __user *uinfo)
167{
168	siginfo_t info;
169	int ret;
170	mm_segment_t old_fs = get_fs();
171
172	if (copy_siginfo_from_user32(&info, uinfo))
173		return -EFAULT;
174	set_fs(KERNEL_DS);
175	ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __force __user *)&info);
176	set_fs(old_fs);
177	return ret;
178}
179
180int copy_siginfo_to_user32(struct compat_siginfo __user *to, siginfo_t *from)
181{
182	int err;
183
184	if (!access_ok(VERIFY_WRITE, to, sizeof(struct compat_siginfo)))
185		return -EFAULT;
186
187	/* If you change siginfo_t structure, please make sure that
188	   this code is fixed accordingly.
189	   It should never copy any pad contained in the structure
190	   to avoid security leaks, but must copy the generic
191	   3 ints plus the relevant union member.  */
192	err = __put_user(from->si_signo, &to->si_signo);
193	err |= __put_user(from->si_errno, &to->si_errno);
194	err |= __put_user((short)from->si_code, &to->si_code);
195
196	if (from->si_code < 0) {
197		err |= __put_user(from->si_pid, &to->si_pid);
198		err |= __put_user(from->si_uid, &to->si_uid);
199		err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr);
200	} else {
201		/*
202		 * First 32bits of unions are always present:
203		 * si_pid === si_band === si_tid === si_addr(LS half)
204		 */
205		err |= __put_user(from->_sifields._pad[0],
206				  &to->_sifields._pad[0]);
207		switch (from->si_code >> 16) {
208		case __SI_FAULT >> 16:
209			break;
210		case __SI_CHLD >> 16:
211			err |= __put_user(from->si_utime, &to->si_utime);
212			err |= __put_user(from->si_stime, &to->si_stime);
213			err |= __put_user(from->si_status, &to->si_status);
214			/* FALL THROUGH */
215		default:
216		case __SI_KILL >> 16:
217			err |= __put_user(from->si_uid, &to->si_uid);
218			break;
219		case __SI_POLL >> 16:
220			err |= __put_user(from->si_fd, &to->si_fd);
221			break;
222		case __SI_TIMER >> 16:
223			err |= __put_user(from->si_overrun, &to->si_overrun);
224			err |= __put_user(ptr_to_compat(from->si_ptr),
225					  &to->si_ptr);
226			break;
227			 /* This is not generated by the kernel as of now.  */
228		case __SI_RT >> 16:
229		case __SI_MESGQ >> 16:
230			err |= __put_user(from->si_uid, &to->si_uid);
231			err |= __put_user(from->si_int, &to->si_int);
232			break;
233		}
234	}
235	return err;
236}
237
238int copy_siginfo_from_user32(siginfo_t *to, struct compat_siginfo __user *from)
239{
240	int err;
241	u32 ptr32;
242
243	if (!access_ok(VERIFY_READ, from, sizeof(struct compat_siginfo)))
244		return -EFAULT;
245
246	err = __get_user(to->si_signo, &from->si_signo);
247	err |= __get_user(to->si_errno, &from->si_errno);
248	err |= __get_user(to->si_code, &from->si_code);
249
250	err |= __get_user(to->si_pid, &from->si_pid);
251	err |= __get_user(to->si_uid, &from->si_uid);
252	err |= __get_user(ptr32, &from->si_ptr);
253	to->si_ptr = compat_ptr(ptr32);
254
255	return err;
256}
257
258long _compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,
259			     struct compat_sigaltstack __user *uoss_ptr,
260			     struct pt_regs *regs)
261{
262	stack_t uss, uoss;
263	int ret;
264	mm_segment_t seg;
265
266	if (uss_ptr) {
267		u32 ptr;
268
269		memset(&uss, 0, sizeof(stack_t));
270		if (!access_ok(VERIFY_READ, uss_ptr, sizeof(*uss_ptr)) ||
271			    __get_user(ptr, &uss_ptr->ss_sp) ||
272			    __get_user(uss.ss_flags, &uss_ptr->ss_flags) ||
273			    __get_user(uss.ss_size, &uss_ptr->ss_size))
274			return -EFAULT;
275		uss.ss_sp = compat_ptr(ptr);
276	}
277	seg = get_fs();
278	set_fs(KERNEL_DS);
279	ret = do_sigaltstack(uss_ptr ? (stack_t __user __force *)&uss : NULL,
280			     (stack_t __user __force *)&uoss,
281			     (unsigned long)compat_ptr(regs->sp));
282	set_fs(seg);
283	if (ret >= 0 && uoss_ptr)  {
284		if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(*uoss_ptr)) ||
285		    __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) ||
286		    __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) ||
287		    __put_user(uoss.ss_size, &uoss_ptr->ss_size))
288			ret = -EFAULT;
289	}
290	return ret;
291}
292
293long _compat_sys_rt_sigreturn(struct pt_regs *regs)
294{
295	struct compat_rt_sigframe __user *frame =
296		(struct compat_rt_sigframe __user *) compat_ptr(regs->sp);
297	sigset_t set;
298	long r0;
299
300	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
301		goto badframe;
302	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
303		goto badframe;
304
305	sigdelsetmask(&set, ~_BLOCKABLE);
306	spin_lock_irq(&current->sighand->siglock);
307	current->blocked = set;
308	recalc_sigpending();
309	spin_unlock_irq(&current->sighand->siglock);
310
311	if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &r0))
312		goto badframe;
313
314	if (_compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0)
315		goto badframe;
316
317	return r0;
318
319badframe:
320	force_sig(SIGSEGV, current);
321	return 0;
322}
323
324/*
325 * Determine which stack to use..
326 */
327static inline void __user *compat_get_sigframe(struct k_sigaction *ka,
328					       struct pt_regs *regs,
329					       size_t frame_size)
330{
331	unsigned long sp;
332
333	/* Default to using normal stack */
334	sp = (unsigned long)compat_ptr(regs->sp);
335
336	/*
337	 * If we are on the alternate signal stack and would overflow
338	 * it, don't.  Return an always-bogus address instead so we
339	 * will die with SIGSEGV.
340	 */
341	if (on_sig_stack(sp) && !likely(on_sig_stack(sp - frame_size)))
342		return (void __user __force *)-1UL;
343
344	/* This is the X/Open sanctioned signal stack switching.  */
345	if (ka->sa.sa_flags & SA_ONSTACK) {
346		if (sas_ss_flags(sp) == 0)
347			sp = current->sas_ss_sp + current->sas_ss_size;
348	}
349
350	sp -= frame_size;
351	/*
352	 * Align the stack pointer according to the TILE ABI,
353	 * i.e. so that on function entry (sp & 15) == 0.
354	 */
355	sp &= -16UL;
356	return (void __user *) sp;
357}
358
359int compat_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
360			  sigset_t *set, struct pt_regs *regs)
361{
362	unsigned long restorer;
363	struct compat_rt_sigframe __user *frame;
364	int err = 0;
365	int usig;
366
367	frame = compat_get_sigframe(ka, regs, sizeof(*frame));
368
369	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
370		goto give_sigsegv;
371
372	usig = current_thread_info()->exec_domain
373		&& current_thread_info()->exec_domain->signal_invmap
374		&& sig < 32
375		? current_thread_info()->exec_domain->signal_invmap[sig]
376		: sig;
377
378	/* Always write at least the signal number for the stack backtracer. */
379	if (ka->sa.sa_flags & SA_SIGINFO) {
380		/* At sigreturn time, restore the callee-save registers too. */
381		err |= copy_siginfo_to_user32(&frame->info, info);
382		regs->flags |= PT_FLAGS_RESTORE_REGS;
383	} else {
384		err |= __put_user(info->si_signo, &frame->info.si_signo);
385	}
386
387	/* Create the ucontext.  */
388	err |= __clear_user(&frame->save_area, sizeof(frame->save_area));
389	err |= __put_user(0, &frame->uc.uc_flags);
390	err |= __put_user(0, &frame->uc.uc_link);
391	err |= __put_user(ptr_to_compat((void *)(current->sas_ss_sp)),
392			  &frame->uc.uc_stack.ss_sp);
393	err |= __put_user(sas_ss_flags(regs->sp),
394			  &frame->uc.uc_stack.ss_flags);
395	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
396	err |= setup_sigcontext(&frame->uc.uc_mcontext, regs);
397	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
398	if (err)
399		goto give_sigsegv;
400
401	restorer = VDSO_BASE;
402	if (ka->sa.sa_flags & SA_RESTORER)
403		restorer = ptr_to_compat_reg(ka->sa.sa_restorer);
404
405	/*
406	 * Set up registers for signal handler.
407	 * Registers that we don't modify keep the value they had from
408	 * user-space at the time we took the signal.
409	 */
410	regs->pc = ptr_to_compat_reg(ka->sa.sa_handler);
411	regs->ex1 = PL_ICS_EX1(USER_PL, 1); /* set crit sec in handler */
412	regs->sp = ptr_to_compat_reg(frame);
413	regs->lr = restorer;
414	regs->regs[0] = (unsigned long) usig;
415
416	if (ka->sa.sa_flags & SA_SIGINFO) {
417		/* Need extra arguments, so mark to restore caller-saves. */
418		regs->regs[1] = ptr_to_compat_reg(&frame->info);
419		regs->regs[2] = ptr_to_compat_reg(&frame->uc);
420		regs->flags |= PT_FLAGS_CALLER_SAVES;
421	}
422
423	/*
424	 * Notify any tracer that was single-stepping it.
425	 * The tracer may want to single-step inside the
426	 * handler too.
427	 */
428	if (test_thread_flag(TIF_SINGLESTEP))
429		ptrace_notify(SIGTRAP);
430
431	return 0;
432
433give_sigsegv:
434	force_sigsegv(sig, current);
435	return -EFAULT;
436}
437