Skip to content

Commit c72f9a0

Browse files
committed
WIP 1 - starting to make BarrierElement in shared dataflow lib
1 parent 5159aeb commit c72f9a0

File tree

7 files changed

+112
-6
lines changed

7 files changed

+112
-6
lines changed
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/**
2+
* Provides classes and predicates for defining barriers and barrier guards.
3+
*
4+
* Flow sinks defined here feed into data flow configurations as follows:
5+
*
6+
* ```text
7+
* data from *.model.yml | QL extensions of FlowSink::Range
8+
* v v
9+
* FlowSink (associated with a models-as-data kind string)
10+
* v
11+
* sinkNode predicate | other QL defined sinks, for example using concepts
12+
* v v
13+
* various Sink classes for specific data flow configurations <- extending QuerySink
14+
* ```
15+
*
16+
* New sinks should be defined using models-as-data, QL extensions of
17+
* `FlowSink::Range`, or concepts. Data flow configurations should use the
18+
* `sinkNode` predicate and/or concepts to define their sinks.
19+
*/
20+
21+
private import rust
22+
private import internal.FlowSummaryImpl as Impl
23+
private import internal.DataFlowImpl as DataFlowImpl
24+
25+
// import all instances below
26+
private module Barriers {
27+
private import codeql.rust.Frameworks
28+
private import codeql.rust.dataflow.internal.ModelsAsData
29+
}
30+
31+
/** Provides the `Range` class used to define the extent of `FlowBarrier`. */
32+
module FlowBarrier {
33+
/** A flow sink. */
34+
abstract class Range extends Impl::Public::BarrierElement {
35+
bindingset[this]
36+
Range() { any() }
37+
38+
override predicate isBarrier(
39+
string output, string kind, Impl::Public::Provenance provenance, string model
40+
) {
41+
this.isBarrier(output, kind) and provenance = "manual" and model = ""
42+
}
43+
44+
/**
45+
* Holds is this element is a flow barrier of kind `kind`, where data
46+
* flows out as described by `output`.
47+
*/
48+
predicate isBarrier(string output, string kind) { none() }
49+
}
50+
}
51+
52+
final class FlowBarrier = FlowBarrier::Range;
53+
54+
predicate barrierNode = DataFlowImpl::barrierNode/2;

rust/ql/lib/codeql/rust/dataflow/internal/DataFlowImpl.qll

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,6 +1157,10 @@ private module Cached {
11571157
cached
11581158
predicate sinkNode(Node n, string kind) { n.(FlowSummaryNode).isSink(kind, _) }
11591159

1160+
/** Holds if `n` is a flow barrier of kind `kind`. */
1161+
cached
1162+
predicate barrierNode(Node n, string kind) { n.(FlowSummaryNode).isBarrier(kind, _) }
1163+
11601164
/**
11611165
* A step in a flow summary defined using `OptionalStep[name]`. An `OptionalStep` is "opt-in", which means
11621166
* that by default the step is not present in the flow summary and needs to be explicitly enabled by defining

rust/ql/lib/codeql/rust/dataflow/internal/ModelsAsData.qll

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@
4444
*/
4545

4646
private import rust
47+
private import codeql.rust.dataflow.FlowBarrier
4748
private import codeql.rust.dataflow.FlowSummary
4849
private import codeql.rust.dataflow.FlowSource
4950
private import codeql.rust.dataflow.FlowSink
@@ -239,6 +240,23 @@ private class FlowSinkFromModel extends FlowSink::Range {
239240
}
240241
}
241242

243+
private class BarrierFromModel extends FlowBarrier::Range {
244+
private string path;
245+
246+
BarrierFromModel() {
247+
barrierModel(path, _, _, _, _) and
248+
this.callResolvesTo(path)
249+
// path = this.getCall().getResolvedTarget().getCanonicalPath()
250+
}
251+
252+
override predicate isBarrier(string output, string kind, Provenance provenance, string model) {
253+
exists(QlBuiltins::ExtensionId madId |
254+
barrierModel(path, output, kind, provenance, madId) and
255+
model = "MaD:" + madId.toString()
256+
)
257+
}
258+
}
259+
242260
private module Debug {
243261
private import FlowSummaryImpl
244262
private import Private

rust/ql/lib/codeql/rust/dataflow/internal/Node.qll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,12 +82,12 @@ class FlowSummaryNode extends Node, TFlowSummaryNode {
8282
result = this.getSummaryNode().getSinkElement()
8383
}
8484

85-
/** Holds is this node is a source node of kind `kind`. */
85+
/** Holds if this node is a source node of kind `kind`. */
8686
predicate isSource(string kind, string model) {
8787
this.getSummaryNode().(FlowSummaryImpl::Private::SourceOutputNode).isEntry(kind, model)
8888
}
8989

90-
/** Holds is this node is a sink node of kind `kind`. */
90+
/** Holds if this node is a sink node of kind `kind`. */
9191
predicate isSink(string kind, string model) {
9292
this.getSummaryNode().(FlowSummaryImpl::Private::SinkInputNode).isExit(kind, model)
9393
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
extensions:
2+
- addsTo:
3+
pack: codeql/rust-all
4+
extensible: barrierModel
5+
data:
6+
- ["main::sanitize", "ReturnValue", "test", "manual"]

rust/ql/test/library-tests/dataflow/barrier/inline-flow.ql

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,21 @@
33
*/
44

55
import rust
6+
import codeql.rust.dataflow.DataFlow
7+
import codeql.rust.dataflow.FlowBarrier
68
import utils.test.InlineFlowTest
7-
import DefaultFlowTest
8-
import TaintFlow::PathGraph
9+
import PathGraph
910

10-
from TaintFlow::PathNode source, TaintFlow::PathNode sink
11-
where TaintFlow::flowPath(source, sink)
11+
module CustomConfig implements DataFlow::ConfigSig {
12+
predicate isSource = DefaultFlowConfig::isSource/1;
13+
14+
predicate isSink = DefaultFlowConfig::isSink/1;
15+
16+
predicate isBarrier(DataFlow::Node n) { barrierNode(n, "test") }
17+
}
18+
19+
import FlowTest<CustomConfig, CustomConfig>
20+
21+
from PathNode source, PathNode sink
22+
where flowPath(source, sink)
1223
select sink, source, sink, "$@", source, source.toString()

shared/dataflow/codeql/dataflow/internal/FlowSummaryImpl.qll

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,19 @@ module Make<
368368
abstract predicate isSink(string input, string kind, Provenance provenance, string model);
369369
}
370370

371+
/** A barrier element. */
372+
abstract class BarrierElement extends SourceBaseFinal {
373+
bindingset[this]
374+
BarrierElement() { any() }
375+
376+
/**
377+
* Holds if this element is a flow barrier of kind `kind`, where data
378+
* flows out as described by `output`.
379+
*/
380+
pragma[nomagic]
381+
abstract predicate isBarrier(string output, string kind, Provenance provenance, string model);
382+
}
383+
371384
private signature predicate hasKindSig(string kind);
372385

373386
signature class NeutralCallableSig extends SummarizedCallableBaseFinal {

0 commit comments

Comments
 (0)