[DTrace-devel] [PATCH v4 00/10] alloca and bcopy

Nick Alcock nick.alcock at oracle.com
Tue Apr 12 10:58:59 UTC 2022


This pile of commits implements alloca and bcopy.  It's a joint effort, with
Kris doing massive revamps of the alloca/deref work.

alloca is simpler than it used to be in past revisions. It still stores
everything in a new percpu scratchmem array, but much of the rest has
changed.

1) mark all pointers emitted from alloca(), all variables such values
   are stored in, and all values retrieved from those variables with
   special parser/ident flags (unchanged from previous revisions)

2) propagate these flags to and from identifiers.  There is no bounds
   checking at this point: the pointers are still just scalar offsets from
   scratchmem.  (Offset zero is NULL: non-null offsets start at 8.)  A
   couple of prohibitions are injected at this point, but nothing more.

2) at deref time, bounds-check the pointers and raise them to map_values
   relative to the scratchmem array , taking the size of the access into
   account.  Some derefs are in somewhat unexpected places, and some sizes
   are hard to dig out, but they are all basically the same.

Rather than three bounds checkers as in days of yore there is only one,
dt_cg_alloca_access_check, whicdh always checks an offset-from-scratchmem,
not an address. Calls to this should be followed by calls to
dt_cg_alloca_ptr, which raises the resulting offset into a pointer, and
optionally returns it in a new reg.

The alloca-tainting stuff above has some slightly unfortunate implications,
since alloca status attaches to identifiers, not to specific uses of them.
You cannot reuse the same variable to store both alloca pointers and other
sorts of pointer in a single D program (not clause!).  You *can* have
ternary conditionals whose branches are sometimes alloca and sometimes not,
but you can't assign the result of such ternaries to variables at all.

The above restructions do *not* apply to null pointers: you can assign NULL
to pointers that previously held allocaed pointers, and stick alloca
pointers back on them, freely.  But that's not a get-out clause: you still
can't do this:

foo = 42;
foo = NULL;
foo = alloca(10);

Tainting does have some nice effects: we don't need extra bounds checks for
"not in scratch space" for bcopy, since we can just use alloca taint to
prove it; and we can use alloca taint to figure out whether to bounds-check
things like subr args that might or might not be alloca.

The non-alloca-related parts of this have mostly been pushed into a later
series. The only bit left in this series is actually used by it, the
fault-handling improvements; dt_cg_probe_error can now emit an illegal value
found in a register, and avoids using the regset machinery because that can
try to spill to the stack, which can cause verifier failures if some regs
are still uninitialized -- which is quite likely in a fault situation.

Kris Van Hees (1):
  alloca: deref

Nick Alcock (9):
  alloca: track alloca()ed allocations
  cg: fault improvements
  alloca: new bad-size fault
  alloca: add alloca() itself
  alloca: bcopy
  cg: support casts of pointers to integers
  cg: support null pointers in ternary conditionals
  cg: move dt_regset_xalloc for consistency
  alloca: allow passing alloca pointers to actions and subrs

 include/dtrace/faults_defines.h               |   1 +
 include/dtrace/options_defines.h              |   3 +-
 libdtrace/dt_bpf.c                            |  13 +
 libdtrace/dt_cg.c                             | 536 +++++++++++++++---
 libdtrace/dt_dctx.h                           |  24 +-
 libdtrace/dt_dlibs.c                          |   1 +
 libdtrace/dt_error.c                          |   1 +
 libdtrace/dt_errtags.h                        |   2 +
 libdtrace/dt_handle.c                         |   1 +
 libdtrace/dt_ident.c                          |  18 +-
 libdtrace/dt_ident.h                          |   2 +
 libdtrace/dt_open.c                           |  10 +-
 libdtrace/dt_options.c                        |  16 +
 libdtrace/dt_parser.c                         | 230 +++++++-
 libdtrace/dt_parser.h                         |   5 +-
 libdtrace/dt_pcb.h                            |   1 +
 test/unittest/dif/alloca.d                    |   3 +-
 .../alloca/err.D_ALLOCA_INCOMPAT.ternary.d    |  26 +
 .../alloca/err.D_ALLOCA_INCOMPAT.ternary.r    |   2 +
 ...rr.D_ALLOCA_INCOMPAT.var-clash-non-first.d |  28 +
 ...rr.D_ALLOCA_INCOMPAT.var-clash-non-first.r |   2 +
 .../alloca/err.D_ALLOCA_INCOMPAT.var-clash.d  |  30 +
 .../alloca/err.D_ALLOCA_INCOMPAT.var-clash.r  |   2 +
 .../alloca/err.alloca-bcopy-before-beyond.d   |  27 +
 .../alloca/err.alloca-bcopy-before-beyond.r   |   3 +
 .../alloca/err.alloca-bcopy-before-bottom.d   |  27 +
 .../alloca/err.alloca-bcopy-before-bottom.r   |   3 +
 .../alloca/err.alloca-bcopy-beyond-top.d      |  27 +
 .../alloca/err.alloca-bcopy-beyond-top.r      |   3 +
 .../alloca/err.alloca-bcopy-crossing-bottom.d |  27 +
 .../alloca/err.alloca-bcopy-crossing-bottom.r |   3 +
 .../alloca/err.alloca-bcopy-crossing-top.d    |  27 +
 .../alloca/err.alloca-bcopy-crossing-top.r    |   3 +
 .../alloca/err.alloca-crossing-clauses.d      |  31 +
 .../alloca/err.alloca-crossing-clauses.r      |   3 +
 .../alloca/err.alloca-load-before-bottom.d    |  26 +
 .../alloca/err.alloca-load-before-bottom.r    |   3 +
 .../funcs/alloca/err.alloca-load-beyond-top.d |  28 +
 .../funcs/alloca/err.alloca-load-beyond-top.r |   3 +
 .../alloca/err.alloca-load-crossing-bottom.d  |  25 +
 .../alloca/err.alloca-load-crossing-bottom.r  |   3 +
 .../alloca/err.alloca-null-deref-lvalue.d     |  29 +
 .../alloca/err.alloca-null-deref-lvalue.r     |   3 +
 .../funcs/alloca/err.alloca-null-deref.d      |  27 +
 .../funcs/alloca/err.alloca-null-deref.r      |   3 +
 .../err.alloca-scratch-exceeding-bcopy.d      |  36 ++
 .../err.alloca-scratch-exceeding-bcopy.r      |   3 +
 .../alloca/err.alloca-store-before-bottom.d   |  26 +
 .../alloca/err.alloca-store-before-bottom.r   |   3 +
 .../alloca/err.alloca-store-beyond-top.d      |  28 +
 .../alloca/err.alloca-store-beyond-top.r      |   3 +
 .../alloca/err.alloca-store-crossing-bottom.d |  26 +
 .../alloca/err.alloca-store-crossing-bottom.r |   3 +
 .../funcs/alloca/tst.alloca-alignment.d       |  34 ++
 .../funcs/alloca/tst.alloca-bcopy-top.d       |  28 +
 .../funcs/alloca/tst.alloca-bcopy-top.r       |   2 +
 .../alloca/tst.alloca-crossing-clauses.d      |  33 ++
 test/unittest/funcs/alloca/tst.alloca-funcs.d | 164 ++++++
 test/unittest/funcs/alloca/tst.alloca-funcs.r |   2 +
 .../funcs/alloca/tst.alloca-overtainting.sh   |  35 ++
 .../alloca/tst.alloca-scratch-filling-bcopy.d |  31 +
 ....alloca-store-load-aliasing-arith-bottom.d |  29 +
 ....alloca-store-load-aliasing-arith-bottom.r |   1 +
 .../tst.alloca-store-load-aliasing-arith.d    |  29 +
 .../alloca/tst.alloca-store-load-bottom.d     |  27 +
 .../alloca/tst.alloca-store-load-idx-1.d      |  27 +
 .../funcs/alloca/tst.alloca-store-load-top.d  |  27 +
 .../alloca/tst.alloca0-after-alloca-load.d    |  28 +
 .../funcs/alloca/tst.alloca0-after-alloca.d   |  26 +
 test/unittest/funcs/alloca/tst.alloca0-load.d |  27 +
 .../funcs/alloca/tst.alloca0-values.sh        |  34 ++
 test/unittest/funcs/alloca/tst.alloca0.d      |  25 +
 .../unittest/funcs/alloca/tst.string-alloca.d |  29 +
 .../unittest/funcs/alloca/tst.string-alloca.r |   1 +
 test/unittest/funcs/alloca/tst.ternary.d      |  27 +
 .../funcs/err.D_ALLOCA_SIZE.big_alloca.d      |  24 +
 .../funcs/err.D_ALLOCA_SIZE.big_alloca.r      |   2 +
 test/unittest/funcs/err.badalloca.r           |   3 +
 test/unittest/funcs/err.badalloca2.d          |   3 +-
 test/unittest/funcs/err.badalloca2.r          |   6 +-
 test/unittest/funcs/err.badbcopy.r            |   4 +
 test/unittest/funcs/err.badbcopy1.r           |   3 +
 test/unittest/funcs/err.badbcopy2.r           |   4 +
 test/unittest/funcs/err.badbcopy3.r           |   4 +
 test/unittest/funcs/err.badbcopy4.d           |   1 -
 test/unittest/funcs/err.badbcopy4.r           |   2 +-
 test/unittest/funcs/err.badbcopy5.d           |   1 -
 test/unittest/funcs/err.badbcopy5.r           |   2 +-
 test/unittest/funcs/err.badbcopy6.d           |   1 -
 test/unittest/funcs/err.badbcopy6.r           |   2 +-
 .../funcs/{tst.bcopy.d => err.badbcopy7.d}    |  17 +-
 test/unittest/funcs/err.badbcopy7.r           |   4 +
 .../{err.badbcopy5.d => err.badbcopy8.d}      |  13 +-
 test/unittest/funcs/err.badbcopy8.r           |   3 +
 test/unittest/funcs/tst.bcopy.d               |  12 +-
 ...st.ValidPointer2.d => err.AllocaOverrun.d} |  11 +-
 test/unittest/pointers/err.AllocaOverrun.r    |   3 +
 test/unittest/pointers/tst.ValidPointer1.d    |   1 -
 ...CA_INCOMPAT.alloca-postinc-instantiation.d |  21 +
 ...CA_INCOMPAT.alloca-postinc-instantiation.r |   2 +
 .../tst.alloca-postinc-instantiation.d        |  46 ++
 101 files changed, 2144 insertions(+), 136 deletions(-)
 create mode 100644 test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.ternary.d
 create mode 100644 test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.ternary.r
 create mode 100644 test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.var-clash-non-first.d
 create mode 100644 test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.var-clash-non-first.r
 create mode 100644 test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.var-clash.d
 create mode 100644 test/unittest/funcs/alloca/err.D_ALLOCA_INCOMPAT.var-clash.r
 create mode 100644 test/unittest/funcs/alloca/err.alloca-bcopy-before-beyond.d
 create mode 100644 test/unittest/funcs/alloca/err.alloca-bcopy-before-beyond.r
 create mode 100644 test/unittest/funcs/alloca/err.alloca-bcopy-before-bottom.d
 create mode 100644 test/unittest/funcs/alloca/err.alloca-bcopy-before-bottom.r
 create mode 100644 test/unittest/funcs/alloca/err.alloca-bcopy-beyond-top.d
 create mode 100644 test/unittest/funcs/alloca/err.alloca-bcopy-beyond-top.r
 create mode 100644 test/unittest/funcs/alloca/err.alloca-bcopy-crossing-bottom.d
 create mode 100644 test/unittest/funcs/alloca/err.alloca-bcopy-crossing-bottom.r
 create mode 100644 test/unittest/funcs/alloca/err.alloca-bcopy-crossing-top.d
 create mode 100644 test/unittest/funcs/alloca/err.alloca-bcopy-crossing-top.r
 create mode 100644 test/unittest/funcs/alloca/err.alloca-crossing-clauses.d
 create mode 100644 test/unittest/funcs/alloca/err.alloca-crossing-clauses.r
 create mode 100644 test/unittest/funcs/alloca/err.alloca-load-before-bottom.d
 create mode 100644 test/unittest/funcs/alloca/err.alloca-load-before-bottom.r
 create mode 100644 test/unittest/funcs/alloca/err.alloca-load-beyond-top.d
 create mode 100644 test/unittest/funcs/alloca/err.alloca-load-beyond-top.r
 create mode 100644 test/unittest/funcs/alloca/err.alloca-load-crossing-bottom.d
 create mode 100644 test/unittest/funcs/alloca/err.alloca-load-crossing-bottom.r
 create mode 100644 test/unittest/funcs/alloca/err.alloca-null-deref-lvalue.d
 create mode 100644 test/unittest/funcs/alloca/err.alloca-null-deref-lvalue.r
 create mode 100644 test/unittest/funcs/alloca/err.alloca-null-deref.d
 create mode 100644 test/unittest/funcs/alloca/err.alloca-null-deref.r
 create mode 100644 test/unittest/funcs/alloca/err.alloca-scratch-exceeding-bcopy.d
 create mode 100644 test/unittest/funcs/alloca/err.alloca-scratch-exceeding-bcopy.r
 create mode 100644 test/unittest/funcs/alloca/err.alloca-store-before-bottom.d
 create mode 100644 test/unittest/funcs/alloca/err.alloca-store-before-bottom.r
 create mode 100644 test/unittest/funcs/alloca/err.alloca-store-beyond-top.d
 create mode 100644 test/unittest/funcs/alloca/err.alloca-store-beyond-top.r
 create mode 100644 test/unittest/funcs/alloca/err.alloca-store-crossing-bottom.d
 create mode 100644 test/unittest/funcs/alloca/err.alloca-store-crossing-bottom.r
 create mode 100644 test/unittest/funcs/alloca/tst.alloca-alignment.d
 create mode 100644 test/unittest/funcs/alloca/tst.alloca-bcopy-top.d
 create mode 100644 test/unittest/funcs/alloca/tst.alloca-bcopy-top.r
 create mode 100644 test/unittest/funcs/alloca/tst.alloca-crossing-clauses.d
 create mode 100644 test/unittest/funcs/alloca/tst.alloca-funcs.d
 create mode 100644 test/unittest/funcs/alloca/tst.alloca-funcs.r
 create mode 100755 test/unittest/funcs/alloca/tst.alloca-overtainting.sh
 create mode 100644 test/unittest/funcs/alloca/tst.alloca-scratch-filling-bcopy.d
 create mode 100644 test/unittest/funcs/alloca/tst.alloca-store-load-aliasing-arith-bottom.d
 create mode 100644 test/unittest/funcs/alloca/tst.alloca-store-load-aliasing-arith-bottom.r
 create mode 100644 test/unittest/funcs/alloca/tst.alloca-store-load-aliasing-arith.d
 create mode 100644 test/unittest/funcs/alloca/tst.alloca-store-load-bottom.d
 create mode 100644 test/unittest/funcs/alloca/tst.alloca-store-load-idx-1.d
 create mode 100644 test/unittest/funcs/alloca/tst.alloca-store-load-top.d
 create mode 100644 test/unittest/funcs/alloca/tst.alloca0-after-alloca-load.d
 create mode 100644 test/unittest/funcs/alloca/tst.alloca0-after-alloca.d
 create mode 100644 test/unittest/funcs/alloca/tst.alloca0-load.d
 create mode 100755 test/unittest/funcs/alloca/tst.alloca0-values.sh
 create mode 100644 test/unittest/funcs/alloca/tst.alloca0.d
 create mode 100644 test/unittest/funcs/alloca/tst.string-alloca.d
 create mode 100644 test/unittest/funcs/alloca/tst.string-alloca.r
 create mode 100644 test/unittest/funcs/alloca/tst.ternary.d
 create mode 100644 test/unittest/funcs/err.D_ALLOCA_SIZE.big_alloca.d
 create mode 100644 test/unittest/funcs/err.D_ALLOCA_SIZE.big_alloca.r
 create mode 100644 test/unittest/funcs/err.badalloca.r
 create mode 100644 test/unittest/funcs/err.badbcopy.r
 create mode 100644 test/unittest/funcs/err.badbcopy1.r
 create mode 100644 test/unittest/funcs/err.badbcopy2.r
 create mode 100644 test/unittest/funcs/err.badbcopy3.r
 copy test/unittest/funcs/{tst.bcopy.d => err.badbcopy7.d} (64%)
 create mode 100644 test/unittest/funcs/err.badbcopy7.r
 copy test/unittest/funcs/{err.badbcopy5.d => err.badbcopy8.d} (63%)
 create mode 100644 test/unittest/funcs/err.badbcopy8.r
 rename test/unittest/pointers/{tst.ValidPointer2.d => err.AllocaOverrun.d} (62%)
 create mode 100644 test/unittest/pointers/err.AllocaOverrun.r
 create mode 100644 test/unittest/predicates/err.D_ALLOCA_INCOMPAT.alloca-postinc-instantiation.d
 create mode 100644 test/unittest/predicates/err.D_ALLOCA_INCOMPAT.alloca-postinc-instantiation.r
 create mode 100644 test/unittest/predicates/tst.alloca-postinc-instantiation.d

-- 
2.35.1




More information about the DTrace-devel mailing list