Skip to content

Commit

Permalink
alloca: bcopy
Browse files Browse the repository at this point in the history
This is fairly simple given the machinery already present: we just need
to make sure the arguments are suitably alloca-tainted or non-tainted,
then call dt_cg_alloca_access_check on the alloca pointer to bounds
check it, and dt_cg_alloca_ptr to turn it into a real map_value pointer.

Since we validate the destination address completely ourselves, if the
underlying probe_read call fails we can even tell that it's a problem
with the source pointer, and report the failing address appropriately.

Signed-off-by: Nick Alcock <nick.alcock@oracle.com>
Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
Reviewed-by: Kris Van Hees <kris.van.hees@oracle.com>
  • Loading branch information
nickalcock committed Apr 19, 2022
1 parent 020c85f commit e05eb1d
Show file tree
Hide file tree
Showing 31 changed files with 419 additions and 12 deletions.
68 changes: 67 additions & 1 deletion libdtrace/dt_cg.c
Original file line number Diff line number Diff line change
Expand Up @@ -4005,6 +4005,72 @@ dt_cg_subr_alloca(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
TRACE_REGSET(" subr-alloca:End ");
}

static void
dt_cg_subr_bcopy(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
{
dt_node_t *src = dnp->dn_args;
dt_node_t *dst = src->dn_list;
dt_node_t *size = dst->dn_list;
int maxsize = yypcb->pcb_hdl->dt_options[DTRACEOPT_SCRATCHSIZE];
uint_t lbl_badsize = dt_irlist_label(dlp);
uint_t lbl_ok = dt_irlist_label(dlp);

TRACE_REGSET(" subr-bcopy:Begin");

dt_cg_node(src, dlp, drp);
if (src->dn_flags & DT_NF_ALLOCA)
dnerror(src, D_PROTO_ARG,
"bcopy( ) 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);

dt_cg_node(dst, dlp, drp);
if (!(dst->dn_flags & DT_NF_ALLOCA))
dnerror(dst, D_PROTO_ARG,
"bcopy( ) argument #2 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_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));

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(BPF_FUNC_probe_read));

/*
* 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-bcopy:End ");
}

static void
dt_cg_subr_strchr(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
{
Expand Down Expand Up @@ -4479,7 +4545,7 @@ static dt_cg_subr_f *_dt_cg_subr[DIF_SUBR_MAX + 1] = {
[DIF_SUBR_COPYOUT] = NULL,
[DIF_SUBR_COPYOUTSTR] = NULL,
[DIF_SUBR_ALLOCA] = &dt_cg_subr_alloca,
[DIF_SUBR_BCOPY] = NULL,
[DIF_SUBR_BCOPY] = &dt_cg_subr_bcopy,
[DIF_SUBR_COPYINTO] = NULL,
[DIF_SUBR_MSGDSIZE] = NULL,
[DIF_SUBR_MSGSIZE] = NULL,
Expand Down
27 changes: 27 additions & 0 deletions test/unittest/funcs/alloca/err.alloca-bcopy-before-beyond.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* 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: bcopies overlapping the whole of alloca()ed memory fail.
*
* SECTION: Actions and Subroutines/alloca()
*/

#pragma D option quiet

BEGIN
{
a = "0";
s = (char *)alloca(15);
bcopy(a, s-1, 17);
exit(0);
}

ERROR
{
exit(1);
}
3 changes: 3 additions & 0 deletions test/unittest/funcs/alloca/err.alloca-bcopy-before-beyond.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

-- @@stderr --
dtrace: error on enabled probe ID 3 (ID 1: dtrace:::BEGIN): invalid address ({ptr}) in action #1 at BPF pc NNN
27 changes: 27 additions & 0 deletions test/unittest/funcs/alloca/err.alloca-bcopy-before-bottom.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* 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: bcopies to before the bottom of alloca()ed memory fail.
*
* SECTION: Actions and Subroutines/alloca()
*/

#pragma D option quiet

BEGIN
{
a = "0";
s = (char *)alloca(15);
bcopy(a, s-1, 1);
exit(0);
}

ERROR
{
exit(1);
}
3 changes: 3 additions & 0 deletions test/unittest/funcs/alloca/err.alloca-bcopy-before-bottom.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

-- @@stderr --
dtrace: error on enabled probe ID 3 (ID 1: dtrace:::BEGIN): invalid address ({ptr}) in action #1 at BPF pc NNN
27 changes: 27 additions & 0 deletions test/unittest/funcs/alloca/err.alloca-bcopy-beyond-top.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* 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: bcopies to past the end of alloca()ed memory fail.
*
* SECTION: Actions and Subroutines/alloca()
*/

#pragma D option quiet

BEGIN
{
a = "01";
s = (char *)alloca(16);
bcopy(a, &s[16], 1);
exit(0);
}

ERROR
{
exit(1);
}
3 changes: 3 additions & 0 deletions test/unittest/funcs/alloca/err.alloca-bcopy-beyond-top.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

-- @@stderr --
dtrace: error on enabled probe ID 3 (ID 1: dtrace:::BEGIN): invalid address ({ptr}) in action #1 at BPF pc NNN
27 changes: 27 additions & 0 deletions test/unittest/funcs/alloca/err.alloca-bcopy-crossing-bottom.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* 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: bcopies to across the bottom of alloca()ed memory fail.
*
* SECTION: Actions and Subroutines/alloca()
*/

#pragma D option quiet

BEGIN
{
a = "01";
s = (char *)alloca(15);
bcopy(a, s-1, 2);
exit(0);
}

ERROR
{
exit(1);
}
3 changes: 3 additions & 0 deletions test/unittest/funcs/alloca/err.alloca-bcopy-crossing-bottom.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

-- @@stderr --
dtrace: error on enabled probe ID 3 (ID 1: dtrace:::BEGIN): invalid address ({ptr}) in action #1 at BPF pc NNN
27 changes: 27 additions & 0 deletions test/unittest/funcs/alloca/err.alloca-bcopy-crossing-top.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* 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: bcopies to across the end of alloca()ed memory fail.
*
* SECTION: Actions and Subroutines/alloca()
*/

#pragma D option quiet

BEGIN
{
a = "01";
s = (char *)alloca(16);
bcopy(a, &s[15], 2);
exit(0);
}

ERROR
{
exit(1);
}
3 changes: 3 additions & 0 deletions test/unittest/funcs/alloca/err.alloca-bcopy-crossing-top.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

-- @@stderr --
dtrace: error on enabled probe ID 3 (ID 1: dtrace:::BEGIN): invalid size ({ptr}) in action #1 at BPF pc NNN
36 changes: 36 additions & 0 deletions test/unittest/funcs/alloca/err.alloca-scratch-exceeding-bcopy.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*
* 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: Exceeding the size of alloca()ed memory with a bcopy is an error.
*
* SECTION: Actions and Subroutines/alloca()
*/

/*
* Intentionally use an unaligned size, to make sure that errors are still
* emitted when accessing beyond the last byte when the size is not a
* multiple of the max type size.
*/

#pragma D option quiet
#pragma D option scratchsize=9

string a;

BEGIN
{
a = "0123456789abcdefgh";
s = (char *)alloca(9);
bcopy(a, s, 17);
exit((s[0] == '0' && s[16] == 'g') ? 0 : 1);
}

ERROR
{
exit(1);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

-- @@stderr --
dtrace: error on enabled probe ID 3 (ID 1: dtrace:::BEGIN): invalid size ({ptr}) in action #1 at BPF pc NNN
28 changes: 28 additions & 0 deletions test/unittest/funcs/alloca/tst.alloca-bcopy-top.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/*
* 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: bcopies to the last byte of alloca()ed memory succeed.
*
* SECTION: Actions and Subroutines/alloca()
*/

#pragma D option quiet

BEGIN
{
a = "0";
s = (char *)alloca(15);
bcopy(a, &s[14], 1);
printf("%c\n", s[14]);
exit(0);
}

ERROR
{
exit(1);
}
2 changes: 2 additions & 0 deletions test/unittest/funcs/alloca/tst.alloca-bcopy-top.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
0

31 changes: 31 additions & 0 deletions test/unittest/funcs/alloca/tst.alloca-scratch-filling-bcopy.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/*
* 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: It is possible to store and load structures that fill up
* alloca()ed memory.
*
* SECTION: Actions and Subroutines/alloca()
*/

#pragma D option quiet
#pragma D option scratchsize=8

string a;

BEGIN
{
a = "01234567";
s = (char *)alloca(8);
bcopy(a, s, 8);
exit((s[0] == '0' && s[7] == '7') ? 0 : 1);
}

ERROR
{
exit(1);
}
4 changes: 4 additions & 0 deletions test/unittest/funcs/err.badbcopy.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-- @@stderr --
dtrace: failed to compile script test/unittest/funcs/err.badbcopy.d: line 26: bcopy( ) argument #1 is incompatible with prototype:
prototype: non-alloca pointer
argument: alloca pointer
3 changes: 3 additions & 0 deletions test/unittest/funcs/err.badbcopy1.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@

-- @@stderr --
dtrace: error on enabled probe ID 3 (ID 1: dtrace:::BEGIN): invalid address ({ptr}) in action #1 at BPF pc NNN
4 changes: 4 additions & 0 deletions test/unittest/funcs/err.badbcopy2.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-- @@stderr --
dtrace: failed to compile script test/unittest/funcs/err.badbcopy2.d: line 25: bcopy( ) argument #2 is incompatible with prototype:
prototype: alloca pointer
argument: non-alloca pointer
4 changes: 4 additions & 0 deletions test/unittest/funcs/err.badbcopy3.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-- @@stderr --
dtrace: failed to compile script test/unittest/funcs/err.badbcopy3.d: line 22: bcopy( ) argument #2 is incompatible with prototype:
prototype: alloca pointer
argument: non-alloca pointer
1 change: 0 additions & 1 deletion test/unittest/funcs/err.badbcopy4.d
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
/* @@xfail: dtv2 */

/*
* ASSERTION:
Expand Down
2 changes: 1 addition & 1 deletion test/unittest/funcs/err.badbcopy4.r
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@

-- @@stderr --
dtrace: error on enabled probe ID 1 (ID 1: dtrace:::BEGIN): invalid address ({ptr}) in action #2 at DIF offset 52
dtrace: error on enabled probe ID 3 (ID 1: dtrace:::BEGIN): invalid address ({ptr}) in action #1 at BPF pc NNN
1 change: 0 additions & 1 deletion test/unittest/funcs/err.badbcopy5.d
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
/* @@xfail: dtv2 */

/*
* ASSERTION:
Expand Down
2 changes: 1 addition & 1 deletion test/unittest/funcs/err.badbcopy5.r
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@

-- @@stderr --
dtrace: error on enabled probe ID 1 (ID 1: dtrace:::BEGIN): invalid address ({ptr}) in action #2 at DIF offset 40
dtrace: error on enabled probe ID 3 (ID 1: dtrace:::BEGIN): invalid address ({ptr}) in action #1 at BPF pc NNN
1 change: 0 additions & 1 deletion test/unittest/funcs/err.badbcopy6.d
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
* Licensed under the Universal Permissive License v 1.0 as shown at
* http://oss.oracle.com/licenses/upl.
*/
/* @@xfail: dtv2 */

#pragma D option quiet

Expand Down

0 comments on commit e05eb1d

Please sign in to comment.