[DTrace-devel] [PATCH] cg, sdt: copy userspace string arguments to kernelspace

Kris Van Hees kris.van.hees at oracle.com
Tue Feb 28 08:20:11 UTC 2023


When an SDT probe argument is provided by a userspace string, it must be
copied to kernelspace because SDT probe pointer arguments are expected
to be kernel addresses.

Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
 libdtrace/dt_cg.c          | 31 +++++++++++++++++++++++++++++++
 libdtrace/dt_probe.c       |  1 +
 libdtrace/dt_prov_proc.c   | 38 +++++++++++++++++++-------------------
 libdtrace/dt_provider.h    |  1 +
 libdtrace/dt_provider_tp.c |  1 +
 5 files changed, 53 insertions(+), 19 deletions(-)

diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 2c4648df..be0215d7 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -4132,6 +4132,7 @@ dt_cg_array_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 	dt_ident_t	*fidp = dt_dlib_get_func(yypcb->pcb_hdl, "dt_get_bvar");
 	size_t		size;
 	int		n;
+	int		ustr = 0;
 
 	assert(dnp->dn_kind == DT_NODE_VAR);
 	assert(!(idp->di_flags & (DT_IDFLG_TLS | DT_IDFLG_LOCAL)));
@@ -4155,6 +4156,12 @@ dt_cg_array_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 			dnp->dn_reg = -1;
 			return;
 		}
+
+		/*
+		 * If the argument node is mark DT_NF_USERLAND, it is a string
+		 * in userspace.  Set a flag to indicate we need to copy it.
+		 */
+		ustr = prp->xargv[saved]->dn_flags & DT_NF_USERLAND;
 		dnp->dn_args->dn_value = prp->mapping[saved];
 	}
 
@@ -4201,6 +4208,30 @@ dt_cg_array_op(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
 	emit(dlp, BPF_MOV_REG(dnp->dn_reg, BPF_REG_0));
 	dt_regset_free(drp, BPF_REG_0);
 
+	if (dt_node_is_string(dnp) && ustr) {
+		dtrace_hdl_t    *dtp = yypcb->pcb_hdl;
+
+		dt_regset_xalloc(drp, BPF_REG_0);
+
+		emit(dlp,  BPF_MOV_REG(BPF_REG_0, dnp->dn_reg));
+		dt_cg_tstring_alloc(yypcb, dnp);
+		emit(dlp,  BPF_LOAD(BPF_DW, dnp->dn_reg, BPF_REG_FP, DT_STK_DCTX));
+		emit(dlp,  BPF_LOAD(BPF_DW, dnp->dn_reg, dnp->dn_reg, DCTX_MEM));
+		emit(dlp,  BPF_ALU64_IMM(BPF_ADD, dnp->dn_reg, dnp->dn_tstring->dn_value));
+
+		if (dt_regset_xalloc_args(drp) == -1)
+			longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+
+		emit(dlp,  BPF_MOV_REG(BPF_REG_1, dnp->dn_reg));
+		emit(dlp,  BPF_MOV_IMM(BPF_REG_2, dtp->dt_options[DTRACEOPT_STRSIZE]));
+		emit(dlp,  BPF_MOV_REG(BPF_REG_3, BPF_REG_0));
+		emit(dlp,  BPF_CALL_HELPER(dtp->dt_bpfhelper[BPF_FUNC_probe_read_user_str]));
+
+		dt_regset_free_args(drp);
+		dt_regset_free(drp, BPF_REG_0);
+		return;
+	}
+
 	/*
 	 * If this is a reference to the args[] array, we need to take the
 	 * additional step of explicitly eliminating any bits larger than the
diff --git a/libdtrace/dt_probe.c b/libdtrace/dt_probe.c
index dfcd28a8..5cf5fe27 100644
--- a/libdtrace/dt_probe.c
+++ b/libdtrace/dt_probe.c
@@ -951,6 +951,7 @@ dt_probe_args_info(dtrace_hdl_t *dtp, dt_probe_t *prp)
 
 		prp->mapping[i] = argv[i].mapping;
 		prp->argv[i] = dtt;
+		prp->xargv[i]->dn_flags |= argv[i].flags;
 	}
 
 	dt_free(dtp, argv);
diff --git a/libdtrace/dt_prov_proc.c b/libdtrace/dt_prov_proc.c
index 57753b94..4544f594 100644
--- a/libdtrace/dt_prov_proc.c
+++ b/libdtrace/dt_prov_proc.c
@@ -82,32 +82,32 @@ typedef struct probe_arg {
  * that provides no arguments.
  */
 static probe_arg_t probe_args[] = {
-	{ "create", 0, { 0, "struct task_struct *", "psinfo_t *" } },
-	{ "exec", 0, { 0, "string", } },
-	{ "exec-failure", 0, { 0, "int", } },
+	{ "create", 0, { 0, 0, "struct task_struct *", "psinfo_t *" } },
+	{ "exec", 0, { 0, DT_NF_USERLAND, "string", } },
+	{ "exec-failure", 0, { 0, 0, "int", } },
 	{ "exec-success", },
-	{ "exit", 0, { 0, "int", } },
+	{ "exit", 0, { 0, 0, "int", } },
 #if 0
-	{ "fault", 0, { 0, "int", } },
-	{ "fault", 1, { 1, "siginfo_t *", } },
+	{ "fault", 0, { 0, 0, "int", } },
+	{ "fault", 1, { 1, 0, "siginfo_t *", } },
 #endif
-	{ "lwp-create", 0, { 0, "struct task_struct *", "lwpsinfo_t *" } },
-	{ "lwp-create", 1, { 0, "struct task_struct *", "psinfo_t *" } },
+	{ "lwp-create", 0, { 0, 0, "struct task_struct *", "lwpsinfo_t *" } },
+	{ "lwp-create", 1, { 0, 0, "struct task_struct *", "psinfo_t *" } },
 	{ "lwp-exit", },
 	{ "lwp-start", },
 #if 0
-	{ "signal-clear", 0, { 0, "int", } },
-	{ "signal-clear", 1, { 1, "siginfo_t *", } },
+	{ "signal-clear", 0, { 0, 0, "int", } },
+	{ "signal-clear", 1, { 1, 0, "siginfo_t *", } },
 #endif
-	{ "signal-discard", 0, { 0, "struct task_struct *", "lwpsinfo_t *" } },
-	{ "signal-discard", 1, { 0, "struct task_struct *", "psinfo_t *" } },
-	{ "signal-discard", 2, { 1, "int", } },
-	{ "signal-handle", 0, { 0, "int", } },
-	{ "signal-handle", 1, { 1, "siginfo_t *", } },
-	{ "signal-handle", 2, { 2, "void (*)(void)", } },
-	{ "signal-send", 0, { 0, "struct task_struct *", "lwpsinfo_t *" } },
-	{ "signal-send", 1, { 0, "struct task_struct *", "psinfo_t *" } },
-	{ "signal-send", 2, { 1, "int", } },
+	{ "signal-discard", 0, { 0, 0, "struct task_struct *", "lwpsinfo_t *" } },
+	{ "signal-discard", 1, { 0, 0, "struct task_struct *", "psinfo_t *" } },
+	{ "signal-discard", 2, { 1, 0, "int", } },
+	{ "signal-handle", 0, { 0, 0, "int", } },
+	{ "signal-handle", 1, { 1, 0, "siginfo_t *", } },
+	{ "signal-handle", 2, { 2, 0, "void (*)(void)", } },
+	{ "signal-send", 0, { 0, 0, "struct task_struct *", "lwpsinfo_t *" } },
+	{ "signal-send", 1, { 0, 0, "struct task_struct *", "psinfo_t *" } },
+	{ "signal-send", 2, { 1, 0, "int", } },
 	{ "start", },
 };
 
diff --git a/libdtrace/dt_provider.h b/libdtrace/dt_provider.h
index 0986f4f8..da1b4e57 100644
--- a/libdtrace/dt_provider.h
+++ b/libdtrace/dt_provider.h
@@ -48,6 +48,7 @@ struct dt_probe;
  */
 typedef struct dt_argdesc {
 	int mapping;
+	int flags;				/* see DT_NF_* */
 	const char *native;
 	const char *xlate;
 } dt_argdesc_t;
diff --git a/libdtrace/dt_provider_tp.c b/libdtrace/dt_provider_tp.c
index 07ba5e4e..a08550ab 100644
--- a/libdtrace/dt_provider_tp.c
+++ b/libdtrace/dt_provider_tp.c
@@ -248,6 +248,7 @@ dt_tp_event_info(dtrace_hdl_t *dtp, FILE *f, int skip, tp_probe_t *tpp,
 		}
 
 		argv[argc].mapping = argc;
+		argv[argc].flags = 0;
 		argv[argc].native = strp;
 		argv[argc].xlate = NULL;
 
-- 
2.39.1




More information about the DTrace-devel mailing list