⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ia32_signal.c

📁 广州斯道2410普及版II的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * IA32 Architecture-specific signal handling support. * * Copyright (C) 1999, 2001 Hewlett-Packard Co *	David Mosberger-Tang <davidm@hpl.hp.com> * Copyright (C) 1999 Arun Sharma <arun.sharma@intel.com> * Copyright (C) 2000 VA Linux Co * Copyright (C) 2000 Don Dugger <n0ano@valinux.com> * * Derived from i386 and Alpha versions. */#include <linux/errno.h>#include <linux/kernel.h>#include <linux/mm.h>#include <linux/personality.h>#include <linux/ptrace.h>#include <linux/sched.h>#include <linux/signal.h>#include <linux/smp.h>#include <linux/smp_lock.h>#include <linux/stddef.h>#include <linux/unistd.h>#include <linux/wait.h>#include <asm/uaccess.h>#include <asm/rse.h>#include <asm/sigcontext.h>#include <asm/segment.h>#include <asm/ia32.h>#include "../kernel/sigframe.h"#define A(__x)		((unsigned long)(__x))#define DEBUG_SIG	0#define _BLOCKABLE	(~(sigmask(SIGKILL) | sigmask(SIGSTOP)))#define __IA32_NR_sigreturn            119#define __IA32_NR_rt_sigreturn         173struct sigframe_ia32{       int pretcode;       int sig;       struct sigcontext_ia32 sc;       struct _fpstate_ia32 fpstate;       unsigned int extramask[_IA32_NSIG_WORDS-1];       char retcode[8];};struct rt_sigframe_ia32{       int pretcode;       int sig;       int pinfo;       int puc;       siginfo_t32 info;       struct ucontext_ia32 uc;       struct _fpstate_ia32 fpstate;       char retcode[8];};intcopy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 *from){	unsigned long tmp;	int err;	if (!access_ok(VERIFY_READ, from, sizeof(siginfo_t32)))		return -EFAULT;	err = __get_user(to->si_signo, &from->si_signo);	err |= __get_user(to->si_errno, &from->si_errno);	err |= __get_user(to->si_code, &from->si_code);	if (from->si_code < 0)		err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);	else {		switch (from->si_code >> 16) {		      case __SI_CHLD >> 16:			err |= __get_user(to->si_utime, &from->si_utime);			err |= __get_user(to->si_stime, &from->si_stime);			err |= __get_user(to->si_status, &from->si_status);		      default:			err |= __get_user(to->si_pid, &from->si_pid);			err |= __get_user(to->si_uid, &from->si_uid);			break;		      case __SI_FAULT >> 16:			err |= __get_user(tmp, &from->si_addr);			to->si_addr = (void *) tmp;			break;		      case __SI_POLL >> 16:			err |= __get_user(to->si_band, &from->si_band);			err |= __get_user(to->si_fd, &from->si_fd);			break;			/* case __SI_RT: This is not generated by the kernel as of now.  */		}	}	return err;}intcopy_siginfo_to_user32 (siginfo_t32 *to, siginfo_t *from){	int err;	if (!access_ok(VERIFY_WRITE, to, sizeof(siginfo_t32)))		return -EFAULT;	/* If you change siginfo_t structure, please be sure	   this code is fixed accordingly.	   It should never copy any pad contained in the structure	   to avoid security leaks, but must copy the generic	   3 ints plus the relevant union member.	   This routine must convert siginfo from 64bit to 32bit as well	   at the same time.  */	err = __put_user(from->si_signo, &to->si_signo);	err |= __put_user(from->si_errno, &to->si_errno);	err |= __put_user((short)from->si_code, &to->si_code);	if (from->si_code < 0)		err |= __copy_to_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);	else {		switch (from->si_code >> 16) {		case __SI_CHLD >> 16:			err |= __put_user(from->si_utime, &to->si_utime);			err |= __put_user(from->si_stime, &to->si_stime);			err |= __put_user(from->si_status, &to->si_status);		default:			err |= __put_user(from->si_pid, &to->si_pid);			err |= __put_user(from->si_uid, &to->si_uid);			break;		case __SI_FAULT >> 16:			err |= __put_user((long)from->si_addr, &to->si_addr);			break;		case __SI_POLL >> 16:			err |= __put_user(from->si_band, &to->si_band);			err |= __put_user(from->si_fd, &to->si_fd);			break;		/* case __SI_RT: This is not generated by the kernel as of now.  */		}	}	return err;}static inline voidsigact_set_handler (struct k_sigaction *sa, unsigned int handler, unsigned int restorer){	if (handler + 1 <= 2)		/* SIG_DFL, SIG_IGN, or SIG_ERR: must sign-extend to 64-bits */		sa->sa.sa_handler = (__sighandler_t) A((int) handler);	else		sa->sa.sa_handler = (__sighandler_t) (((unsigned long) restorer << 32) | handler);}asmlinkage longia32_rt_sigsuspend (sigset32_t *uset, unsigned int sigsetsize, struct sigscratch *scr){	extern long ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall);	sigset_t oldset, set;	scr->scratch_unat = 0;	/* avoid leaking kernel bits to user level */	memset(&set, 0, sizeof(&set));	if (sigsetsize > sizeof(sigset_t))		return -EINVAL;	if (copy_from_user(&set.sig, &uset->sig, sigsetsize))		return -EFAULT;	sigdelsetmask(&set, ~_BLOCKABLE);	spin_lock_irq(&current->sigmask_lock);	{		oldset = current->blocked;		current->blocked = set;		recalc_sigpending(current);	}	spin_unlock_irq(&current->sigmask_lock);	/*	 * The return below usually returns to the signal handler.  We need to pre-set the	 * correct error code here to ensure that the right values get saved in sigcontext	 * by ia64_do_signal.	 */	scr->pt.r8 = -EINTR;	while (1) {		current->state = TASK_INTERRUPTIBLE;		schedule();		if (ia64_do_signal(&oldset, scr, 1))			return -EINTR;	}}asmlinkage longia32_sigsuspend (unsigned int mask, struct sigscratch *scr){	return ia32_rt_sigsuspend((sigset32_t *)&mask, sizeof(mask), scr);}asmlinkage longsys32_signal (int sig, unsigned int handler){	struct k_sigaction new_sa, old_sa;	int ret;	sigact_set_handler(&new_sa, handler, 0);	new_sa.sa.sa_flags = SA_ONESHOT | SA_NOMASK;	ret = do_sigaction(sig, &new_sa, &old_sa);	return ret ? ret : IA32_SA_HANDLER(&old_sa);}asmlinkage longsys32_rt_sigaction (int sig, struct sigaction32 *act,		    struct sigaction32 *oact, unsigned int sigsetsize){	struct k_sigaction new_ka, old_ka;	unsigned int handler, restorer;	int ret;	/* XXX: Don't preclude handling different sized sigset_t's.  */	if (sigsetsize != sizeof(sigset32_t))		return -EINVAL;	if (act) {		ret = get_user(handler, &act->sa_handler);		ret |= get_user(new_ka.sa.sa_flags, &act->sa_flags);		ret |= get_user(restorer, &act->sa_restorer);		ret |= copy_from_user(&new_ka.sa.sa_mask, &act->sa_mask, sizeof(sigset32_t));		if (ret)			return -EFAULT;		sigact_set_handler(&new_ka, handler, restorer);	}	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);	if (!ret && oact) {		ret = put_user(IA32_SA_HANDLER(&old_ka), &oact->sa_handler);		ret |= put_user(old_ka.sa.sa_flags, &oact->sa_flags);		ret |= put_user(IA32_SA_RESTORER(&old_ka), &oact->sa_restorer);		ret |= copy_to_user(&oact->sa_mask, &old_ka.sa.sa_mask, sizeof(sigset32_t));	}	return ret;}extern asmlinkage long sys_rt_sigprocmask (int how, sigset_t *set, sigset_t *oset,					   size_t sigsetsize);asmlinkage longsys32_rt_sigprocmask (int how, sigset32_t *set, sigset32_t *oset, unsigned int sigsetsize){	mm_segment_t old_fs = get_fs();	sigset_t s;	long ret;	if (sigsetsize > sizeof(s))		return -EINVAL;	if (set) {		memset(&s, 0, sizeof(s));		if (copy_from_user(&s.sig, set, sigsetsize))			return -EFAULT;	}	set_fs(KERNEL_DS);	ret = sys_rt_sigprocmask(how, set ? &s : NULL, oset ? &s : NULL, sizeof(s));	set_fs(old_fs);	if (ret)		return ret;	if (oset) {		if (copy_to_user(oset, &s.sig, sigsetsize))			return -EFAULT;	}	return 0;}asmlinkage longsys32_sigprocmask (int how, unsigned int *set, unsigned int *oset){	return sys32_rt_sigprocmask(how, (sigset32_t *) set, (sigset32_t *) oset, sizeof(*set));}asmlinkage longsys32_rt_sigtimedwait (sigset32_t *uthese, siginfo_t32 *uinfo, struct timespec32 *uts,		       unsigned int sigsetsize){	extern asmlinkage long sys_rt_sigtimedwait (const sigset_t *, siginfo_t *,						    const struct timespec *, size_t);	extern int copy_siginfo_to_user32 (siginfo_t32 *, siginfo_t *);	mm_segment_t old_fs = get_fs();	struct timespec t;	siginfo_t info;	sigset_t s;	int ret;	if (copy_from_user(&s.sig, uthese, sizeof(sigset32_t)))		return -EFAULT;	if (uts) {		ret = get_user(t.tv_sec, &uts->tv_sec);		ret |= get_user(t.tv_nsec, &uts->tv_nsec);		if (ret)			return -EFAULT;	}	set_fs(KERNEL_DS);	ret = sys_rt_sigtimedwait(&s, &info, &t, sigsetsize);	set_fs(old_fs);	if (ret >= 0 && uinfo) {		if (copy_siginfo_to_user32(uinfo, &info))			return -EFAULT;	}	return ret;}asmlinkage longsys32_rt_sigqueueinfo (int pid, int sig, siginfo_t32 *uinfo){	extern asmlinkage long sys_rt_sigqueueinfo (int, int, siginfo_t *);	extern int copy_siginfo_from_user32 (siginfo_t *to, siginfo_t32 *from);	mm_segment_t old_fs = get_fs();	siginfo_t info;	int ret;	if (copy_siginfo_from_user32(&info, uinfo))		return -EFAULT;	set_fs(KERNEL_DS);	ret = sys_rt_sigqueueinfo(pid, sig, &info);	set_fs(old_fs);	return ret;}asmlinkage longsys32_sigaction (int sig, struct old_sigaction32 *act, struct old_sigaction32 *oact){	struct k_sigaction new_ka, old_ka;	unsigned int handler, restorer;	int ret;	if (act) {		old_sigset32_t mask;		ret = get_user(handler, &act->sa_handler);		ret |= get_user(new_ka.sa.sa_flags, &act->sa_flags);		ret |= get_user(restorer, &act->sa_restorer);		ret |= get_user(mask, &act->sa_mask);		if (ret)			return ret;		sigact_set_handler(&new_ka, handler, restorer);		siginitset(&new_ka.sa.sa_mask, mask);	}	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);	if (!ret && oact) {		ret = put_user(IA32_SA_HANDLER(&old_ka), &oact->sa_handler);		ret |= put_user(old_ka.sa.sa_flags, &oact->sa_flags);		ret |= put_user(IA32_SA_RESTORER(&old_ka), &oact->sa_restorer);		ret |= put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);	}	return ret;}static intsetup_sigcontext_ia32 (struct sigcontext_ia32 *sc, struct _fpstate_ia32 *fpstate,		       struct pt_regs *regs, unsigned long mask){	int  err = 0;	unsigned long flag;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -