dfsan_origin.h 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. //===-- dfsan_origin.h ----------------------------------*- C++ -*-===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file is a part of DataFlowSanitizer.
  10. //
  11. // Origin id utils.
  12. //===----------------------------------------------------------------------===//
  13. #ifndef DFSAN_ORIGIN_H
  14. #define DFSAN_ORIGIN_H
  15. #include "dfsan_chained_origin_depot.h"
  16. #include "dfsan_flags.h"
  17. #include "sanitizer_common/sanitizer_stackdepot.h"
  18. namespace __dfsan {
  19. // Origin handling.
  20. //
  21. // Origin is a 32-bit identifier that is attached to any taint value in the
  22. // program and describes how this memory came to be tainted.
  23. //
  24. // Chained origin id is like:
  25. // zzzz xxxx xxxx xxxx
  26. //
  27. // Chained origin id describes an event of storing a taint value to
  28. // memory. The xxx part is a value of ChainedOriginDepot, which is a mapping of
  29. // (stack_id, prev_id) -> id, where
  30. // * stack_id describes the event.
  31. // StackDepot keeps a mapping between those and corresponding stack traces.
  32. // * prev_id is another origin id that describes the earlier part of the
  33. // taint value history. 0 prev_id indicates the start of a chain.
  34. // Following a chain of prev_id provides the full recorded history of a taint
  35. // value.
  36. //
  37. // This, effectively, defines a forest where nodes are points in value history
  38. // marked with origin ids, and edges are events that are marked with stack_id.
  39. //
  40. // The "zzzz" bits of chained origin id are used to store the length of the
  41. // origin chain.
  42. class Origin {
  43. public:
  44. static bool isValidId(u32 id) { return id != 0; }
  45. u32 raw_id() const { return raw_id_; }
  46. bool isChainedOrigin() const { return Origin::isValidId(raw_id_); }
  47. u32 getChainedId() const {
  48. CHECK(Origin::isValidId(raw_id_));
  49. return raw_id_ & kChainedIdMask;
  50. }
  51. // Returns the next origin in the chain and the current stack trace.
  52. //
  53. // It scans a partition of StackDepot linearly, and is used only by origin
  54. // tracking report.
  55. Origin getNextChainedOrigin(StackTrace *stack) const {
  56. CHECK(Origin::isValidId(raw_id_));
  57. u32 prev_id;
  58. u32 stack_id = GetChainedOriginDepot()->Get(getChainedId(), &prev_id);
  59. if (stack)
  60. *stack = StackDepotGet(stack_id);
  61. return Origin(prev_id);
  62. }
  63. static Origin CreateChainedOrigin(Origin prev, StackTrace *stack) {
  64. int depth = prev.isChainedOrigin() ? prev.depth() : -1;
  65. // depth is the length of the chain minus 1.
  66. // origin_history_size of 0 means unlimited depth.
  67. if (flags().origin_history_size > 0) {
  68. ++depth;
  69. if (depth >= flags().origin_history_size || depth > kMaxDepth)
  70. return prev;
  71. }
  72. StackDepotHandle h = StackDepotPut_WithHandle(*stack);
  73. if (!h.valid())
  74. return prev;
  75. if (flags().origin_history_per_stack_limit > 0) {
  76. int use_count = h.use_count();
  77. if (use_count > flags().origin_history_per_stack_limit)
  78. return prev;
  79. }
  80. u32 chained_id;
  81. bool inserted =
  82. GetChainedOriginDepot()->Put(h.id(), prev.raw_id(), &chained_id);
  83. CHECK((chained_id & kChainedIdMask) == chained_id);
  84. if (inserted && flags().origin_history_per_stack_limit > 0)
  85. h.inc_use_count_unsafe();
  86. return Origin((depth << kDepthShift) | chained_id);
  87. }
  88. static Origin FromRawId(u32 id) { return Origin(id); }
  89. private:
  90. static const int kDepthBits = 4;
  91. static const int kDepthShift = 32 - kDepthBits;
  92. static const u32 kChainedIdMask = ((u32)-1) >> kDepthBits;
  93. u32 raw_id_;
  94. explicit Origin(u32 raw_id) : raw_id_(raw_id) {}
  95. int depth() const {
  96. CHECK(isChainedOrigin());
  97. return (raw_id_ >> kDepthShift) & ((1 << kDepthBits) - 1);
  98. }
  99. public:
  100. static const int kMaxDepth = (1 << kDepthBits) - 1;
  101. };
  102. } // namespace __dfsan
  103. #endif // DFSAN_ORIGIN_H