Skip to content

Commit

Permalink
cg, parser: fix handling of alloca()'d string values
Browse files Browse the repository at this point in the history
When alloca()'d memory is used as a string, special handling is needed
to ensure variable assignment and storing in the output buffer works
correctly.

Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
Reviewed-by: Nick Alcock <nick.alcock@oracle.com>
  • Loading branch information
kvanhees committed Feb 20, 2023
1 parent 24087cd commit c530238
Show file tree
Hide file tree
Showing 13 changed files with 166 additions and 8 deletions.
19 changes: 15 additions & 4 deletions libdtrace/dt_cg.c
Original file line number Diff line number Diff line change
Expand Up @@ -1163,7 +1163,7 @@ dt_cg_store_val(dt_pcb_t *pcb, dt_node_t *dnp, dtrace_actkind_t kind,
size_t strsize = pcb->pcb_hdl->dt_options[DTRACEOPT_STRSIZE];

if (!not_null)
dt_cg_check_notnull(dlp, drp, dnp->dn_reg);
dt_cg_check_ptr_arg(dlp, drp, dnp, NULL);

TRACE_REGSET("store_val(): Begin ");
off = dt_rec_add(pcb->pcb_hdl, dt_cg_fill_gap, kind, size + 1,
Expand Down Expand Up @@ -3009,18 +3009,29 @@ dt_cg_store_var(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp,
srcsz = dt_node_type_size(dnp->dn_right);
size = MIN(srcsz, idp->di_size);

dt_cg_check_ptr_arg(dlp, drp, dnp->dn_right, NULL);
dt_cg_memcpy(dlp, drp, reg, dnp->dn_reg, size);

/*
* Since strings are passed by value, we need to force
* the value of the assignment to be the destination
* address.
*/
if (dt_node_is_string(dnp)) {
dt_regset_free(drp, dnp->dn_reg);
dnp->dn_reg = reg;
} else
dt_regset_free(drp, reg);
} else {
size = idp->di_size;

assert(size > 0 && size <= 8 &&
(size & (size - 1)) == 0);

emit(dlp, BPF_STORE(ldstw[size], reg, idp->di_offset, dnp->dn_reg));
dt_regset_free(drp, reg);
}

dt_regset_free(drp, reg);

TRACE_REGSET(" store_var: End ");

return;
Expand Down Expand Up @@ -5412,7 +5423,7 @@ dt_cg_node(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)

case DT_TOK_STRINGOF:
dt_cg_node(dnp->dn_child, dlp, drp);
dt_cg_check_ptr_arg(dlp, drp, dnp->dn_child, NULL);
dt_cg_check_notnull(dlp, drp, dnp->dn_child->dn_reg);
dnp->dn_reg = dnp->dn_child->dn_reg;
break;

Expand Down
10 changes: 6 additions & 4 deletions libdtrace/dt_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -3855,11 +3855,13 @@ dt_cook_op2(dt_node_t *dnp, uint_t idflags)
lp_idp = lp->dn_ident;

/*
* Transfer alloca taint. Stores of non-alloca, non-literal-0
* values turn on DT_IDFLG_NONALLOCA to prevent this identifier
* from being used for alloca storage anywhere in the program.
* Transfer alloca taint unless the value is a string because
* those are assigned by value.
* Stores of non-alloca, non-literal-0 values turn on
* DT_IDFLG_NONALLOCA to prevent this identifier from being
* used for alloca storage anywhere in the program.
*/
if (rp->dn_flags & DT_NF_ALLOCA)
if (rp->dn_flags & DT_NF_ALLOCA && !dt_node_is_string(rp))
dt_cook_taint_alloca(lp, lp_idp, rp);
else if (lp_idp && !(rp->dn_kind == DT_NODE_INT && rp->dn_value == 0))
lp_idp->di_flags |= DT_IDFLG_NONALLOCA;
Expand Down
22 changes: 22 additions & 0 deletions test/unittest/actions/printf/tst.conv_s_alloca_var.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*
* 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 printf action supports '%s' for alloca()'d string variables.
*
* SECTION: Actions/printf()
*/

#pragma D option quiet

BEGIN
{
s = alloca(10);
bcopy(probename, s, 5);
printf("'%s'", (string)s);
exit(0);
}
1 change: 1 addition & 0 deletions test/unittest/actions/printf/tst.conv_s_alloca_var.r
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
'BEGIN'
27 changes: 27 additions & 0 deletions test/unittest/actions/printf/tst.conv_s_copyin.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: The printf action supports '%s' for copyin()'d string values.
*
* SECTION: Actions/printf()
*/
/* @@trigger: delaydie */

#pragma D option quiet

syscall::write:entry
/pid == $target/
{
printf("'%s'", (string)copyin(arg1, 32));
exit(0);
}

ERROR
{
exit(1);
}
3 changes: 3 additions & 0 deletions test/unittest/actions/printf/tst.conv_s_copyin.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
'Delay in ns needed in delay env '
-- @@stderr --
Delay in ns needed in delay env var.
27 changes: 27 additions & 0 deletions test/unittest/actions/printf/tst.conv_s_copyinstr.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: The printf action supports '%s' for copyinstr()'d values.
*
* SECTION: Actions/printf()
*/
/* @@trigger: delaydie */

#pragma D option quiet

syscall::write:entry
/pid == $target/
{
printf("'%s'", copyinstr(arg1, 32));
exit(0);
}

ERROR
{
exit(1);
}
3 changes: 3 additions & 0 deletions test/unittest/actions/printf/tst.conv_s_copyinstr.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
'Delay in ns needed in delay env'
-- @@stderr --
Delay in ns needed in delay env var.
18 changes: 18 additions & 0 deletions test/unittest/funcs/bcopy/err.bcopy-into-string.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*
* 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: A bcopy() into an alloca()'d string variable yields an error.
*
* SECTION: Actions and Subroutines/bcopy()
*/

BEGIN {
s = (string)alloca(10);
bcopy(probename, s, 5);
exit(0);
}
21 changes: 21 additions & 0 deletions test/unittest/funcs/bcopy/tst.bcopy-into-alloca.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* 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: A bcopy() into an alloca()'d space can be used as a string.
*
* SECTION: Actions and Subroutines/bcopy()
*/

#pragma D option quiet

BEGIN {
s = alloca(10);
bcopy(probename, s, 5);
trace((string)s);
exit(0);
}
1 change: 1 addition & 0 deletions test/unittest/funcs/bcopy/tst.bcopy-into-alloca.r
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
BEGIN
21 changes: 21 additions & 0 deletions test/unittest/funcs/bcopy/tst.bcopy-into-string-indirect.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/*
* 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: A bcopy() into an alloca()'d space can be used as a string.
*
* SECTION: Actions and Subroutines/bcopy()
*/

#pragma D option quiet

BEGIN {
s = alloca(0);
bcopy(probename, alloca(10), 5);
trace((string)s);
exit(0);
}
1 change: 1 addition & 0 deletions test/unittest/funcs/bcopy/tst.bcopy-into-string-indirect.r
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
BEGIN

0 comments on commit c530238

Please sign in to comment.