Exemplo n.º 1
0
/*
 * Because contexts contain tagged capabilities, we can't just use memcpy()
 * on the data structure.  Once the C compiler knows about capabilities, then
 * direct structure assignment should be plausible.  In the mean time, an
 * explicit capability context copy routine is required.
 *
 * XXXRW: Compiler should know how to do copies of tagged capabilities.
 *
 * XXXRW: Compiler should be providing us with the temporary register.
 */
void
cheri_capability_copy(struct chericap *cp_to, struct chericap *cp_from)
{

	cheri_capability_load(CHERI_CR_CTEMP0, cp_from);
	cheri_capability_store(CHERI_CR_CTEMP0, cp_to);
}
Exemplo n.º 2
0
/*
 * If a signal is delivered while in a sandbox, forceably unwind the trusted
 * stack simulating a CReturn.  Clear the regular and capability register
 * files.
 *
 * When a signal is thrown in a sandbox, one option is for the kernel to
 * forceably unwind the stack by a frame.
 *
 * Note that the callee has not had a chance to clean up the mess -- and
 * particular, can't clear the register file before returning.  We therefore
 * have to do that for the callee or information/rights may leak!.
 *
 * XXXRW: Really we want to delegate this to userspace via SIGSANDBOX or
 * similar, but in the mean time.
 *
 * XXXRW: We don't yet handle floating point.
 */
int
cheri_stack_sandboxexception(struct thread *td, struct trapframe *tf,
    int signum)
{
	struct cheri_stack_frame *csfp;
	struct pcb *pcb = td->td_pcb;
	register_t s, sr, badvaddr, cause;
	f_register_t fsr;

	if (pcb->pcb_cheristack.cs_tsp == CHERI_STACK_SIZE)
		return (0);

	printf("%s: processing sandbox exception signal %d, pid %d\n",
	    __func__, signum, td->td_proc->p_pid);

#if DDB
	if (security_cheri_debugger_on_sandbox_exception)
		kdb_enter(KDB_WHY_CHERI, "CHERI sandbox exception");
#endif

	/*
	 * XXXRW: It is my belief that the trap frame in a thread is always a
	 * pointer to the PCB.  Check this is true, however, because I rely on
	 * it.
	 */
	KASSERT(td->td_frame == &pcb->pcb_regs,
	    ("%s: td_frame != pcb_regs", __func__));
	KASSERT(td->td_frame == tf, ("%s: td_frame != tf", __func__));

	/*
	 * XXXRW: It would actually be quite nice to print out some exception
	 * information here.  Otherwise all the state required to debug the
	 * sandbox failure will be lost.
	 *
	 * XXXRW: Or, has it all been sent to printf?
	 *
	 * XXXRW: Or, maybe that is actually a bad thing, since printf is
	 * quite slow and noisy, and not something we want to do on every
	 * sandbox failure.
	 */

	/*
	 * Clear the regular and capability register files to ensure no state
	 * (information, rights) is returned to the caller that shouldn't be
	 * when the callee exits unexpectedly.  Save and restore kernel-side
	 * registers, however.
	 *
	 * XXXRW: What about floating-point registers?
	 */
	sr = pcb->pcb_regs.sr;
	badvaddr = pcb->pcb_regs.badvaddr;
	cause = pcb->pcb_regs.cause;
	fsr = pcb->pcb_regs.fsr;
	bzero(&pcb->pcb_regs, sizeof(pcb->pcb_regs));
	bzero(&pcb->pcb_cheriframe, sizeof(pcb->pcb_cheriframe));
	pcb->pcb_regs.sr = sr;
	pcb->pcb_regs.badvaddr = badvaddr;
	pcb->pcb_regs.cause = cause;
	pcb->pcb_regs.fsr = fsr;

	/*
	 * Reproduce CReturn.
	 */
	csfp = &pcb->pcb_cheristack.cs_frames[pcb->pcb_cheristack.cs_tsp /
	    CHERI_FRAME_SIZE];
	pcb->pcb_cheristack.cs_tsp += CHERI_FRAME_SIZE;

	/*
	 * Pop IDC, PCC.
	 */
	s = intr_disable();
	cheri_capability_load(CHERI_CR_CTEMP, &csfp->csf_idc);
	cheri_capability_store(CHERI_CR_CTEMP, &pcb->pcb_cheriframe.cf_idc);
	cheri_capability_load(CHERI_CR_CTEMP, &csfp->csf_pcc);
	cheri_capability_store(CHERI_CR_CTEMP, &pcb->pcb_cheriframe.cf_pcc);
	intr_restore(s);

	/*
	 * Pop SP, PC (+4 already done).
	 */
	pcb->pcb_regs.sp = csfp->csf_sp;
	pcb->pcb_regs.pc = csfp->csf_pc;

	/*
	 * Set 'v0' to -1, and 'v1' to the signal number so that the consumer
	 * of CCall can handle the error.
	 *
	 * XXXRW: That isn't really quite what we want, however.  What about
	 * CCall failures themselves, and what if CReturn returns a -1 -- how
	 * should the caller interpret that?
	 */
	pcb->pcb_regs.v0 = -1;
	pcb->pcb_regs.v1 = signum;
	return (1);
}