diff options
| author | Al Viro <viro@zeniv.linux.org.uk> | 2012-12-25 19:09:45 -0500 | 
|---|---|---|
| committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-02-03 15:09:23 -0500 | 
| commit | 495dfbf767553980dbd40a19a96a8ca5fa1be616 (patch) | |
| tree | 5c6d499f130f17abad2ee9407272d92e9192879a | |
| parent | 08d32fe504a7670cab3190c624448695adcf70e4 (diff) | |
| download | olio-linux-3.10-495dfbf767553980dbd40a19a96a8ca5fa1be616.tar.xz olio-linux-3.10-495dfbf767553980dbd40a19a96a8ca5fa1be616.zip  | |
generic sys_sigaction() and compat_sys_sigaction()
conditional on OLD_SIGACTION/COMPAT_OLD_SIGACTION
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
| -rw-r--r-- | arch/Kconfig | 11 | ||||
| -rw-r--r-- | include/linux/compat.h | 14 | ||||
| -rw-r--r-- | include/linux/signal.h | 9 | ||||
| -rw-r--r-- | include/linux/syscalls.h | 5 | ||||
| -rw-r--r-- | kernel/signal.c | 78 | 
5 files changed, 117 insertions, 0 deletions
diff --git a/arch/Kconfig b/arch/Kconfig index 3b4a416fc44..e50d3af294d 100644 --- a/arch/Kconfig +++ b/arch/Kconfig @@ -400,4 +400,15 @@ config OLD_SIGSUSPEND3  	help  	  Even weirder antique ABI - three-argument sigsuspend(2) +config OLD_SIGACTION +	bool +	help +	  Architecture has old sigaction(2) syscall.  Nope, not the same +	  as OLD_SIGSUSPEND | OLD_SIGSUSPEND3 - alpha has sigsuspend(2), +	  but fairly different variant of sigaction(2), thanks to OSF/1 +	  compatibility... + +config COMPAT_OLD_SIGACTION +	bool +  source "kernel/gcov/Kconfig" diff --git a/include/linux/compat.h b/include/linux/compat.h index 0d53ab4f79c..e20b8b404ae 100644 --- a/include/linux/compat.h +++ b/include/linux/compat.h @@ -299,6 +299,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; @@ -383,6 +392,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) diff --git a/include/linux/signal.h b/include/linux/signal.h index 0b6878e882d..e28e8d455d6 100644 --- a/include/linux/signal.h +++ b/include/linux/signal.h @@ -269,6 +269,15 @@ struct k_sigaction {  	__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  extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie);  extern void signal_delivered(int sig, siginfo_t *info, struct k_sigaction *ka, struct pt_regs *regs, int stepping); diff --git a/include/linux/syscalls.h b/include/linux/syscalls.h index 1c4938bf901..02b04501278 100644 --- a/include/linux/syscalls.h +++ b/include/linux/syscalls.h @@ -385,6 +385,11 @@ asmlinkage long sys_sigsuspend(old_sigset_t mask);  asmlinkage long sys_sigsuspend(int unused1, int unused2, old_sigset_t mask);  #endif +#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 *, diff --git a/kernel/signal.c b/kernel/signal.c index f3665f3de66..79998f5b0f1 100644 --- a/kernel/signal.c +++ b/kernel/signal.c @@ -3409,6 +3409,84 @@ COMPAT_SYSCALL_DEFINE4(rt_sigaction, int, sig,  #endif  #endif /* !CONFIG_ODD_RT_SIGACTION */ +#ifdef CONFIG_OLD_SIGACTION +SYSCALL_DEFINE3(sigaction, int, sig, +		const struct old_sigaction __user *, act, +	        struct old_sigaction __user *, oact) +{ +	struct k_sigaction new_ka, old_ka; +	int ret; + +	if (act) { +		old_sigset_t mask; +		if (!access_ok(VERIFY_READ, act, sizeof(*act)) || +		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) || +		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer) || +		    __get_user(new_ka.sa.sa_flags, &act->sa_flags) || +		    __get_user(mask, &act->sa_mask)) +			return -EFAULT; +#ifdef __ARCH_HAS_KA_RESTORER +		new_ka.ka_restorer = NULL; +#endif +		siginitset(&new_ka.sa.sa_mask, mask); +	} + +	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + +	if (!ret && oact) { +		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || +		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) || +		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer) || +		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || +		    __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) +			return -EFAULT; +	} + +	return ret; +} +#endif +#ifdef CONFIG_COMPAT_OLD_SIGACTION +COMPAT_SYSCALL_DEFINE3(sigaction, int, sig, +		const struct compat_old_sigaction __user *, act, +	        struct compat_old_sigaction __user *, oact) +{ +	struct k_sigaction new_ka, old_ka; +	int ret; +	compat_old_sigset_t mask; +	compat_uptr_t handler, restorer; + +	if (act) { +		if (!access_ok(VERIFY_READ, act, sizeof(*act)) || +		    __get_user(handler, &act->sa_handler) || +		    __get_user(restorer, &act->sa_restorer) || +		    __get_user(new_ka.sa.sa_flags, &act->sa_flags) || +		    __get_user(mask, &act->sa_mask)) +			return -EFAULT; + +#ifdef __ARCH_HAS_KA_RESTORER +		new_ka.ka_restorer = NULL; +#endif +		new_ka.sa.sa_handler = compat_ptr(handler); +		new_ka.sa.sa_restorer = compat_ptr(restorer); +		siginitset(&new_ka.sa.sa_mask, mask); +	} + +	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL); + +	if (!ret && oact) { +		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) || +		    __put_user(ptr_to_compat(old_ka.sa.sa_handler), +			       &oact->sa_handler) || +		    __put_user(ptr_to_compat(old_ka.sa.sa_restorer), +			       &oact->sa_restorer) || +		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) || +		    __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask)) +			return -EFAULT; +	} +	return ret; +} +#endif +  #ifdef __ARCH_WANT_SYS_SGETMASK  /*  |