[DTrace-devel] [PATCH 2/2] Handle BPF_send_signal() return value

Kris Van Hees kris.van.hees at oracle.com
Wed Apr 20 02:31:19 UTC 2022


Now that we have ERROR probe support, we can revisit this.

The following failures can be reported (with suggested faults):

EAGAIN	-> try again (some transient condition)
	   Should be reported as DTRACEFLT_UNKNOWN
EBUSY	-> cannot add signal to the work queue
	   Should be reported as DTRACEFLT_ILLOP
EINVAL	-> invalid signal value (only one that legacy DTrace reported on)
	   Should be reported as DTRACEFLT_ILLOP
EPERM	-> not allowed
	   Should be reported as DTRACEFLT_KPRIV

On Fri, Jul 17, 2020 at 03:00:06PM -0400, eugene.loh at oracle.com wrote:
> From: Eugene Loh <eugene.loh at oracle.com>
> 
> Handle the return value of BPF_send_signal(), which is used to
> implement raise().  Specifically, if the value is nonzero, store
> it in dctx->mst->fault and jump to the exit label.
> 
> This patch is separate from the previous one, which introduced
> raise() support, for the purpose of code review.  It can be
> squashed into that previous patch if both patches are accepted.
> 
> Signed-off-by: Eugene Loh <eugene.loh at oracle.com>
> ---
>  libdtrace/dt_cg.c | 30 ++++++++++++++++++++++++++++++
>  1 file changed, 30 insertions(+)
> 
> diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
> index e78491b7..4413e80b 100644
> --- a/libdtrace/dt_cg.c
> +++ b/libdtrace/dt_cg.c
> @@ -701,6 +701,8 @@ dt_cg_act_raise(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind)
>  	struct bpf_insn	instr;
>  	dt_irlist_t	*dlp = &pcb->pcb_ir;
>  	dt_regset_t	*drp = pcb->pcb_regs;
> +	uint_t		lbl_zero = dt_irlist_label(dlp);
> +	int		r;
>  
>  	dt_cg_node(dnp->dn_args, &pcb->pcb_ir, drp);
>  
> @@ -713,6 +715,34 @@ dt_cg_act_raise(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind)
>  	instr = BPF_CALL_HELPER(BPF_FUNC_send_signal);
>  	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
>  	dt_regset_free_args(drp);
> +
> +	/*
> +	 * if (send_signal() != 0) {
> +	 *     // lddw %r, [%fp + DT_STK_DCTX]
> +	 *     // lddw %r, [%r + DCTX_MST]
> +	 *     // stdw [%r + DMST_FAULT], %r0
> +	 *     dctx->mst->fault = r0;
> +	 *     exit;
> +	 * }
> +	 *
> +	 * Note that we need a temporary register.
> +	 * Since we know %r1-%r5 are free, we could just use
> +	 * r=BPF_REG_1 and dispense with the dt_regset_free(drp,r).
> +	 */
> +	instr = BPF_BRANCH_IMM(BPF_JEQ, BPF_REG_0, 0, lbl_zero);
> +	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
> +	if ((r = dt_regset_alloc(drp)) == -1)
> +		longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
> +	instr = BPF_LOAD(BPF_DW, r, BPF_REG_FP, DT_STK_DCTX);
> +	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
> +	instr = BPF_LOAD(BPF_DW, r, r, DCTX_MST);
> +	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
> +	instr = BPF_STORE(BPF_DW, r, DMST_FAULT, BPF_REG_0);
> +	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
> +	dt_regset_free(drp, r);
> +	instr = BPF_JUMP(pcb->pcb_exitlbl);
> +	dt_irlist_append(dlp, dt_cg_node_alloc(DT_LBL_NONE, instr));
> +	dt_irlist_append(dlp, dt_cg_node_alloc(lbl_zero, BPF_NOP()));
>  	dt_regset_free(drp, BPF_REG_0);
>  }
>  
> -- 
> 2.18.2
> 
> 
> _______________________________________________
> DTrace-devel mailing list
> DTrace-devel at oss.oracle.com
> https://oss.oracle.com/mailman/listinfo/dtrace-devel



More information about the DTrace-devel mailing list