Skip to content

Commit

Permalink
cg, test: fix copyinstr() implementation to use a tstring
Browse files Browse the repository at this point in the history
Since copyinstr() returns a string, it should be using a temporary
string like other string functions.  Also, semantics needed fixing to
apply strsize as an upper limit to the optional size rather than
triggering a fault if the size is greater than strsize.

Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
Reviewed-by: Eugene Loh <eugene.loh@oracle.com>
  • Loading branch information
kvanhees committed Feb 20, 2023
1 parent ff2766d commit 24087cd
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 38 deletions.
23 changes: 12 additions & 11 deletions libdtrace/dt_cg.c
Original file line number Diff line number Diff line change
Expand Up @@ -4517,7 +4517,7 @@ dt_cg_subr_copyinstr(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
dt_node_t *size = src->dn_list;
int maxsize = dtp->dt_options[DTRACEOPT_STRSIZE];
uint_t lbl_ok = dt_irlist_label(dlp);
uint_t lbl_badsize = dt_irlist_label(dlp);
uint_t lbl_oksize = dt_irlist_label(dlp);

TRACE_REGSET(" subr-copyinstr:Begin");

Expand All @@ -4529,15 +4529,19 @@ dt_cg_subr_copyinstr(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)

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));
emit(dlp, BPF_BRANCH_IMM(BPF_JLE, size->dn_reg, maxsize, lbl_oksize));
emit(dlp, BPF_MOV_IMM(size->dn_reg, maxsize));
emitl(dlp, lbl_oksize,
BPF_NOP());

if ((dnp->dn_reg = dt_regset_alloc(drp)) == -1)
/* Allocate a temporary string for the destination (return value). */
dnp->dn_reg = dt_regset_alloc(drp);
if (dnp->dn_reg == -1)
longjmp(yypcb->pcb_jmpbuf, EDT_NOREG);

/* Allocate scratch space. */
dt_cg_subr_alloca_impl(dnp, size, dlp, drp);
dt_cg_alloca_ptr(dlp, drp, dnp->dn_reg, 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));

dt_cg_node(src, dlp, drp);

Expand All @@ -4552,9 +4556,6 @@ dt_cg_subr_copyinstr(dt_node_t *dnp, dt_irlist_t *dlp, dt_regset_t *drp)
dt_regset_free_args(drp);
emit(dlp, BPF_BRANCH_IMM(BPF_JSGT, BPF_REG_0, 0, lbl_ok));
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, BPF_REG_0);
Expand Down
2 changes: 1 addition & 1 deletion libdtrace/dt_open.c
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ static const dt_ident_t _dtrace_globals[] = {
&dt_idops_func, "void(int)" },
{ "copyin", DT_IDENT_FUNC, 0, DIF_SUBR_COPYIN, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_func, "void *(uintptr_t, size_t)" },
{ "copyinstr", DT_IDENT_FUNC, 0, DIF_SUBR_COPYINSTR,
{ "copyinstr", DT_IDENT_FUNC, DT_IDFLG_DPTR, DIF_SUBR_COPYINSTR,
DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_func, "string(uintptr_t, [size_t])" },
{ "copyinto", DT_IDENT_FUNC, 0, DIF_SUBR_COPYINTO, DT_ATTR_STABCMN,
Expand Down
26 changes: 0 additions & 26 deletions test/unittest/funcs/copyinstr/err.D_ALLOCA_SIZE.d

This file was deleted.

30 changes: 30 additions & 0 deletions test/unittest/funcs/copyinstr/tst.copyinstr-high-maxsize.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
* Oracle Linux DTrace.
* Copyright (c) 2006, 2023, 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 a string from userspace addresses.
*
* SECTION: Actions and Subroutines/copyinstr()
* User Process Tracing/copyin() and copyinstr() Subroutines
*/
/* @@trigger: delaydie */

#pragma D option quiet
#pragma D option strsize=12

syscall::write:entry
/pid == $target/
{
printf("%s char match\n", (s = copyinstr(arg1, 96))[4] == 'y' ? "good" : "BAD");
printf("'%s'", s);
exit(0);
}

ERROR
{
exit(1);
}
4 changes: 4 additions & 0 deletions test/unittest/funcs/copyinstr/tst.copyinstr-high-maxsize.r
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
good char match
'Delay in ns'
-- @@stderr --
Delay in ns needed in delay env var.

0 comments on commit 24087cd

Please sign in to comment.