Skip to content

Commit

Permalink
Ensure curcpu values are scalarized when typecast
Browse files Browse the repository at this point in the history
The 'curcpu' built-in variable is special because its value is a
pointer to a map value.  This means that the verifier will impose
strict limitations on what can be done with that pointer value.
By scalarizing it when it is typecast we ensure that the verifier
will treat the value as a regular scalar.

Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
Reviewed-by: Nick Alcock <nick.alcock@oracle.com>
  • Loading branch information
kvanhees committed Aug 4, 2022
1 parent 7b443ed commit 00e2ca4
Show file tree
Hide file tree
Showing 7 changed files with 72 additions and 8 deletions.
11 changes: 9 additions & 2 deletions bpf/get_bvar.c
Original file line number Diff line number Diff line change
Expand Up @@ -186,8 +186,15 @@ noinline uint64_t dt_get_bvar(const dt_dctx_t *dctx, uint32_t id, uint32_t idx)
uint32_t key = 0;
void *val = bpf_map_lookup_elem(&cpuinfo, &key);

if (val == NULL)
return (uint64_t)NULL; /* FIXME */
if (val == NULL) {
/*
* Typically, we would use 'return error(...);' but
* that confuses the verifier because it returns -1.
* So, instead, we explicitly return 0.
*/
error(dctx, DTRACEFLT_ILLOP, 0);
return 0;
}

return (uint64_t)val;
}
Expand Down
2 changes: 1 addition & 1 deletion libdtrace/dt_cg.c
Original file line number Diff line number Diff line change
Expand Up @@ -2521,7 +2521,7 @@ dt_cg_typecast(const dt_node_t *src, const dt_node_t *dst,
return;

if (dt_node_is_arith(dst) && dt_node_is_pointer(src) &&
(src->dn_flags & DT_NF_ALLOCA)) {
(src->dn_flags & (DT_NF_ALLOCA | DT_NF_DPTR))) {
int mst;

if ((mst = dt_regset_alloc(drp)) == -1)
Expand Down
1 change: 1 addition & 0 deletions libdtrace/dt_ident.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ typedef struct dt_ident {
#define DT_IDFLG_BPF 0x1000 /* variable is BPF */
#define DT_IDFLG_ALLOCA 0x2000 /* variable holds an alloca()ed pointer */
#define DT_IDFLG_NONALLOCA 0x4000 /* variable known not to hold an alloca()ed pointer */
#define DT_IDFLG_DPTR 0x8000 /* variable is ptr to DTrace-managed storage */

#define DT_IDENT_UNDEF UINT_MAX /* id for (as yet) undefined identifiers */

Expand Down
4 changes: 2 additions & 2 deletions libdtrace/dt_open.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,8 +143,8 @@ static const dt_ident_t _dtrace_globals[] = {
&dt_idops_func, "void(char *, uintptr_t, size_t)" },
{ "count", DT_IDENT_AGGFUNC, 0, DT_AGG_COUNT, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_func, "void()" },
{ "curcpu", DT_IDENT_SCALAR, 0, DIF_VAR_CURCPU, DT_ATTR_STABCMN, DT_VERS_1_0,
&dt_idops_type, "cpuinfo_t *" },
{ "curcpu", DT_IDENT_SCALAR, DT_IDFLG_DPTR, DIF_VAR_CURCPU, DT_ATTR_STABCMN,
DT_VERS_1_0, &dt_idops_type, "cpuinfo_t *" },
{ "curthread", DT_IDENT_SCALAR, 0, DIF_VAR_CURTHREAD,
{ DTRACE_STABILITY_STABLE, DTRACE_STABILITY_PRIVATE,
DTRACE_CLASS_COMMON }, DT_VERS_1_0,
Expand Down
9 changes: 6 additions & 3 deletions libdtrace/dt_parser.c
Original file line number Diff line number Diff line change
Expand Up @@ -2832,10 +2832,13 @@ dt_xcook_ident(dt_node_t *dnp, dt_idhash_t *dhp, uint_t idkind, int create)
dnp->dn_flags |= DT_NF_LVALUE;

/*
* If the type of the variable is a REF-type, we mark this
* variable node as a pointer to DTrace-managed storage (DPTR).
* If the identifier is marked as a pointer to DTrace-managed
* storage (DPTR), or if the type of the variable is a
* REF-type, we mark this variable node as a pointer to
* DTrace-managed storage (DPTR).
*/
if (dnp->dn_flags & DT_NF_REF)
if ((idp->di_flags & DT_IDFLG_DPTR) ||
(dnp->dn_flags & DT_NF_REF))
dnp->dn_flags |= DT_NF_DPTR;

if (idp->di_flags & DT_IDFLG_WRITE)
Expand Down
27 changes: 27 additions & 0 deletions test/unittest/arithmetic/tst.cast-alloca.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: Casting an alloca() pointer to a scalar is allowed.
*
* SECTION: Types, Operators, and Expressions/Arithmetic Operators
*/

#pragma D option quiet

BEGIN
{
ptr = alloca(10);
val = ((int64_t)ptr) >> 8;
trace(val);
exit(0);
}

ERROR
{
exit(1);
}
26 changes: 26 additions & 0 deletions test/unittest/arithmetic/tst.cast-curcpu.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* 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: Casting a curcpu value to a scalar is allowed.
*
* SECTION: Types, Operators, and Expressions/Arithmetic Operators
*/

#pragma D option quiet

BEGIN
{
val = ((int64_t)curcpu) >> 8;
trace(val);
exit(0);
}

ERROR
{
exit(1);
}

0 comments on commit 00e2ca4

Please sign in to comment.