diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-24 06:50:11 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-02-24 06:50:11 +0400 |
commit | 9e2d59ad580d590134285f361a0e80f0e98c0207 (patch) | |
tree | f3232be75781484193413f32ec82c21f6d8eb76e /include/linux | |
parent | 5ce1a70e2f00f0bce0cab57f798ca354b9496169 (diff) | |
parent | 235b80226b986dabcbba844968f7807866bd0bfe (diff) | |
download | linux-9e2d59ad580d590134285f361a0e80f0e98c0207.tar.xz |
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()
...
Diffstat (limited to 'include/linux')
-rw-r--r-- | include/linux/compat.h | 50 | ||||
-rw-r--r-- | include/linux/sched.h | 12 | ||||
-rw-r--r-- | include/linux/signal.h | 52 | ||||
-rw-r--r-- | include/linux/syscalls.h | 25 |
4 files changed, 126 insertions, 13 deletions
diff --git a/include/linux/compat.h b/include/linux/compat.h index dec7e2d18875..de095b0462a7 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -68,7 +68,6 @@ #ifndef compat_user_stack_pointer #define compat_user_stack_pointer() current_user_stack_pointer() #endif -#ifdef CONFIG_GENERIC_SIGALTSTACK #ifndef compat_sigaltstack /* we'll need that for MIPS */ typedef struct compat_sigaltstack { compat_uptr_t ss_sp; @@ -76,7 +75,6 @@ typedef struct compat_sigaltstack { compat_size_t ss_size; } compat_stack_t; #endif -#endif #define compat_jiffies_to_clock_t(x) \ (((unsigned long)(x) * COMPAT_USER_HZ) / HZ) @@ -142,6 +140,20 @@ typedef struct { compat_sigset_word sig[_COMPAT_NSIG_WORDS]; } compat_sigset_t; +struct compat_sigaction { +#ifndef __ARCH_HAS_ODD_SIGACTION + compat_uptr_t sa_handler; + compat_ulong_t sa_flags; +#else + compat_ulong_t sa_flags; + compat_uptr_t sa_handler; +#endif +#ifdef __ARCH_HAS_SA_RESTORER + compat_uptr_t sa_restorer; +#endif + compat_sigset_t sa_mask __packed; +}; + /* * These functions operate strictly on struct compat_time* */ @@ -283,6 +295,15 @@ struct compat_robust_list_head { compat_uptr_t list_op_pending; }; +#ifdef CONFIG_COMPAT_OLD_SIGACTION +struct compat_old_sigaction { + compat_uptr_t sa_handler; + compat_old_sigset_t sa_mask; + compat_ulong_t sa_flags; + compat_uptr_t sa_restorer; +}; +#endif + struct compat_statfs; struct compat_statfs64; struct compat_old_linux_dirent; @@ -367,6 +388,11 @@ int get_compat_sigevent(struct sigevent *event, const struct compat_sigevent __user *u_event); long compat_sys_rt_tgsigqueueinfo(compat_pid_t tgid, compat_pid_t pid, int sig, struct compat_siginfo __user *uinfo); +#ifdef CONFIG_COMPAT_OLD_SIGACTION +asmlinkage long compat_sys_sigaction(int sig, + const struct compat_old_sigaction __user *act, + struct compat_old_sigaction __user *oact); +#endif static inline int compat_timeval_compare(struct compat_timeval *lhs, struct compat_timeval *rhs) @@ -401,7 +427,8 @@ asmlinkage long compat_sys_settimeofday(struct compat_timeval __user *tv, asmlinkage long compat_sys_adjtimex(struct compat_timex __user *utp); extern int compat_printk(const char *fmt, ...); -extern void sigset_from_compat(sigset_t *set, compat_sigset_t *compat); +extern void sigset_from_compat(sigset_t *set, const compat_sigset_t *compat); +extern void sigset_to_compat(compat_sigset_t *compat, const sigset_t *set); asmlinkage long compat_sys_migrate_pages(compat_pid_t pid, compat_ulong_t maxnode, const compat_ulong_t __user *old_nodes, @@ -503,7 +530,7 @@ asmlinkage long compat_sys_vmsplice(int fd, const struct compat_iovec __user *, unsigned int nr_segs, unsigned int flags); asmlinkage long compat_sys_open(const char __user *filename, int flags, umode_t mode); -asmlinkage long compat_sys_openat(unsigned int dfd, const char __user *filename, +asmlinkage long compat_sys_openat(int dfd, const char __user *filename, int flags, umode_t mode); asmlinkage long compat_sys_open_by_handle_at(int mountdirfd, struct file_handle __user *handle, @@ -592,6 +619,19 @@ asmlinkage long compat_sys_rt_sigtimedwait(compat_sigset_t __user *uthese, struct compat_timespec __user *uts, compat_size_t sigsetsize); asmlinkage long compat_sys_rt_sigsuspend(compat_sigset_t __user *unewset, compat_size_t sigsetsize); +asmlinkage long compat_sys_rt_sigprocmask(int how, compat_sigset_t __user *set, + compat_sigset_t __user *oset, + compat_size_t sigsetsize); +asmlinkage long compat_sys_rt_sigpending(compat_sigset_t __user *uset, + compat_size_t sigsetsize); +#ifndef CONFIG_ODD_RT_SIGACTION +asmlinkage long compat_sys_rt_sigaction(int, + const struct compat_sigaction __user *, + struct compat_sigaction __user *, + compat_size_t); +#endif +asmlinkage long compat_sys_rt_sigqueueinfo(compat_pid_t pid, int sig, + struct compat_siginfo __user *uinfo); asmlinkage long compat_sys_sysinfo(struct compat_sysinfo __user *info); asmlinkage long compat_sys_ioctl(unsigned int fd, unsigned int cmd, unsigned long arg); @@ -642,13 +682,11 @@ asmlinkage ssize_t compat_sys_process_vm_writev(compat_pid_t pid, asmlinkage long compat_sys_sendfile(int out_fd, int in_fd, compat_off_t __user *offset, compat_size_t count); -#ifdef CONFIG_GENERIC_SIGALTSTACK asmlinkage long compat_sys_sigaltstack(const compat_stack_t __user *uss_ptr, compat_stack_t __user *uoss_ptr); int compat_restore_altstack(const compat_stack_t __user *uss); int __compat_save_altstack(compat_stack_t __user *, unsigned long); -#endif asmlinkage long compat_sys_sched_rr_get_interval(compat_pid_t pid, struct compat_timespec __user *interval); diff --git a/include/linux/sched.h b/include/linux/sched.h index c2182b53dace..0655570c67eb 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2182,7 +2182,6 @@ extern struct sigqueue *sigqueue_alloc(void); extern void sigqueue_free(struct sigqueue *); extern int send_sigqueue(struct sigqueue *, struct task_struct *, int group); extern int do_sigaction(int, struct k_sigaction *, struct k_sigaction *); -extern int do_sigaltstack(const stack_t __user *, stack_t __user *, unsigned long); static inline void restore_saved_sigmask(void) { @@ -2228,6 +2227,17 @@ static inline int sas_ss_flags(unsigned long sp) : on_sig_stack(sp) ? SS_ONSTACK : 0); } +static inline unsigned long sigsp(unsigned long sp, struct ksignal *ksig) +{ + if (unlikely((ksig->ka.sa.sa_flags & SA_ONSTACK)) && ! sas_ss_flags(sp)) +#ifdef CONFIG_STACK_GROWSUP + return current->sas_ss_sp; +#else + return current->sas_ss_sp + current->sas_ss_size; +#endif + return sp; +} + /* * Routines for handling mm_structs */ diff --git a/include/linux/signal.h b/include/linux/signal.h index 0a89ffc48466..a2dcb94ea49d 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h @@ -241,9 +241,6 @@ extern int do_send_sig_info(int sig, struct siginfo *info, struct task_struct *p, bool group); extern int group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p); extern int __group_send_sig_info(int, struct siginfo *, struct task_struct *); -extern long do_rt_tgsigqueueinfo(pid_t tgid, pid_t pid, int sig, - siginfo_t *info); -extern long do_sigpending(void __user *, unsigned long); extern int do_sigtimedwait(const sigset_t *, siginfo_t *, const struct timespec *); extern int sigprocmask(int, sigset_t *, sigset_t *); @@ -252,10 +249,59 @@ extern void __set_current_blocked(const sigset_t *); extern int show_unhandled_signals; extern int sigsuspend(sigset_t *); +struct sigaction { +#ifndef __ARCH_HAS_ODD_SIGACTION + __sighandler_t sa_handler; + unsigned long sa_flags; +#else + unsigned long sa_flags; + __sighandler_t sa_handler; +#endif +#ifdef __ARCH_HAS_SA_RESTORER + __sigrestore_t sa_restorer; +#endif + sigset_t sa_mask; /* mask last for extensibility */ +}; + +struct k_sigaction { + struct sigaction sa; +#ifdef __ARCH_HAS_KA_RESTORER + __sigrestore_t ka_restorer; +#endif +}; + +#ifdef CONFIG_OLD_SIGACTION +struct old_sigaction { + __sighandler_t sa_handler; + old_sigset_t sa_mask; + unsigned long sa_flags; + __sigrestore_t sa_restorer; +}; +#endif + +struct ksignal { + struct k_sigaction ka; + siginfo_t info; + int sig; +}; + extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie); +extern void signal_setup_done(int failed, struct ksignal *ksig, int stepping); extern void signal_delivered(int sig, siginfo_t *info, struct k_sigaction *ka, struct pt_regs *regs, int stepping); extern void exit_signals(struct task_struct *tsk); +/* + * Eventually that'll replace get_signal_to_deliver(); macro for now, + * to avoid nastiness with include order. + */ +#define get_signal(ksig) \ +({ \ + struct ksignal *p = (ksig); \ + p->sig = get_signal_to_deliver(&p->info, &p->ka, \ + signal_pt_regs(), NULL);\ + p->sig > 0; \ +}) + extern struct kmem_cache *sighand_cachep; int unhandled_signal(struct task_struct *tsk, int sig); diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 45e2db270255..313a8e0a6553 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -68,11 +68,11 @@ struct sigaltstack; #include <linux/types.h> #include <linux/aio_abi.h> #include <linux/capability.h> +#include <linux/signal.h> #include <linux/list.h> #include <linux/bug.h> #include <linux/sem.h> #include <asm/siginfo.h> -#include <asm/signal.h> #include <linux/unistd.h> #include <linux/quota.h> #include <linux/key.h> @@ -300,10 +300,8 @@ asmlinkage long sys_personality(unsigned int personality); asmlinkage long sys_sigpending(old_sigset_t __user *set); asmlinkage long sys_sigprocmask(int how, old_sigset_t __user *set, old_sigset_t __user *oset); -#ifdef CONFIG_GENERIC_SIGALTSTACK asmlinkage long sys_sigaltstack(const struct sigaltstack __user *uss, struct sigaltstack __user *uoss); -#endif asmlinkage long sys_getitimer(int which, struct itimerval __user *value); asmlinkage long sys_setitimer(int which, @@ -377,6 +375,27 @@ asmlinkage long sys_init_module(void __user *umod, unsigned long len, asmlinkage long sys_delete_module(const char __user *name_user, unsigned int flags); +#ifdef CONFIG_OLD_SIGSUSPEND +asmlinkage long sys_sigsuspend(old_sigset_t mask); +#endif + +#ifdef CONFIG_OLD_SIGSUSPEND3 +asmlinkage long sys_sigsuspend(int unused1, int unused2, old_sigset_t mask); +#endif + +asmlinkage long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize); + +#ifdef CONFIG_OLD_SIGACTION +asmlinkage long sys_sigaction(int, const struct old_sigaction __user *, + struct old_sigaction __user *); +#endif + +#ifndef CONFIG_ODD_RT_SIGACTION +asmlinkage long sys_rt_sigaction(int, + const struct sigaction __user *, + struct sigaction __user *, + size_t); +#endif asmlinkage long sys_rt_sigprocmask(int how, sigset_t __user *set, sigset_t __user *oset, size_t sigsetsize); asmlinkage long sys_rt_sigpending(sigset_t __user *set, size_t sigsetsize); |