Exemplo n.º 1
0
static void
setup_frame(int usig, struct k_sigaction *ka, sigset_t *set, struct exregs_regs *regs)
{
	struct sigframe *frame = get_sigframe(ka, regs, sizeof(*frame));
	unsigned long handler = (unsigned long)ka->sa.sa_handler;
	int err = 0;
	printk_dbg("%s called\n", __func__);

	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
		goto badframe;

	err |= setup_sigcontext(&frame->sc, /*&frame->fpstate,*/ regs, set->sig[0]);

	if (_NSIG_WORDS > 1) {
		err |= __copy_to_user(frame->extramask, &set->sig[1],
				      sizeof(frame->extramask));
	}

	err |= __put_user(handler, &frame->sig_ip);
	printk_dbg("%s frame->sig_ip = %lx\n", __func__, handler);

	if (!err)
		err = setup_return(regs, ka, &frame->retcode, frame,
				&frame->lr, &frame->usig, usig);

	if (err)
		goto badframe;

	regs->ip = TASK_SIG_BASE;
	switch (regs->syscall_action)
	{
	case 1:	/* Syscall */
		regs->ip += ((unsigned long)&__wombat_user_sigentry) & ~PAGE_MASK;
		break;
	case 0:	/* Fault */
	case 2:	/* Restart syscall */
		regs->ip += ((unsigned long)&__wombat_user_sigentry_restart) & ~PAGE_MASK;
		break;
	case 4:	/* Interrupt syscall */
		regs->ip += ((unsigned long)&__wombat_user_sigentry_int) & ~PAGE_MASK;
		break;
	default:
		BUG();
	}

	set_need_restart(current_thread_info(), regs->ip,
			regs->sp, regs->flags);

	printk_dbg("SIG deliver (%s:%d:%lx): sp=%p pc=%p\n",
			current->comm, current->pid,
			current_thread_info()->user_tid.raw,
			frame, (void*)regs->ip);

	return;

badframe:
	force_sigsegv(usig, current);
	return;
}
Exemplo n.º 2
0
asmlinkage int
sys_rt_sigsuspend(sigset_t *unewset, size_t sigsetsize, struct pt_regs *regs)
{
	sigset_t saveset, newset;
	printk_dbg("XXX - %s() called\n", __func__);

	/* XXX: Don't preclude handling different sized sigset_t's. */
	if (sigsetsize != sizeof(sigset_t))
		return -EINVAL;

	if (copy_from_user(&newset, unewset, sizeof(newset)))
		return -EFAULT;
	sigdelsetmask(&newset, ~_BLOCKABLE);

	spin_lock_irq(&current->sighand->siglock);
	saveset = current->blocked;
	current->blocked = newset;
	recalc_sigpending();
	spin_unlock_irq(&current->sighand->siglock);
	ARM_put_r0(regs, -ERESTART_RESTARTBLOCK);

	while (1) {
		current->state = TASK_INTERRUPTIBLE;
		schedule();
		if (l4_do_signal(&saveset, regs, 1))
			return ARM_r0(regs);
	}
}
Exemplo n.º 3
0
asmlinkage int 
sys_sigaction(int sig, const struct old_sigaction *act,
	      struct old_sigaction *oact)
{
	struct k_sigaction new_ka, old_ka;
	int ret;

	printk_dbg("XXX - %s() called\n", __func__);

	if (act) {
		old_sigset_t mask;
		if (verify_area(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))
			return -EFAULT;
		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
		__get_user(mask, &act->sa_mask);
		siginitset(&new_ka.sa.sa_mask, mask);
	}

	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);

	if (!ret && oact) {
		if (verify_area(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))
			 return -EFAULT;
		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
	}

	return ret;
}
Exemplo n.º 4
0
static int
restore_sigcontext(struct sigcontext *sc)
{
	int err = 0;
	struct exregs_regs regs;
	struct restore_sigframe __user *restore;
	
	printk_dbg("%s called\n", __func__);

	/* User registers are saved/restored in user.S (__wombat_user_xxx) */
	__get_user_error(regs.sp, &sc->arm_sp, err);
	__get_user_error(regs.ip, &sc->arm_pc, err);
	__get_user_error(regs.flags, &sc->arm_cpsr, err);

	restore = (void*)(regs.sp - sizeof(struct restore_sigframe));

	__put_user_error(regs.ip, &restore->ret_ip, err);

	if (!err) {
		set_need_restart(current_thread_info(),
				(unsigned long)TASK_SIG_BASE +
				(((unsigned long)&__wombat_user_sigrestore) & ~PAGE_MASK),
				(unsigned long)sc, regs.flags);

		L4_Stop_Thread(current_thread_info()->user_tid);
		set_user_ipc_cancelled(current_thread_info());
	}

	return err;
}
Exemplo n.º 5
0
static inline void *
get_sigframe(struct k_sigaction *ka, struct exregs_regs *regs, int framesize)
{
	unsigned long sp = regs->sp;
	printk_dbg("%s called\n", __func__);

	/*
	 * This is the X/Open sanctioned signal stack switching.
	 */
	if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
		sp = current->sas_ss_sp + current->sas_ss_size;

	/*
	 * ATPCS B01 mandates 8-byte alignment
	 */
	return (void *)((sp - framesize) & ~7);
}
Exemplo n.º 6
0
asmlinkage int sys_sigreturn(struct pt_regs *regs)
{
	struct sigframe *frame;
	sigset_t set;

	printk_dbg("XXX - %s() called\n", __func__);

	/* Always make any pending restarted system calls return -EINTR */
	current_thread_info()->restart_block.fn = do_no_restart_syscall;

        /*
	 * Since we stacked the signal on a 64-bit boundary,
	 * then 'sp' should be word aligned here.  If it's
	 * not, then the user is trying to mess with us.
	 */
	if (ARM_sp(regs) & 7)
		goto badframe;

	frame = (struct sigframe *)ARM_sp(regs);

	if (verify_area(VERIFY_READ, frame, sizeof (*frame)))
		goto badframe;
	if (__get_user(set.sig[0], &frame->sc.oldmask)
		|| (_NSIG_WORDS > 1
		&& __copy_from_user(&set.sig[1], &frame->extramask,
			sizeof(frame->extramask))))
		goto badframe;

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

	if (restore_sigcontext(&frame->sc))
		goto badframe;

	return ARM_r0(regs);

badframe:
	force_sig(SIGSEGV, current);
	return 0;
}
Exemplo n.º 7
0
/*
 * atomically swap in the new signal mask, and wait for a signal.
 */
asmlinkage int sys_sigsuspend(int restart, unsigned long oldmask, old_sigset_t mask, struct pt_regs *regs)
{
	sigset_t saveset;

	printk_dbg("XXX - %s() called\n", __func__);

	mask &= _BLOCKABLE;
	spin_lock_irq(&current->sighand->siglock);
	saveset = current->blocked;
	siginitset(&current->blocked, mask);
	recalc_sigpending();
	spin_unlock_irq(&current->sighand->siglock);
	ARM_put_r0(regs, -ERESTART_RESTARTBLOCK);

	while (1) {
		current->state = TASK_INTERRUPTIBLE;
		schedule();
		if (l4_do_signal(&saveset, regs, 1))
			return ARM_r0(regs);
	}
}
Exemplo n.º 8
0
void l4_arch_setup_frame(int signr, struct k_sigaction * ka, siginfo_t *info,
		                sigset_t *set, struct exregs_regs *regs)
{
	struct thread_info *thread = current_thread_info();
	int usig = signr;

	/*
	 * translate the signal
	 */
	if (usig < 32 && thread->exec_domain && thread->exec_domain->signal_invmap)
		usig = thread->exec_domain->signal_invmap[usig];

	printk_dbg("%s %d\n", __func__, usig);

	if (regs->syscall_action == 2) /* restart syscall */
		regs->ip -= 4;
	/*
	 * Set up the stack frame
	 */
	if (ka->sa.sa_flags & SA_SIGINFO)
		setup_rt_frame(usig, ka, info, set, regs);
	else
		setup_frame(usig, ka, set, regs);
}
Exemplo n.º 9
0
/*
 *	subbuf_splice_actor - splice up to one subbuf's worth of data
 */
static int subbuf_splice_actor(struct file *in,
			       loff_t *ppos,
			       struct pipe_inode_info *pipe,
			       size_t len,
			       unsigned int flags,
			       struct lib_ring_buffer *buf)
{
	struct channel *chan = buf->backend.chan;
	const struct lib_ring_buffer_config *config = &chan->backend.config;
	unsigned int poff, subbuf_pages, nr_pages;
	struct page *pages[PIPE_DEF_BUFFERS];
	struct partial_page partial[PIPE_DEF_BUFFERS];
	struct splice_pipe_desc spd = {
		.pages = pages,
		.nr_pages = 0,
		.partial = partial,
#if (LINUX_VERSION_CODE < KERNEL_VERSION(4,12,0))
		.flags = flags,
#endif
		.ops = &ring_buffer_pipe_buf_ops,
		.spd_release = lib_ring_buffer_page_release,
	};
	unsigned long consumed_old, roffset;
	unsigned long bytes_avail;

	/*
	 * Check that a GET_SUBBUF ioctl has been done before.
	 */
	WARN_ON(atomic_long_read(&buf->active_readers) != 1);
	consumed_old = lib_ring_buffer_get_consumed(config, buf);
	consumed_old += *ppos;

	/*
	 * Adjust read len, if longer than what is available.
	 * Max read size is 1 subbuffer due to get_subbuf/put_subbuf for
	 * protection.
	 */
	bytes_avail = chan->backend.subbuf_size;
	WARN_ON(bytes_avail > chan->backend.buf_size);
	len = min_t(size_t, len, bytes_avail);
	subbuf_pages = bytes_avail >> PAGE_SHIFT;
	nr_pages = min_t(unsigned int, subbuf_pages, PIPE_DEF_BUFFERS);
	roffset = consumed_old & PAGE_MASK;
	poff = consumed_old & ~PAGE_MASK;
	printk_dbg(KERN_DEBUG "SPLICE actor len %zu pos %zd write_pos %ld\n",
		   len, (ssize_t)*ppos, lib_ring_buffer_get_offset(config, buf));

	for (; spd.nr_pages < nr_pages; spd.nr_pages++) {
		unsigned int this_len;
		unsigned long *pfnp, new_pfn;
		struct page *new_page;
		void **virt;

		if (!len)
			break;
		printk_dbg(KERN_DEBUG "SPLICE actor loop len %zu roffset %ld\n",
			   len, roffset);

		/*
		 * We have to replace the page we are moving into the splice
		 * pipe.
		 */
		new_page = alloc_pages_node(cpu_to_node(max(buf->backend.cpu,
							    0)),
					    GFP_KERNEL | __GFP_ZERO, 0);
		if (!new_page)
			break;
		new_pfn = page_to_pfn(new_page);
		this_len = PAGE_SIZE - poff;
		pfnp = lib_ring_buffer_read_get_pfn(&buf->backend, roffset, &virt);
		spd.pages[spd.nr_pages] = pfn_to_page(*pfnp);
		*pfnp = new_pfn;
		*virt = page_address(new_page);
		spd.partial[spd.nr_pages].offset = poff;
		spd.partial[spd.nr_pages].len = this_len;

		poff = 0;
		roffset += PAGE_SIZE;
		len -= this_len;
	}

	if (!spd.nr_pages)
		return 0;

	return wrapper_splice_to_pipe(pipe, &spd);
}

ssize_t lib_ring_buffer_splice_read(struct file *in, loff_t *ppos,
				    struct pipe_inode_info *pipe, size_t len,
				    unsigned int flags,
				    struct lib_ring_buffer *buf)
{
	struct channel *chan = buf->backend.chan;
	const struct lib_ring_buffer_config *config = &chan->backend.config;
	ssize_t spliced;
	int ret;

	if (config->output != RING_BUFFER_SPLICE)
		return -EINVAL;

	/*
	 * We require ppos and length to be page-aligned for performance reasons
	 * (no page copy). Size is known using the ioctl
	 * RING_BUFFER_GET_PADDED_SUBBUF_SIZE, which is page-size padded.
	 * We fail when the ppos or len passed is not page-sized, because splice
	 * is not allowed to copy more than the length passed as parameter (so
	 * the ABI does not let us silently copy more than requested to include
	 * padding).
	 */
	if (*ppos != PAGE_ALIGN(*ppos) || len != PAGE_ALIGN(len))
		return -EINVAL;

	ret = 0;
	spliced = 0;

	printk_dbg(KERN_DEBUG "SPLICE read len %zu pos %zd\n", len,
		   (ssize_t)*ppos);
	while (len && !spliced) {
		ret = subbuf_splice_actor(in, ppos, pipe, len, flags, buf);
		printk_dbg(KERN_DEBUG "SPLICE read loop ret %d\n", ret);
		if (ret < 0)
			break;
		else if (!ret) {
			if (flags & SPLICE_F_NONBLOCK)
				ret = -EAGAIN;
			break;
		}

		*ppos += ret;
		if (ret > len)
			len = 0;
		else
			len -= ret;
		spliced += ret;
	}

	if (spliced)
		return spliced;

	return ret;
}
EXPORT_SYMBOL_GPL(lib_ring_buffer_splice_read);

ssize_t vfs_lib_ring_buffer_splice_read(struct file *in, loff_t *ppos,
				    struct pipe_inode_info *pipe, size_t len,
				    unsigned int flags)
{
	struct lib_ring_buffer *buf = in->private_data;

	return lib_ring_buffer_splice_read(in, ppos, pipe, len, flags, buf);
}
EXPORT_SYMBOL_GPL(vfs_lib_ring_buffer_splice_read);
Exemplo n.º 10
0
asmlinkage int
sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss, struct pt_regs *regs)
{
	printk_dbg("XXX - %s() called\n", __func__);
	return do_sigaltstack(uss, uoss, ARM_sp(regs));
}
Exemplo n.º 11
0
static void
setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
	       sigset_t *set, struct exregs_regs *regs)
{
	struct rt_sigframe *frame = get_sigframe(ka, regs, sizeof(*frame));
	unsigned long handler = (unsigned long)ka->sa.sa_handler;
	int err = 0;
	printk_dbg("%s called\n", __func__);

	if (!access_ok(VERIFY_WRITE, frame, sizeof (*frame)))
		goto badframe;

	__put_user_error(&frame->info, &frame->pinfo, err);
	__put_user_error(&frame->uc, &frame->puc, err);
	err |= copy_siginfo_to_user(&frame->info, info);

	/* Clear all the bits of the ucontext we don't use.  */
	err |= clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext));

	err |= setup_sigcontext(&frame->uc.uc_mcontext, /*&frame->fpstate,*/
				regs, set->sig[0]);
	err |= copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));

	err |= __put_user(handler, &frame->sig_ip);
	printk_dbg("%s frame->sig_ip = %lx\n", __func__, handler);

	if (!err)
		err = setup_return(regs, ka, &frame->retcode, frame,
				&frame->lr, &frame->usig, usig);

	if (!err) {
		/*
		 * For realtime signals we must also set the second and third
		 * arguments for the signal handler.
		 *   -- Peter Maydell <*****@*****.**> 2000-12-06
		 */
//		ARM_put_r1(regs, (unsigned long)frame->pinfo);
//		ARM_put_r2(regs, (unsigned long)frame->puc);
	}

	if (err)
		goto badframe;

	regs->ip = TASK_SIG_BASE;
	switch (regs->syscall_action)
	{
	case 1:	/* Syscall */
		regs->ip += ((unsigned long)&__wombat_user_rt_sigentry) & ~PAGE_MASK;
		break;
	case 0:	/* Fault */
	case 2:	/* Restart syscall */
		regs->ip += ((unsigned long)&__wombat_user_rt_sigentry_restart) & ~PAGE_MASK;
		break;
	case 4:	/* Interrupt syscall */
		regs->ip += ((unsigned long)&__wombat_user_rt_sigentry_int) & ~PAGE_MASK;
		break;
	default:
		BUG();
	}

	set_need_restart(current_thread_info(), regs->ip,
			regs->sp, regs->flags);

	printk_dbg("SIG rt deliver (%s:%d:%lx): sp=%p pc=%p\n",
			current->comm, current->pid,
			current_thread_info()->user_tid.raw,
			frame, (void*)regs->ip);

	return;

badframe:
	force_sigsegv(usig, current);
	return;
}
Exemplo n.º 12
0
static int
setup_return(struct exregs_regs *regs, struct k_sigaction *ka,
	     unsigned long __user *rc, void __user *frame,
	     unsigned long __user *lr, int __user *sig,
	     int usig)
{
	unsigned long retcode;
	int thumb = 0;

	unsigned long cpsr = regs->flags & ~PSR_f;
	unsigned long handler = (unsigned long)ka->sa.sa_handler;

	/*
	 * Maybe we need to deliver a 32-bit signal to a 26-bit task.
	 */
	if (ka->sa.sa_flags & SA_THIRTYTWO)
		cpsr = (cpsr & ~MODE_MASK) | USR_MODE;

	/* Thumb mode tests */
	/*
	 * The LSB of the handler determines if we're going to
	 * be using THUMB or ARM mode for this signal handler.
	 */
	thumb = handler & 1;

	if (thumb)
		cpsr |= PSR_T_BIT;
	else
		cpsr &= ~PSR_T_BIT;

	if (thumb)
	{
		printk("%d: Thumb mode handlers not suppoted\n", current->pid);
		return 1;
	}

	if (ka->sa.sa_flags & SA_RESTORER) {
		retcode = (unsigned long)ka->sa.sa_restorer;
	} else {
		unsigned int idx = thumb << 1;

		if (ka->sa.sa_flags & SA_SIGINFO)
			idx += 3;

		if (__put_user(sigreturn_codes[idx], rc) ||
		    __put_user(sigreturn_codes[idx+1], rc+1))
			return 1;

		/*
		 * Ensure that the instruction cache sees
		 * the return code written onto the stack.
		 */
		flush_icache_range((unsigned long)rc,
				   (unsigned long)(rc + 1));

		retcode = ((unsigned long)rc) + thumb;
	}
	if (__put_user(usig, sig))
		return 1;
	if (__put_user(retcode, lr))
		return 1;
	printk_dbg("%s %d restorer = %lx, frame = %p\n", __func__, __LINE__, retcode, frame);

	regs->sp = (unsigned long)frame;
	regs->flags = cpsr;

//	ARM_put_r0(regs, usig);
//	ARM_put_lr(regs, retcode);
	return 0;
}