[DTrace-devel] [PATCH 11/12] Add support for copyinto() subroutine
Kris Van Hees
kris.van.hees at oracle.com
Wed Jul 13 19:18:01 UTC 2022
The copyinto() subroutine is a near-identical copy of bcopy() other
than that the arguments are ordered differently, and it reads from
userspace addresses rather than kernel addresses.
Signed-off-by: Kris Van Hees <kris.van.hees at oracle.com>
---
libdtrace/dt_cg.c | 73 ++++++++++++++++++-
.../err.D_PROTO_ARG.non_alloca_arg3-2.d | 23 ++++++
.../err.D_PROTO_ARG.non_alloca_arg3.d | 23 ++++++
.../copyinto/err.D_PROTO_ARG.non_ptr_arg3.d | 23 ++++++
.../err.D_PROTO_ARG.non_scalar_arg1.d | 23 ++++++
.../err.D_PROTO_ARG.non_scalar_arg2.d | 23 ++++++
.../copyinto/err.D_PROTO_LEN.missing_arg.d | 23 ++++++
.../copyinto/err.D_PROTO_LEN.too_few_args.d | 23 ++++++
.../copyinto/err.D_PROTO_LEN.too_many_args.d | 23 ++++++
test/unittest/funcs/copyinto/err.badaddr.d | 24 ++++++
test/unittest/funcs/copyinto/err.badaddr.r | 6 ++
test/unittest/funcs/copyinto/err.badsize.d | 25 +++++++
test/unittest/funcs/copyinto/err.badsize.r | 6 ++
test/unittest/funcs/copyinto/err.null_arg1.d | 24 ++++++
test/unittest/funcs/copyinto/err.null_arg1.r | 6 ++
test/unittest/funcs/copyinto/tst.copyinto.d | 27 +++++++
test/unittest/funcs/tst.copyinto.d | 36 ---------
17 files changed, 374 insertions(+), 37 deletions(-)
create mode 100644 test/unittest/funcs/copyinto/err.D_PROTO_ARG.non_alloca_arg3-2.d
create mode 100644 test/unittest/funcs/copyinto/err.D_PROTO_ARG.non_alloca_arg3.d
create mode 100644 test/unittest/funcs/copyinto/err.D_PROTO_ARG.non_ptr_arg3.d
create mode 100644 test/unittest/funcs/copyinto/err.D_PROTO_ARG.non_scalar_arg1.d
create mode 100644 test/unittest/funcs/copyinto/err.D_PROTO_ARG.non_scalar_arg2.d
create mode 100644 test/unittest/funcs/copyinto/err.D_PROTO_LEN.missing_arg.d
create mode 100644 test/unittest/funcs/copyinto/err.D_PROTO_LEN.too_few_args.d
create mode 100644 test/unittest/funcs/copyinto/err.D_PROTO_LEN.too_many_args.d
create mode 100644 test/unittest/funcs/copyinto/err.badaddr.d
create mode 100644 test/unittest/funcs/copyinto/err.badaddr.r
create mode 100644 test/unittest/funcs/copyinto/err.badsize.d
create mode 100644 test/unittest/funcs/copyinto/err.badsize.r
create mode 100644 test/unittest/funcs/copyinto/err.null_arg1.d
create mode 100644 test/unittest/funcs/copyinto/err.null_arg1.r
create mode 100644 test/unittest/funcs/copyinto/tst.copyinto.d
delete mode 100644 test/unittest/funcs/tst.copyinto.d
diff --git a/libdtrace/dt_cg.c b/libdtrace/dt_cg.c
index 9a4a80d0..265a6408 100644
--- a/libdtrace/dt_cg.c
+++ b/libdtrace/dt_cg.c
@@ -4325,6 +4325,77 @@ dt_cg_subr_copyin(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
TRACE_REGSET(" subr-copyin:End ");
}
+static void
+dt_cg_subr_copyinto(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
+{
+ dtrace_hdl_t *dtp = yypcb->pcb_hdl;
+ dt_node_t *src = dnp->dn_args;
+ dt_node_t *size = src->dn_list;
+ dt_node_t *dst = size->dn_list;
+ int maxsize = dtp->dt_options[DTRACEOPT_SCRATCHSIZE] - 8;
+ uint_t lbl_badsize = dt_irlist_label(dlp);
+ uint_t lbl_ok = dt_irlist_label(dlp);
+
+ TRACE_REGSET(" subr-copyinto:Begin");
+
+ /* Validate the size for the copy operation. */
+ dt_cg_node(size, dlp, drp);
+
+ emit(dlp, BPF_BRANCH_IMM(BPF_JSLT, size->dn_reg, 0, lbl_badsize));
+ emit(dlp, BPF_BRANCH_IMM(BPF_JGT, size->dn_reg, maxsize, lbl_badsize));
+
+ /* Validate the source pointer. */
+ dt_cg_node(src, dlp, drp);
+ if (src->dn_flags & DT_NF_ALLOCA)
+ dnerror(src, D_PROTO_ARG,
+ "copyinto( ) argument #1 is incompatible with prototype:\n"
+ "\tprototype: non-alloca pointer\n"
+ "\t argument: alloca pointer\n");
+ dt_cg_check_notnull(dlp, drp, src->dn_reg);
+
+ /* Validate the destination pointer. */
+ dt_cg_node(dst, dlp, drp);
+ if (!(dst->dn_flags & DT_NF_ALLOCA))
+ dnerror(dst, D_PROTO_ARG,
+ "copyinto( ) argument #3 is incompatible with prototype:\n"
+ "\tprototype: alloca pointer\n"
+ "\t argument: non-alloca pointer\n");
+ /* The dst will be NULL-checked in the alloca access check below. */
+
+ dt_cg_alloca_access_check(dlp, drp, dst->dn_reg,
+ DT_ISREG, size->dn_reg);
+ dt_cg_alloca_ptr(dlp, drp, dst->dn_reg, dst->dn_reg);
+
+ if (dt_regset_xalloc_args(drp) == -1)
+ longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);
+
+ emit(dlp, BPF_MOV_REG(BPF_REG_1, dst->dn_reg));
+ emit(dlp, BPF_MOV_REG(BPF_REG_2, size->dn_reg));
+ emit(dlp, BPF_MOV_REG(BPF_REG_3, src->dn_reg));
+ dt_regset_xalloc(drp, BPF_REG_0);
+ emit(dlp, BPF_CALL_HELPER(dtp->dt_bpfhelper[BPF_FUNC_probe_read_user]));
+
+ /*
+ * At this point the dst is validated, so any problem must be with
+ * the src address.
+ */
+ emit(dlp, BPF_BRANCH_IMM(BPF_JEQ, BPF_REG_0, 0, lbl_ok));
+ dt_regset_free(drp, BPF_REG_0);
+ dt_regset_free_args(drp);
+ dt_cg_probe_error(yypcb, DTRACEFLT_BADADDR, DT_ISREG, src->dn_reg);
+ emitl(dlp, lbl_badsize,
+ BPF_NOP());
+ dt_cg_probe_error(yypcb, DTRACEFLT_BADSIZE, DT_ISREG, size->dn_reg);
+ emitl(dlp, lbl_ok,
+ BPF_NOP());
+
+ dt_regset_free(drp, src->dn_reg);
+ dt_regset_free(drp, dst->dn_reg);
+ dt_regset_free(drp, size->dn_reg);
+
+ TRACE_REGSET(" subr-copyinto:End ");
+}
+
static void
dt_cg_subr_strchr(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
{
@@ -4805,7 +4876,7 @@ static dt_cg_subr_f *_dt_cg_subr[DIF_SUBR_MAX + 1] = {
[DIF_SUBR_COPYOUTSTR] = NULL,
[DIF_SUBR_ALLOCA] = &dt_cg_subr_alloca,
[DIF_SUBR_BCOPY] = &dt_cg_subr_bcopy,
- [DIF_SUBR_COPYINTO] = NULL,
+ [DIF_SUBR_COPYINTO] = &dt_cg_subr_copyinto,
[DIF_SUBR_MSGDSIZE] = NULL,
[DIF_SUBR_MSGSIZE] = NULL,
[DIF_SUBR_GETMAJOR] = &dt_cg_subr_getmajor,
diff --git a/test/unittest/funcs/copyinto/err.D_PROTO_ARG.non_alloca_arg3-2.d b/test/unittest/funcs/copyinto/err.D_PROTO_ARG.non_alloca_arg3-2.d
new file mode 100644
index 00000000..97dd22a5
--- /dev/null
+++ b/test/unittest/funcs/copyinto/err.D_PROTO_ARG.non_alloca_arg3-2.d
@@ -0,0 +1,23 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: Argument 3 for copyinto() must be an alloca() pointer.
+ *
+ * SECTION: Actions and Subroutines/copyinto()
+ */
+
+BEGIN
+{
+ copyinto(1, 2, &`max_pfn);
+ exit(1);
+}
+
+ERROR
+{
+ exit(0);
+}
diff --git a/test/unittest/funcs/copyinto/err.D_PROTO_ARG.non_alloca_arg3.d b/test/unittest/funcs/copyinto/err.D_PROTO_ARG.non_alloca_arg3.d
new file mode 100644
index 00000000..9ef33904
--- /dev/null
+++ b/test/unittest/funcs/copyinto/err.D_PROTO_ARG.non_alloca_arg3.d
@@ -0,0 +1,23 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: Argument 3 for copyinto() must be an alloca() pointer.
+ *
+ * SECTION: Actions and Subroutines/copyinto()
+ */
+
+BEGIN
+{
+ copyinto(1, 2, "");
+ exit(1);
+}
+
+ERROR
+{
+ exit(0);
+}
diff --git a/test/unittest/funcs/copyinto/err.D_PROTO_ARG.non_ptr_arg3.d b/test/unittest/funcs/copyinto/err.D_PROTO_ARG.non_ptr_arg3.d
new file mode 100644
index 00000000..65b41f63
--- /dev/null
+++ b/test/unittest/funcs/copyinto/err.D_PROTO_ARG.non_ptr_arg3.d
@@ -0,0 +1,23 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: Argument 3 for copyinto() must be a pointer.
+ *
+ * SECTION: Actions and Subroutines/copyinto()
+ */
+
+BEGIN
+{
+ copyinto(1, 2, 3);
+ exit(1);
+}
+
+ERROR
+{
+ exit(0);
+}
diff --git a/test/unittest/funcs/copyinto/err.D_PROTO_ARG.non_scalar_arg1.d b/test/unittest/funcs/copyinto/err.D_PROTO_ARG.non_scalar_arg1.d
new file mode 100644
index 00000000..8cdf7746
--- /dev/null
+++ b/test/unittest/funcs/copyinto/err.D_PROTO_ARG.non_scalar_arg1.d
@@ -0,0 +1,23 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: Argument 1 for copyinto() must be a scalar.
+ *
+ * SECTION: Actions and Subroutines/copyinto()
+ */
+
+BEGIN
+{
+ copyinto("1", 2, 3);
+ exit(1);
+}
+
+ERROR
+{
+ exit(0);
+}
diff --git a/test/unittest/funcs/copyinto/err.D_PROTO_ARG.non_scalar_arg2.d b/test/unittest/funcs/copyinto/err.D_PROTO_ARG.non_scalar_arg2.d
new file mode 100644
index 00000000..077f38a5
--- /dev/null
+++ b/test/unittest/funcs/copyinto/err.D_PROTO_ARG.non_scalar_arg2.d
@@ -0,0 +1,23 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: Argument 2 for copyinto() must be a scalar.
+ *
+ * SECTION: Actions and Subroutines/copyinto()
+ */
+
+BEGIN
+{
+ copyinto(1, "2", 3);
+ exit(1);
+}
+
+ERROR
+{
+ exit(0);
+}
diff --git a/test/unittest/funcs/copyinto/err.D_PROTO_LEN.missing_arg.d b/test/unittest/funcs/copyinto/err.D_PROTO_LEN.missing_arg.d
new file mode 100644
index 00000000..3d0813f5
--- /dev/null
+++ b/test/unittest/funcs/copyinto/err.D_PROTO_LEN.missing_arg.d
@@ -0,0 +1,23 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: Arguments are required for copyinto().
+ *
+ * SECTION: Actions and Subroutines/copyinto()
+ */
+
+BEGIN
+{
+ copyinto();
+ exit(1);
+}
+
+ERROR
+{
+ exit(0);
+}
diff --git a/test/unittest/funcs/copyinto/err.D_PROTO_LEN.too_few_args.d b/test/unittest/funcs/copyinto/err.D_PROTO_LEN.too_few_args.d
new file mode 100644
index 00000000..dc756b4d
--- /dev/null
+++ b/test/unittest/funcs/copyinto/err.D_PROTO_LEN.too_few_args.d
@@ -0,0 +1,23 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: Three arguments are required for copyinto().
+ *
+ * SECTION: Actions and Subroutines/copyinto()
+ */
+
+BEGIN
+{
+ copyinto(1, 2);
+ exit(1);
+}
+
+ERROR
+{
+ exit(0);
+}
diff --git a/test/unittest/funcs/copyinto/err.D_PROTO_LEN.too_many_args.d b/test/unittest/funcs/copyinto/err.D_PROTO_LEN.too_many_args.d
new file mode 100644
index 00000000..eb408e6a
--- /dev/null
+++ b/test/unittest/funcs/copyinto/err.D_PROTO_LEN.too_many_args.d
@@ -0,0 +1,23 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: Exactly three Arguments are required for copyinto().
+ *
+ * SECTION: Actions and Subroutines/copyinto()
+ */
+
+BEGIN
+{
+ copyin(1, 2, 3, 4);
+ exit(1);
+}
+
+ERROR
+{
+ exit(0);
+}
diff --git a/test/unittest/funcs/copyinto/err.badaddr.d b/test/unittest/funcs/copyinto/err.badaddr.d
new file mode 100644
index 00000000..a1d85d70
--- /dev/null
+++ b/test/unittest/funcs/copyinto/err.badaddr.d
@@ -0,0 +1,24 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: Using copyinto() with an invalid source address reports a fault.
+ *
+ * SECTION: Actions and Subroutines/copyinto()
+ */
+
+BEGIN
+{
+ ptr = (char *)alloca(256);
+ copyinto(0x1234, 8, ptr);
+ exit(0);
+}
+
+ERROR
+{
+ exit(1);
+}
diff --git a/test/unittest/funcs/copyinto/err.badaddr.r b/test/unittest/funcs/copyinto/err.badaddr.r
new file mode 100644
index 00000000..11861e1f
--- /dev/null
+++ b/test/unittest/funcs/copyinto/err.badaddr.r
@@ -0,0 +1,6 @@
+ FUNCTION:NAME
+ :ERROR
+
+-- @@stderr --
+dtrace: script 'test/unittest/funcs/copyinto/err.badaddr.d' matched 2 probes
+dtrace: error on enabled probe ID 3 (ID 1: dtrace:::BEGIN): invalid address ({ptr}) in action #1 at BPF pc NNN
diff --git a/test/unittest/funcs/copyinto/err.badsize.d b/test/unittest/funcs/copyinto/err.badsize.d
new file mode 100644
index 00000000..c2b6ab18
--- /dev/null
+++ b/test/unittest/funcs/copyinto/err.badsize.d
@@ -0,0 +1,25 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: The copyinto() size must not exceed the allocated space.
+ *
+ * SECTION: Actions and Subroutines/copyin()
+ * User Process Tracing/copyin() and copyinstr()
+ */
+
+BEGIN
+{
+ ptr = (char *)alloca(64);
+ copyinto(curthread->mm->env_start, 65, ptr);
+ exit(0);
+}
+
+ERROR
+{
+ exit(1);
+}
diff --git a/test/unittest/funcs/copyinto/err.badsize.r b/test/unittest/funcs/copyinto/err.badsize.r
new file mode 100644
index 00000000..ec4b062e
--- /dev/null
+++ b/test/unittest/funcs/copyinto/err.badsize.r
@@ -0,0 +1,6 @@
+ FUNCTION:NAME
+ :ERROR
+
+-- @@stderr --
+dtrace: script 'test/unittest/funcs/copyinto/err.badsize.d' matched 2 probes
+dtrace: error on enabled probe ID 3 (ID 1: dtrace:::BEGIN): invalid size ({ptr}) in action #1 at BPF pc NNN
diff --git a/test/unittest/funcs/copyinto/err.null_arg1.d b/test/unittest/funcs/copyinto/err.null_arg1.d
new file mode 100644
index 00000000..2cb302e0
--- /dev/null
+++ b/test/unittest/funcs/copyinto/err.null_arg1.d
@@ -0,0 +1,24 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: Using copyinto() with a NULL source address reports a fault.
+ *
+ * SECTION: Actions and Subroutines/copyinto()
+ */
+
+BEGIN
+{
+ ptr = (char *)alloca(256);
+ copyinto(0, 8, ptr);
+ exit(0);
+}
+
+ERROR
+{
+ exit(1);
+}
diff --git a/test/unittest/funcs/copyinto/err.null_arg1.r b/test/unittest/funcs/copyinto/err.null_arg1.r
new file mode 100644
index 00000000..f568ee5c
--- /dev/null
+++ b/test/unittest/funcs/copyinto/err.null_arg1.r
@@ -0,0 +1,6 @@
+ FUNCTION:NAME
+ :ERROR
+
+-- @@stderr --
+dtrace: script 'test/unittest/funcs/copyinto/err.null_arg1.d' matched 2 probes
+dtrace: error on enabled probe ID 3 (ID 1: dtrace:::BEGIN): invalid address ({ptr}) in action #1 at BPF pc NNN
diff --git a/test/unittest/funcs/copyinto/tst.copyinto.d b/test/unittest/funcs/copyinto/tst.copyinto.d
new file mode 100644
index 00000000..55890fbd
--- /dev/null
+++ b/test/unittest/funcs/copyinto/tst.copyinto.d
@@ -0,0 +1,27 @@
+/*
+ * Oracle Linux DTrace.
+ * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved.
+ * Licensed under the Universal Permissive License v 1.0 as shown at
+ * http://oss.oracle.com/licenses/upl.
+ */
+
+/*
+ * ASSERTION: It is possible to read data from the envp[] userspace area.
+ *
+ * SECTION: Actions and Subroutines/copyinto()
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+ ptr = (char *)alloca(256);
+ copyinto(curthread->mm->env_start, 256, ptr);
+ printf("envp[0] = \"%s\"", stringof(ptr));
+ exit(0);
+}
+
+ERROR
+{
+ exit(1);
+}
diff --git a/test/unittest/funcs/tst.copyinto.d b/test/unittest/funcs/tst.copyinto.d
deleted file mode 100644
index b7abfce0..00000000
--- a/test/unittest/funcs/tst.copyinto.d
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * Oracle Linux DTrace.
- * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved.
- * Licensed under the Universal Permissive License v 1.0 as shown at
- * http://oss.oracle.com/licenses/upl.
- */
-/* @@xfail: dtv2 */
-
-/*
- * ASSERTION:
- * test copyinto by copying the first string of the user's
- * environment.
- *
- * SECTION: Actions and Subroutines/copyinto()
- *
- */
-
-#pragma D option quiet
-
-BEGIN
-/curpsinfo->pr_dmodel == PR_MODEL_ILP32/
-{
- envp = alloca(sizeof(uint32_t));
- copyinto(curpsinfo->pr_envp, sizeof(uint32_t), envp);
- printf("envp[0] = \"%s\"", copyinstr(*(uint32_t *)envp));
- exit(0);
-}
-
-BEGIN
-/curpsinfo->pr_dmodel == PR_MODEL_LP64/
-{
- envp = alloca(sizeof(uint64_t));
- copyinto(curpsinfo->pr_envp, sizeof(uint64_t), envp);
- printf("envp[0] = \"%s\"", copyinstr(*(uint64_t *)envp));
- exit(0);
-}
--
2.34.1
More information about the DTrace-devel
mailing list