Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal
Pull signal handling cleanups from Al Viro: "This is the first pile; another one will come a bit later and will contain SYSCALL_DEFINE-related patches. - a bunch of signal-related syscalls (both native and compat) unified. - a bunch of compat syscalls switched to COMPAT_SYSCALL_DEFINE (fixing several potential problems with missing argument validation, while we are at it) - a lot of now-pointless wrappers killed - a couple of architectures (cris and hexagon) forgot to save altstack settings into sigframe, even though they used the (uninitialized) values in sigreturn; fixed. - microblaze fixes for delivery of multiple signals arriving at once - saner set of helpers for signal delivery introduced, several architectures switched to using those." * 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/signal: (143 commits) x86: convert to ksignal sparc: convert to ksignal arm: switch to struct ksignal * passing alpha: pass k_sigaction and siginfo_t using ksignal pointer burying unused conditionals make do_sigaltstack() static arm64: switch to generic old sigaction() (compat-only) arm64: switch to generic compat rt_sigaction() arm64: switch compat to generic old sigsuspend arm64: switch to generic compat rt_sigqueueinfo() arm64: switch to generic compat rt_sigpending() arm64: switch to generic compat rt_sigprocmask() arm64: switch to generic sigaltstack sparc: switch to generic old sigsuspend sparc: COMPAT_SYSCALL_DEFINE does all sign-extension as well as SYSCALL_DEFINE sparc: kill sign-extending wrappers for native syscalls kill sparc32_open() sparc: switch to use of generic old sigaction sparc: switch sys_compat_rt_sigaction() to COMPAT_SYSCALL_DEFINE mips: switch to generic sys_fork() and sys_clone() ...
This commit is contained in:
@@ -40,6 +40,7 @@ config MIPS
|
||||
select HAVE_MOD_ARCH_SPECIFIC
|
||||
select MODULES_USE_ELF_REL if MODULES
|
||||
select MODULES_USE_ELF_RELA if MODULES && 64BIT
|
||||
select CLONE_BACKWARDS
|
||||
|
||||
menu "Machine selection"
|
||||
|
||||
|
@@ -288,6 +288,14 @@ struct compat_shmid64_ds {
|
||||
compat_ulong_t __unused2;
|
||||
};
|
||||
|
||||
/* MIPS has unusual order of fields in stack_t */
|
||||
typedef struct compat_sigaltstack {
|
||||
compat_uptr_t ss_sp;
|
||||
compat_size_t ss_size;
|
||||
int ss_flags;
|
||||
} compat_stack_t;
|
||||
#define compat_sigaltstack compat_sigaltstack
|
||||
|
||||
static inline int is_compat_task(void)
|
||||
{
|
||||
return test_thread_flag(TIF_32BIT_ADDR);
|
||||
|
@@ -21,4 +21,6 @@
|
||||
#include <asm/sigcontext.h>
|
||||
#include <asm/siginfo.h>
|
||||
|
||||
#define __ARCH_HAS_ODD_SIGACTION
|
||||
|
||||
#endif /* _ASM_SIGNAL_H */
|
||||
|
@@ -20,10 +20,10 @@
|
||||
#define save_static_function(symbol) \
|
||||
__asm__( \
|
||||
".text\n\t" \
|
||||
".globl\t" #symbol "\n\t" \
|
||||
".globl\t__" #symbol "\n\t" \
|
||||
".align\t2\n\t" \
|
||||
".type\t" #symbol ", @function\n\t" \
|
||||
".ent\t" #symbol ", 0\n" \
|
||||
".type\t__" #symbol ", @function\n\t" \
|
||||
".ent\t__" #symbol ", 0\n__" \
|
||||
#symbol":\n\t" \
|
||||
".frame\t$29, 0, $31\n\t" \
|
||||
"sw\t$16,"__str(PT_R16)"($29)\t\t\t# save_static_function\n\t" \
|
||||
@@ -35,9 +35,9 @@ __asm__( \
|
||||
"sw\t$22,"__str(PT_R22)"($29)\n\t" \
|
||||
"sw\t$23,"__str(PT_R23)"($29)\n\t" \
|
||||
"sw\t$30,"__str(PT_R30)"($29)\n\t" \
|
||||
"j\t_" #symbol "\n\t" \
|
||||
".end\t" #symbol "\n\t" \
|
||||
".size\t" #symbol",. - " #symbol)
|
||||
"j\t" #symbol "\n\t" \
|
||||
".end\t__" #symbol "\n\t" \
|
||||
".size\t__" #symbol",. - __" #symbol)
|
||||
|
||||
#define nabi_no_regargs
|
||||
|
||||
@@ -48,10 +48,10 @@ __asm__( \
|
||||
#define save_static_function(symbol) \
|
||||
__asm__( \
|
||||
".text\n\t" \
|
||||
".globl\t" #symbol "\n\t" \
|
||||
".globl\t__" #symbol "\n\t" \
|
||||
".align\t2\n\t" \
|
||||
".type\t" #symbol ", @function\n\t" \
|
||||
".ent\t" #symbol ", 0\n" \
|
||||
".type\t__" #symbol ", @function\n\t" \
|
||||
".ent\t__" #symbol ", 0\n__" \
|
||||
#symbol":\n\t" \
|
||||
".frame\t$29, 0, $31\n\t" \
|
||||
"sd\t$16,"__str(PT_R16)"($29)\t\t\t# save_static_function\n\t" \
|
||||
@@ -63,9 +63,9 @@ __asm__( \
|
||||
"sd\t$22,"__str(PT_R22)"($29)\n\t" \
|
||||
"sd\t$23,"__str(PT_R23)"($29)\n\t" \
|
||||
"sd\t$30,"__str(PT_R30)"($29)\n\t" \
|
||||
"j\t_" #symbol "\n\t" \
|
||||
".end\t" #symbol "\n\t" \
|
||||
".size\t" #symbol",. - " #symbol)
|
||||
"j\t" #symbol "\n\t" \
|
||||
".end\t__" #symbol "\n\t" \
|
||||
".size\t__" #symbol",. - __" #symbol)
|
||||
|
||||
#define nabi_no_regargs \
|
||||
unsigned long __dummy0, \
|
||||
|
@@ -35,7 +35,6 @@
|
||||
#define __ARCH_WANT_SYS_OLDUMOUNT
|
||||
#define __ARCH_WANT_SYS_SIGPENDING
|
||||
#define __ARCH_WANT_SYS_SIGPROCMASK
|
||||
#define __ARCH_WANT_SYS_RT_SIGACTION
|
||||
# ifdef CONFIG_32BIT
|
||||
# define __ARCH_WANT_STAT64
|
||||
# define __ARCH_WANT_SYS_TIME
|
||||
@@ -43,6 +42,8 @@
|
||||
# ifdef CONFIG_MIPS32_O32
|
||||
# define __ARCH_WANT_COMPAT_SYS_TIME
|
||||
# endif
|
||||
#define __ARCH_WANT_SYS_FORK
|
||||
#define __ARCH_WANT_SYS_CLONE
|
||||
|
||||
/* whitelists for checksyscalls */
|
||||
#define __IGNORE_select
|
||||
|
@@ -96,15 +96,13 @@ typedef unsigned long old_sigset_t; /* at least 32 bits */
|
||||
|
||||
#include <asm-generic/signal-defs.h>
|
||||
|
||||
#ifndef __KERNEL__
|
||||
struct sigaction {
|
||||
unsigned int sa_flags;
|
||||
__sighandler_t sa_handler;
|
||||
sigset_t sa_mask;
|
||||
};
|
||||
|
||||
struct k_sigaction {
|
||||
struct sigaction sa;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* IRIX compatible stack_t */
|
||||
typedef struct sigaltstack {
|
||||
|
@@ -119,22 +119,6 @@ SYSCALL_DEFINE6(32_pwrite, unsigned int, fd, const char __user *, buf,
|
||||
return sys_pwrite64(fd, buf, count, merge_64(a4, a5));
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE2(32_sched_rr_get_interval, compat_pid_t, pid,
|
||||
struct compat_timespec __user *, interval)
|
||||
{
|
||||
struct timespec t;
|
||||
int ret;
|
||||
mm_segment_t old_fs = get_fs();
|
||||
|
||||
set_fs(KERNEL_DS);
|
||||
ret = sys_sched_rr_get_interval(pid, (struct timespec __user *)&t);
|
||||
set_fs(old_fs);
|
||||
if (put_user (t.tv_sec, &interval->tv_sec) ||
|
||||
__put_user(t.tv_nsec, &interval->tv_nsec))
|
||||
return -EFAULT;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SYSVIPC
|
||||
|
||||
SYSCALL_DEFINE6(32_ipc, u32, call, long, first, long, second, long, third,
|
||||
@@ -295,27 +279,6 @@ asmlinkage long sys32_fallocate(int fd, int mode, unsigned offset_a2,
|
||||
merge_64(len_a4, len_a5));
|
||||
}
|
||||
|
||||
save_static_function(sys32_clone);
|
||||
static int noinline __used
|
||||
_sys32_clone(nabi_no_regargs struct pt_regs regs)
|
||||
{
|
||||
unsigned long clone_flags;
|
||||
unsigned long newsp;
|
||||
int __user *parent_tidptr, *child_tidptr;
|
||||
|
||||
clone_flags = regs.regs[4];
|
||||
newsp = regs.regs[5];
|
||||
if (!newsp)
|
||||
newsp = regs.regs[29];
|
||||
parent_tidptr = (int __user *) regs.regs[6];
|
||||
|
||||
/* Use __dummy4 instead of getting it off the stack, so that
|
||||
syscall() works. */
|
||||
child_tidptr = (int __user *) __dummy4;
|
||||
return do_fork(clone_flags, newsp, 0,
|
||||
parent_tidptr, child_tidptr);
|
||||
}
|
||||
|
||||
asmlinkage long sys32_lookup_dcookie(u32 a0, u32 a1, char __user *buf,
|
||||
size_t len)
|
||||
{
|
||||
@@ -328,10 +291,3 @@ SYSCALL_DEFINE6(32_fanotify_mark, int, fanotify_fd, unsigned int, flags,
|
||||
return sys_fanotify_mark(fanotify_fd, flags, merge_64(a3, a4),
|
||||
dfd, pathname);
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE6(32_futex, u32 __user *, uaddr, int, op, u32, val,
|
||||
struct compat_timespec __user *, utime, u32 __user *, uaddr2,
|
||||
u32, val3)
|
||||
{
|
||||
return compat_sys_futex(uaddr, op, val, utime, uaddr2, val3);
|
||||
}
|
||||
|
@@ -156,7 +156,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
|
||||
*childregs = *regs;
|
||||
childregs->regs[7] = 0; /* Clear error flag */
|
||||
childregs->regs[2] = 0; /* Child gets zero as return value */
|
||||
childregs->regs[29] = usp;
|
||||
if (usp)
|
||||
childregs->regs[29] = usp;
|
||||
ti->addr_limit = USER_DS;
|
||||
|
||||
p->thread.reg29 = (unsigned long) childregs;
|
||||
|
@@ -226,7 +226,7 @@ einval: li v0, -ENOSYS
|
||||
.macro syscalltable
|
||||
sys sys_syscall 8 /* 4000 */
|
||||
sys sys_exit 1
|
||||
sys sys_fork 0
|
||||
sys __sys_fork 0
|
||||
sys sys_read 3
|
||||
sys sys_write 3
|
||||
sys sys_open 3 /* 4005 */
|
||||
@@ -344,7 +344,7 @@ einval: li v0, -ENOSYS
|
||||
sys sys_ipc 6
|
||||
sys sys_fsync 1
|
||||
sys sys_sigreturn 0
|
||||
sys sys_clone 0 /* 4120 */
|
||||
sys __sys_clone 6 /* 4120 */
|
||||
sys sys_setdomainname 2
|
||||
sys sys_newuname 1
|
||||
sys sys_ni_syscall 0 /* sys_modify_ldt */
|
||||
|
@@ -170,8 +170,8 @@ sys_call_table:
|
||||
PTR sys_socketpair
|
||||
PTR sys_setsockopt
|
||||
PTR sys_getsockopt
|
||||
PTR sys_clone /* 5055 */
|
||||
PTR sys_fork
|
||||
PTR __sys_clone /* 5055 */
|
||||
PTR __sys_fork
|
||||
PTR sys_execve
|
||||
PTR sys_exit
|
||||
PTR sys_wait4
|
||||
|
@@ -117,8 +117,8 @@ EXPORT(sysn32_call_table)
|
||||
PTR sys_mprotect /* 6010 */
|
||||
PTR sys_munmap
|
||||
PTR sys_brk
|
||||
PTR sys_32_rt_sigaction
|
||||
PTR sys_32_rt_sigprocmask
|
||||
PTR compat_sys_rt_sigaction
|
||||
PTR compat_sys_rt_sigprocmask
|
||||
PTR compat_sys_ioctl /* 6015 */
|
||||
PTR sys_pread64
|
||||
PTR sys_pwrite64
|
||||
@@ -159,8 +159,8 @@ EXPORT(sysn32_call_table)
|
||||
PTR sys_socketpair
|
||||
PTR compat_sys_setsockopt
|
||||
PTR sys_getsockopt
|
||||
PTR sys_clone /* 6055 */
|
||||
PTR sys_fork
|
||||
PTR __sys_clone /* 6055 */
|
||||
PTR __sys_fork
|
||||
PTR compat_sys_execve
|
||||
PTR sys_exit
|
||||
PTR compat_sys_wait4
|
||||
@@ -229,11 +229,11 @@ EXPORT(sysn32_call_table)
|
||||
PTR sys_getsid
|
||||
PTR sys_capget
|
||||
PTR sys_capset
|
||||
PTR sys_32_rt_sigpending /* 6125 */
|
||||
PTR compat_sys_rt_sigpending /* 6125 */
|
||||
PTR compat_sys_rt_sigtimedwait
|
||||
PTR sys_32_rt_sigqueueinfo
|
||||
PTR sysn32_rt_sigsuspend
|
||||
PTR sys32_sigaltstack
|
||||
PTR compat_sys_rt_sigqueueinfo
|
||||
PTR compat_sys_rt_sigsuspend
|
||||
PTR compat_sys_sigaltstack
|
||||
PTR compat_sys_utime /* 6130 */
|
||||
PTR sys_mknod
|
||||
PTR sys_32_personality
|
||||
@@ -249,7 +249,7 @@ EXPORT(sysn32_call_table)
|
||||
PTR sys_sched_getscheduler
|
||||
PTR sys_sched_get_priority_max
|
||||
PTR sys_sched_get_priority_min
|
||||
PTR sys_32_sched_rr_get_interval /* 6145 */
|
||||
PTR compat_sys_sched_rr_get_interval /* 6145 */
|
||||
PTR sys_mlock
|
||||
PTR sys_munlock
|
||||
PTR sys_mlockall
|
||||
@@ -298,7 +298,7 @@ EXPORT(sysn32_call_table)
|
||||
PTR sys_fremovexattr
|
||||
PTR sys_tkill
|
||||
PTR sys_ni_syscall
|
||||
PTR sys_32_futex
|
||||
PTR compat_sys_futex
|
||||
PTR compat_sys_sched_setaffinity /* 6195 */
|
||||
PTR compat_sys_sched_getaffinity
|
||||
PTR sys_cacheflush
|
||||
|
@@ -194,7 +194,7 @@ einval: li v0, -ENOSYS
|
||||
sys_call_table:
|
||||
PTR sys32_syscall /* 4000 */
|
||||
PTR sys_exit
|
||||
PTR sys_fork
|
||||
PTR __sys_fork
|
||||
PTR sys_read
|
||||
PTR sys_write
|
||||
PTR compat_sys_open /* 4005 */
|
||||
@@ -312,7 +312,7 @@ sys_call_table:
|
||||
PTR sys_32_ipc
|
||||
PTR sys_fsync
|
||||
PTR sys32_sigreturn
|
||||
PTR sys32_clone /* 4120 */
|
||||
PTR __sys_clone /* 4120 */
|
||||
PTR sys_setdomainname
|
||||
PTR sys_newuname
|
||||
PTR sys_ni_syscall /* sys_modify_ldt */
|
||||
@@ -357,7 +357,7 @@ sys_call_table:
|
||||
PTR sys_sched_yield
|
||||
PTR sys_sched_get_priority_max
|
||||
PTR sys_sched_get_priority_min
|
||||
PTR sys_32_sched_rr_get_interval /* 4165 */
|
||||
PTR compat_sys_sched_rr_get_interval /* 4165 */
|
||||
PTR compat_sys_nanosleep
|
||||
PTR sys_mremap
|
||||
PTR sys_accept
|
||||
@@ -386,19 +386,19 @@ sys_call_table:
|
||||
PTR sys_getresgid
|
||||
PTR sys_prctl
|
||||
PTR sys32_rt_sigreturn
|
||||
PTR sys_32_rt_sigaction
|
||||
PTR sys_32_rt_sigprocmask /* 4195 */
|
||||
PTR sys_32_rt_sigpending
|
||||
PTR compat_sys_rt_sigaction
|
||||
PTR compat_sys_rt_sigprocmask /* 4195 */
|
||||
PTR compat_sys_rt_sigpending
|
||||
PTR compat_sys_rt_sigtimedwait
|
||||
PTR sys_32_rt_sigqueueinfo
|
||||
PTR sys32_rt_sigsuspend
|
||||
PTR compat_sys_rt_sigqueueinfo
|
||||
PTR compat_sys_rt_sigsuspend
|
||||
PTR sys_32_pread /* 4200 */
|
||||
PTR sys_32_pwrite
|
||||
PTR sys_chown
|
||||
PTR sys_getcwd
|
||||
PTR sys_capget
|
||||
PTR sys_capset /* 4205 */
|
||||
PTR sys32_sigaltstack
|
||||
PTR compat_sys_sigaltstack
|
||||
PTR sys_32_sendfile
|
||||
PTR sys_ni_syscall
|
||||
PTR sys_ni_syscall
|
||||
@@ -430,7 +430,7 @@ sys_call_table:
|
||||
PTR sys_fremovexattr /* 4235 */
|
||||
PTR sys_tkill
|
||||
PTR sys_sendfile64
|
||||
PTR sys_32_futex
|
||||
PTR compat_sys_futex
|
||||
PTR compat_sys_sched_setaffinity
|
||||
PTR compat_sys_sched_getaffinity /* 4240 */
|
||||
PTR compat_sys_io_setup
|
||||
@@ -470,7 +470,7 @@ sys_call_table:
|
||||
PTR compat_sys_mq_notify /* 4275 */
|
||||
PTR compat_sys_mq_getsetattr
|
||||
PTR sys_ni_syscall /* sys_vserver */
|
||||
PTR sys_32_waitid
|
||||
PTR compat_sys_waitid
|
||||
PTR sys_ni_syscall /* available, was setaltroot */
|
||||
PTR sys_add_key /* 4280 */
|
||||
PTR sys_request_key
|
||||
|
@@ -247,35 +247,12 @@ void __user *get_sigframe(struct k_sigaction *ka, struct pt_regs *regs,
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_TRAD_SIGNALS
|
||||
asmlinkage int sys_sigsuspend(nabi_no_regargs struct pt_regs regs)
|
||||
SYSCALL_DEFINE1(sigsuspend, sigset_t __user *, uset)
|
||||
{
|
||||
sigset_t newset;
|
||||
sigset_t __user *uset;
|
||||
|
||||
uset = (sigset_t __user *) regs.regs[4];
|
||||
if (copy_from_user(&newset, uset, sizeof(sigset_t)))
|
||||
return -EFAULT;
|
||||
return sigsuspend(&newset);
|
||||
return sys_rt_sigsuspend(uset, sizeof(sigset_t));
|
||||
}
|
||||
#endif
|
||||
|
||||
asmlinkage int sys_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
|
||||
{
|
||||
sigset_t newset;
|
||||
sigset_t __user *unewset;
|
||||
size_t sigsetsize;
|
||||
|
||||
/* XXX Don't preclude handling different sized sigset_t's. */
|
||||
sigsetsize = regs.regs[5];
|
||||
if (sigsetsize != sizeof(sigset_t))
|
||||
return -EINVAL;
|
||||
|
||||
unewset = (sigset_t __user *) regs.regs[4];
|
||||
if (copy_from_user(&newset, unewset, sizeof(newset)))
|
||||
return -EFAULT;
|
||||
return sigsuspend(&newset);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TRAD_SIGNALS
|
||||
SYSCALL_DEFINE3(sigaction, int, sig, const struct sigaction __user *, act,
|
||||
struct sigaction __user *, oact)
|
||||
@@ -317,15 +294,6 @@ SYSCALL_DEFINE3(sigaction, int, sig, const struct sigaction __user *, act,
|
||||
}
|
||||
#endif
|
||||
|
||||
asmlinkage int sys_sigaltstack(nabi_no_regargs struct pt_regs regs)
|
||||
{
|
||||
const stack_t __user *uss = (const stack_t __user *) regs.regs[4];
|
||||
stack_t __user *uoss = (stack_t __user *) regs.regs[5];
|
||||
unsigned long usp = regs.regs[29];
|
||||
|
||||
return do_sigaltstack(uss, uoss, usp);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TRAD_SIGNALS
|
||||
asmlinkage void sys_sigreturn(nabi_no_regargs struct pt_regs regs)
|
||||
{
|
||||
@@ -382,9 +350,8 @@ asmlinkage void sys_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
|
||||
else if (sig)
|
||||
force_sig(sig, current);
|
||||
|
||||
/* It is more difficult to avoid calling this function than to
|
||||
call it and ignore errors. */
|
||||
do_sigaltstack(&frame->rs_uc.uc_stack, NULL, regs.regs[29]);
|
||||
if (restore_altstack(&frame->rs_uc.uc_stack))
|
||||
goto badframe;
|
||||
|
||||
/*
|
||||
* Don't let your children do this ...
|
||||
@@ -461,12 +428,7 @@ static int setup_rt_frame(void *sig_return, struct k_sigaction *ka,
|
||||
/* Create the ucontext. */
|
||||
err |= __put_user(0, &frame->rs_uc.uc_flags);
|
||||
err |= __put_user(NULL, &frame->rs_uc.uc_link);
|
||||
err |= __put_user((void __user *)current->sas_ss_sp,
|
||||
&frame->rs_uc.uc_stack.ss_sp);
|
||||
err |= __put_user(sas_ss_flags(regs->regs[29]),
|
||||
&frame->rs_uc.uc_stack.ss_flags);
|
||||
err |= __put_user(current->sas_ss_size,
|
||||
&frame->rs_uc.uc_stack.ss_size);
|
||||
err |= __save_altstack(&frame->rs_uc.uc_stack, regs->regs[29]);
|
||||
err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext);
|
||||
err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
|
||||
|
||||
|
@@ -55,23 +55,10 @@ extern asmlinkage int fpu_emulator_restore_context32(struct sigcontext32 __user
|
||||
typedef unsigned int __sighandler32_t;
|
||||
typedef void (*vfptr_t)(void);
|
||||
|
||||
struct sigaction32 {
|
||||
unsigned int sa_flags;
|
||||
__sighandler32_t sa_handler;
|
||||
compat_sigset_t sa_mask;
|
||||
};
|
||||
|
||||
/* IRIX compatible stack_t */
|
||||
typedef struct sigaltstack32 {
|
||||
s32 ss_sp;
|
||||
compat_size_t ss_size;
|
||||
int ss_flags;
|
||||
} stack32_t;
|
||||
|
||||
struct ucontext32 {
|
||||
u32 uc_flags;
|
||||
s32 uc_link;
|
||||
stack32_t uc_stack;
|
||||
compat_stack_t uc_stack;
|
||||
struct sigcontext32 uc_mcontext;
|
||||
compat_sigset_t uc_sigmask; /* mask last for extensibility */
|
||||
};
|
||||
@@ -280,36 +267,13 @@ static inline int get_sigset(sigset_t *kbuf, const compat_sigset_t __user *ubuf)
|
||||
* Atomically swap in the new signal mask, and wait for a signal.
|
||||
*/
|
||||
|
||||
asmlinkage int sys32_sigsuspend(nabi_no_regargs struct pt_regs regs)
|
||||
asmlinkage int sys32_sigsuspend(compat_sigset_t __user *uset)
|
||||
{
|
||||
compat_sigset_t __user *uset;
|
||||
sigset_t newset;
|
||||
|
||||
uset = (compat_sigset_t __user *) regs.regs[4];
|
||||
if (get_sigset(&newset, uset))
|
||||
return -EFAULT;
|
||||
return sigsuspend(&newset);
|
||||
return compat_sys_rt_sigsuspend(uset, sizeof(compat_sigset_t));
|
||||
}
|
||||
|
||||
asmlinkage int sys32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
|
||||
{
|
||||
compat_sigset_t __user *uset;
|
||||
sigset_t newset;
|
||||
size_t sigsetsize;
|
||||
|
||||
/* XXX Don't preclude handling different sized sigset_t's. */
|
||||
sigsetsize = regs.regs[5];
|
||||
if (sigsetsize != sizeof(compat_sigset_t))
|
||||
return -EINVAL;
|
||||
|
||||
uset = (compat_sigset_t __user *) regs.regs[4];
|
||||
if (get_sigset(&newset, uset))
|
||||
return -EFAULT;
|
||||
return sigsuspend(&newset);
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE3(32_sigaction, long, sig, const struct sigaction32 __user *, act,
|
||||
struct sigaction32 __user *, oact)
|
||||
SYSCALL_DEFINE3(32_sigaction, long, sig, const struct compat_sigaction __user *, act,
|
||||
struct compat_sigaction __user *, oact)
|
||||
{
|
||||
struct k_sigaction new_ka, old_ka;
|
||||
int ret;
|
||||
@@ -350,45 +314,6 @@ SYSCALL_DEFINE3(32_sigaction, long, sig, const struct sigaction32 __user *, act,
|
||||
return ret;
|
||||
}
|
||||
|
||||
asmlinkage int sys32_sigaltstack(nabi_no_regargs struct pt_regs regs)
|
||||
{
|
||||
const stack32_t __user *uss = (const stack32_t __user *) regs.regs[4];
|
||||
stack32_t __user *uoss = (stack32_t __user *) regs.regs[5];
|
||||
unsigned long usp = regs.regs[29];
|
||||
stack_t kss, koss;
|
||||
int ret, err = 0;
|
||||
mm_segment_t old_fs = get_fs();
|
||||
s32 sp;
|
||||
|
||||
if (uss) {
|
||||
if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
|
||||
return -EFAULT;
|
||||
err |= __get_user(sp, &uss->ss_sp);
|
||||
kss.ss_sp = (void __user *) (long) sp;
|
||||
err |= __get_user(kss.ss_size, &uss->ss_size);
|
||||
err |= __get_user(kss.ss_flags, &uss->ss_flags);
|
||||
if (err)
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
set_fs(KERNEL_DS);
|
||||
ret = do_sigaltstack(uss ? (stack_t __user *)&kss : NULL,
|
||||
uoss ? (stack_t __user *)&koss : NULL, usp);
|
||||
set_fs(old_fs);
|
||||
|
||||
if (!ret && uoss) {
|
||||
if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
|
||||
return -EFAULT;
|
||||
sp = (int) (unsigned long) koss.ss_sp;
|
||||
err |= __put_user(sp, &uoss->ss_sp);
|
||||
err |= __put_user(koss.ss_size, &uoss->ss_size);
|
||||
err |= __put_user(koss.ss_flags, &uoss->ss_flags);
|
||||
if (err)
|
||||
return -EFAULT;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
|
||||
{
|
||||
int err;
|
||||
@@ -490,10 +415,7 @@ badframe:
|
||||
asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
|
||||
{
|
||||
struct rt_sigframe32 __user *frame;
|
||||
mm_segment_t old_fs;
|
||||
sigset_t set;
|
||||
stack_t st;
|
||||
s32 sp;
|
||||
int sig;
|
||||
|
||||
frame = (struct rt_sigframe32 __user *) regs.regs[29];
|
||||
@@ -510,21 +432,8 @@ asmlinkage void sys32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
|
||||
else if (sig)
|
||||
force_sig(sig, current);
|
||||
|
||||
/* The ucontext contains a stack32_t, so we must convert! */
|
||||
if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp))
|
||||
if (compat_restore_altstack(&frame->rs_uc.uc_stack))
|
||||
goto badframe;
|
||||
st.ss_sp = (void __user *)(long) sp;
|
||||
if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size))
|
||||
goto badframe;
|
||||
if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags))
|
||||
goto badframe;
|
||||
|
||||
/* It is more difficult to avoid calling this function than to
|
||||
call it and ignore errors. */
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]);
|
||||
set_fs(old_fs);
|
||||
|
||||
/*
|
||||
* Don't let your children do this ...
|
||||
@@ -590,7 +499,6 @@ static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka,
|
||||
{
|
||||
struct rt_sigframe32 __user *frame;
|
||||
int err = 0;
|
||||
s32 sp;
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
|
||||
@@ -602,13 +510,7 @@ static int setup_rt_frame_32(void *sig_return, struct k_sigaction *ka,
|
||||
/* Create the ucontext. */
|
||||
err |= __put_user(0, &frame->rs_uc.uc_flags);
|
||||
err |= __put_user(0, &frame->rs_uc.uc_link);
|
||||
sp = (int) (long) current->sas_ss_sp;
|
||||
err |= __put_user(sp,
|
||||
&frame->rs_uc.uc_stack.ss_sp);
|
||||
err |= __put_user(sas_ss_flags(regs->regs[29]),
|
||||
&frame->rs_uc.uc_stack.ss_flags);
|
||||
err |= __put_user(current->sas_ss_size,
|
||||
&frame->rs_uc.uc_stack.ss_size);
|
||||
err |= __compat_save_altstack(&frame->rs_uc.uc_stack, regs->regs[29]);
|
||||
err |= setup_sigcontext32(regs, &frame->rs_uc.uc_mcontext);
|
||||
err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
|
||||
|
||||
@@ -656,131 +558,6 @@ struct mips_abi mips_abi_32 = {
|
||||
.restart = __NR_O32_restart_syscall
|
||||
};
|
||||
|
||||
SYSCALL_DEFINE4(32_rt_sigaction, int, sig,
|
||||
const struct sigaction32 __user *, act,
|
||||
struct sigaction32 __user *, oact, unsigned int, sigsetsize)
|
||||
{
|
||||
struct k_sigaction new_sa, old_sa;
|
||||
int ret = -EINVAL;
|
||||
|
||||
/* XXX: Don't preclude handling different sized sigset_t's. */
|
||||
if (sigsetsize != sizeof(sigset_t))
|
||||
goto out;
|
||||
|
||||
if (act) {
|
||||
s32 handler;
|
||||
int err = 0;
|
||||
|
||||
if (!access_ok(VERIFY_READ, act, sizeof(*act)))
|
||||
return -EFAULT;
|
||||
err |= __get_user(handler, &act->sa_handler);
|
||||
new_sa.sa.sa_handler = (void __user *)(s64)handler;
|
||||
err |= __get_user(new_sa.sa.sa_flags, &act->sa_flags);
|
||||
err |= get_sigset(&new_sa.sa.sa_mask, &act->sa_mask);
|
||||
if (err)
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
ret = do_sigaction(sig, act ? &new_sa : NULL, oact ? &old_sa : NULL);
|
||||
|
||||
if (!ret && oact) {
|
||||
int err = 0;
|
||||
|
||||
if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
|
||||
return -EFAULT;
|
||||
|
||||
err |= __put_user((u32)(u64)old_sa.sa.sa_handler,
|
||||
&oact->sa_handler);
|
||||
err |= __put_user(old_sa.sa.sa_flags, &oact->sa_flags);
|
||||
err |= put_sigset(&old_sa.sa.sa_mask, &oact->sa_mask);
|
||||
if (err)
|
||||
return -EFAULT;
|
||||
}
|
||||
out:
|
||||
return ret;
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE4(32_rt_sigprocmask, int, how, compat_sigset_t __user *, set,
|
||||
compat_sigset_t __user *, oset, unsigned int, sigsetsize)
|
||||
{
|
||||
sigset_t old_set, new_set;
|
||||
int ret;
|
||||
mm_segment_t old_fs = get_fs();
|
||||
|
||||
if (set && get_sigset(&new_set, set))
|
||||
return -EFAULT;
|
||||
|
||||
set_fs(KERNEL_DS);
|
||||
ret = sys_rt_sigprocmask(how, set ? (sigset_t __user *)&new_set : NULL,
|
||||
oset ? (sigset_t __user *)&old_set : NULL,
|
||||
sigsetsize);
|
||||
set_fs(old_fs);
|
||||
|
||||
if (!ret && oset && put_sigset(&old_set, oset))
|
||||
return -EFAULT;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE2(32_rt_sigpending, compat_sigset_t __user *, uset,
|
||||
unsigned int, sigsetsize)
|
||||
{
|
||||
int ret;
|
||||
sigset_t set;
|
||||
mm_segment_t old_fs = get_fs();
|
||||
|
||||
set_fs(KERNEL_DS);
|
||||
ret = sys_rt_sigpending((sigset_t __user *)&set, sigsetsize);
|
||||
set_fs(old_fs);
|
||||
|
||||
if (!ret && put_sigset(&set, uset))
|
||||
return -EFAULT;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE3(32_rt_sigqueueinfo, int, pid, int, sig,
|
||||
compat_siginfo_t __user *, uinfo)
|
||||
{
|
||||
siginfo_t info;
|
||||
int ret;
|
||||
mm_segment_t old_fs = get_fs();
|
||||
|
||||
if (copy_from_user(&info, uinfo, 3*sizeof(int)) ||
|
||||
copy_from_user(info._sifields._pad, uinfo->_sifields._pad, SI_PAD_SIZE))
|
||||
return -EFAULT;
|
||||
set_fs(KERNEL_DS);
|
||||
ret = sys_rt_sigqueueinfo(pid, sig, (siginfo_t __user *)&info);
|
||||
set_fs(old_fs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE5(32_waitid, int, which, compat_pid_t, pid,
|
||||
compat_siginfo_t __user *, uinfo, int, options,
|
||||
struct compat_rusage __user *, uru)
|
||||
{
|
||||
siginfo_t info;
|
||||
struct rusage ru;
|
||||
long ret;
|
||||
mm_segment_t old_fs = get_fs();
|
||||
|
||||
info.si_signo = 0;
|
||||
set_fs(KERNEL_DS);
|
||||
ret = sys_waitid(which, pid, (siginfo_t __user *) &info, options,
|
||||
uru ? (struct rusage __user *) &ru : NULL);
|
||||
set_fs(old_fs);
|
||||
|
||||
if (ret < 0 || info.si_signo == 0)
|
||||
return ret;
|
||||
|
||||
if (uru && (ret = put_compat_rusage(&ru, uru)))
|
||||
return ret;
|
||||
|
||||
BUG_ON(info.si_code & __SI_MASK);
|
||||
info.si_code |= __SI_CHLD;
|
||||
return copy_siginfo_to_user32(uinfo, &info);
|
||||
}
|
||||
|
||||
static int signal32_init(void)
|
||||
{
|
||||
if (cpu_has_fpu) {
|
||||
|
@@ -50,18 +50,10 @@
|
||||
extern int setup_sigcontext(struct pt_regs *, struct sigcontext __user *);
|
||||
extern int restore_sigcontext(struct pt_regs *, struct sigcontext __user *);
|
||||
|
||||
|
||||
/* IRIX compatible stack_t */
|
||||
typedef struct sigaltstack32 {
|
||||
s32 ss_sp;
|
||||
compat_size_t ss_size;
|
||||
int ss_flags;
|
||||
} stack32_t;
|
||||
|
||||
struct ucontextn32 {
|
||||
u32 uc_flags;
|
||||
s32 uc_link;
|
||||
stack32_t uc_stack;
|
||||
compat_stack_t uc_stack;
|
||||
struct sigcontext uc_mcontext;
|
||||
compat_sigset_t uc_sigmask; /* mask last for extensibility */
|
||||
};
|
||||
@@ -73,34 +65,10 @@ struct rt_sigframe_n32 {
|
||||
struct ucontextn32 rs_uc;
|
||||
};
|
||||
|
||||
extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat);
|
||||
|
||||
asmlinkage int sysn32_rt_sigsuspend(nabi_no_regargs struct pt_regs regs)
|
||||
{
|
||||
compat_sigset_t __user *unewset;
|
||||
compat_sigset_t uset;
|
||||
size_t sigsetsize;
|
||||
sigset_t newset;
|
||||
|
||||
/* XXX Don't preclude handling different sized sigset_t's. */
|
||||
sigsetsize = regs.regs[5];
|
||||
if (sigsetsize != sizeof(sigset_t))
|
||||
return -EINVAL;
|
||||
|
||||
unewset = (compat_sigset_t __user *) regs.regs[4];
|
||||
if (copy_from_user(&uset, unewset, sizeof(uset)))
|
||||
return -EFAULT;
|
||||
sigset_from_compat(&newset, &uset);
|
||||
return sigsuspend(&newset);
|
||||
}
|
||||
|
||||
asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
|
||||
{
|
||||
struct rt_sigframe_n32 __user *frame;
|
||||
mm_segment_t old_fs;
|
||||
sigset_t set;
|
||||
stack_t st;
|
||||
s32 sp;
|
||||
int sig;
|
||||
|
||||
frame = (struct rt_sigframe_n32 __user *) regs.regs[29];
|
||||
@@ -117,22 +85,8 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
|
||||
else if (sig)
|
||||
force_sig(sig, current);
|
||||
|
||||
/* The ucontext contains a stack32_t, so we must convert! */
|
||||
if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp))
|
||||
if (compat_restore_altstack(&frame->rs_uc.uc_stack))
|
||||
goto badframe;
|
||||
st.ss_sp = (void __user *)(long) sp;
|
||||
if (__get_user(st.ss_size, &frame->rs_uc.uc_stack.ss_size))
|
||||
goto badframe;
|
||||
if (__get_user(st.ss_flags, &frame->rs_uc.uc_stack.ss_flags))
|
||||
goto badframe;
|
||||
|
||||
/* It is more difficult to avoid calling this function than to
|
||||
call it and ignore errors. */
|
||||
old_fs = get_fs();
|
||||
set_fs(KERNEL_DS);
|
||||
do_sigaltstack((stack_t __user *)&st, NULL, regs.regs[29]);
|
||||
set_fs(old_fs);
|
||||
|
||||
|
||||
/*
|
||||
* Don't let your children do this ...
|
||||
@@ -153,7 +107,6 @@ static int setup_rt_frame_n32(void *sig_return, struct k_sigaction *ka,
|
||||
{
|
||||
struct rt_sigframe_n32 __user *frame;
|
||||
int err = 0;
|
||||
s32 sp;
|
||||
|
||||
frame = get_sigframe(ka, regs, sizeof(*frame));
|
||||
if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
|
||||
@@ -165,13 +118,7 @@ static int setup_rt_frame_n32(void *sig_return, struct k_sigaction *ka,
|
||||
/* Create the ucontext. */
|
||||
err |= __put_user(0, &frame->rs_uc.uc_flags);
|
||||
err |= __put_user(0, &frame->rs_uc.uc_link);
|
||||
sp = (int) (long) current->sas_ss_sp;
|
||||
err |= __put_user(sp,
|
||||
&frame->rs_uc.uc_stack.ss_sp);
|
||||
err |= __put_user(sas_ss_flags(regs->regs[29]),
|
||||
&frame->rs_uc.uc_stack.ss_flags);
|
||||
err |= __put_user(current->sas_ss_size,
|
||||
&frame->rs_uc.uc_stack.ss_size);
|
||||
err |= __compat_save_altstack(&frame->rs_uc.uc_stack, regs->regs[29]);
|
||||
err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext);
|
||||
err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
|
||||
|
||||
|
@@ -46,20 +46,14 @@
|
||||
* argument. Historically that used to be expensive in Linux. These days
|
||||
* the performance advantage is negligible.
|
||||
*/
|
||||
asmlinkage int sysm_pipe(nabi_no_regargs volatile struct pt_regs regs)
|
||||
asmlinkage int sysm_pipe(void)
|
||||
{
|
||||
int fd[2];
|
||||
int error, res;
|
||||
|
||||
error = do_pipe_flags(fd, 0);
|
||||
if (error) {
|
||||
res = error;
|
||||
goto out;
|
||||
}
|
||||
regs.regs[3] = fd[1];
|
||||
res = fd[0];
|
||||
out:
|
||||
return res;
|
||||
int error = do_pipe_flags(fd, 0);
|
||||
if (error)
|
||||
return error;
|
||||
current_pt_regs()->regs[3] = fd[1];
|
||||
return fd[0];
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE6(mips_mmap, unsigned long, addr, unsigned long, len,
|
||||
@@ -89,43 +83,7 @@ SYSCALL_DEFINE6(mips_mmap2, unsigned long, addr, unsigned long, len,
|
||||
}
|
||||
|
||||
save_static_function(sys_fork);
|
||||
static int __used noinline
|
||||
_sys_fork(nabi_no_regargs struct pt_regs regs)
|
||||
{
|
||||
return do_fork(SIGCHLD, regs.regs[29], 0, NULL, NULL);
|
||||
}
|
||||
|
||||
save_static_function(sys_clone);
|
||||
static int __used noinline
|
||||
_sys_clone(nabi_no_regargs struct pt_regs regs)
|
||||
{
|
||||
unsigned long clone_flags;
|
||||
unsigned long newsp;
|
||||
int __user *parent_tidptr, *child_tidptr;
|
||||
|
||||
clone_flags = regs.regs[4];
|
||||
newsp = regs.regs[5];
|
||||
if (!newsp)
|
||||
newsp = regs.regs[29];
|
||||
parent_tidptr = (int __user *) regs.regs[6];
|
||||
#ifdef CONFIG_32BIT
|
||||
/* We need to fetch the fifth argument off the stack. */
|
||||
child_tidptr = NULL;
|
||||
if (clone_flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) {
|
||||
int __user *__user *usp = (int __user *__user *) regs.regs[29];
|
||||
if (regs.regs[2] == __NR_syscall) {
|
||||
if (get_user (child_tidptr, &usp[5]))
|
||||
return -EFAULT;
|
||||
}
|
||||
else if (get_user (child_tidptr, &usp[4]))
|
||||
return -EFAULT;
|
||||
}
|
||||
#else
|
||||
child_tidptr = (int __user *) regs.regs[8];
|
||||
#endif
|
||||
return do_fork(clone_flags, newsp, 0,
|
||||
parent_tidptr, child_tidptr);
|
||||
}
|
||||
|
||||
SYSCALL_DEFINE1(set_thread_area, unsigned long, addr)
|
||||
{
|
||||
@@ -138,10 +96,10 @@ SYSCALL_DEFINE1(set_thread_area, unsigned long, addr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int mips_atomic_set(struct pt_regs *regs,
|
||||
unsigned long addr, unsigned long new)
|
||||
static inline int mips_atomic_set(unsigned long addr, unsigned long new)
|
||||
{
|
||||
unsigned long old, tmp;
|
||||
struct pt_regs *regs;
|
||||
unsigned int err;
|
||||
|
||||
if (unlikely(addr & 3))
|
||||
@@ -222,6 +180,7 @@ static inline int mips_atomic_set(struct pt_regs *regs,
|
||||
if (unlikely(err))
|
||||
return err;
|
||||
|
||||
regs = current_pt_regs();
|
||||
regs->regs[2] = old;
|
||||
regs->regs[7] = 0; /* No error */
|
||||
|
||||
@@ -235,22 +194,14 @@ static inline int mips_atomic_set(struct pt_regs *regs,
|
||||
: "r" (regs));
|
||||
|
||||
/* unreached. Honestly. */
|
||||
while (1);
|
||||
unreachable();
|
||||
}
|
||||
|
||||
save_static_function(sys_sysmips);
|
||||
static int __used noinline
|
||||
_sys_sysmips(nabi_no_regargs struct pt_regs regs)
|
||||
SYSCALL_DEFINE3(sysmips, long, cmd, long, arg1, long, arg2)
|
||||
{
|
||||
long cmd, arg1, arg2;
|
||||
|
||||
cmd = regs.regs[4];
|
||||
arg1 = regs.regs[5];
|
||||
arg2 = regs.regs[6];
|
||||
|
||||
switch (cmd) {
|
||||
case MIPS_ATOMIC_SET:
|
||||
return mips_atomic_set(®s, arg1, arg2);
|
||||
return mips_atomic_set(arg1, arg2);
|
||||
|
||||
case MIPS_FIXADE:
|
||||
if (arg1 & ~3)
|
||||
|
Referens i nytt ärende
Block a user