Skip to content

Commit c7975e8

Browse files
author
Robert Marsh
authored
Merge pull request #2657 from jbj/DefaultTaintTracking-models
C++: wire up models library to DefaultTaintTracking
2 parents 79a72a3 + 0e3ed2d commit c7975e8

File tree

10 files changed

+302
-103
lines changed

10 files changed

+302
-103
lines changed

cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll

Lines changed: 75 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ private import semmle.code.cpp.ir.dataflow.DataFlow
44
private import semmle.code.cpp.ir.dataflow.DataFlow2
55
private import semmle.code.cpp.ir.IR
66
private import semmle.code.cpp.ir.dataflow.internal.DataFlowDispatch as Dispatch
7+
private import semmle.code.cpp.models.interfaces.Taint
8+
private import semmle.code.cpp.models.interfaces.DataFlow
79

810
/**
911
* A predictable instruction is one where an external user can predict
@@ -156,18 +158,79 @@ private predicate instructionTaintStep(Instruction i1, Instruction i2) {
156158
// This is part of the translation of `a[i]`, where we want taint to flow
157159
// from `a`.
158160
i2.(PointerAddInstruction).getLeft() = i1
159-
// TODO: robust Chi handling
160-
//
161-
// TODO: Flow from argument to return of known functions: Port missing parts
162-
// of `returnArgument` to the `interfaces.Taint` and `interfaces.DataFlow`
163-
// libraries.
164-
//
165-
// TODO: Flow from input argument to output argument of known functions: Port
166-
// missing parts of `copyValueBetweenArguments` to the `interfaces.Taint` and
167-
// `interfaces.DataFlow` libraries and implement call side-effect nodes. This
168-
// will help with the test for `ExecTainted.ql`. The test for
169-
// `TaintedPath.ql` is more tricky because the output arg is a pointer
170-
// addition expression.
161+
or
162+
// Flow from argument to return value
163+
i2 = any(CallInstruction call |
164+
exists(int indexIn |
165+
modelTaintToReturnValue(call.getStaticCallTarget(), indexIn) and
166+
i1 = getACallArgumentOrIndirection(call, indexIn)
167+
)
168+
)
169+
or
170+
// Flow from input argument to output argument
171+
// TODO: This won't work in practice as long as all aliased memory is tracked
172+
// together in a single virtual variable.
173+
// TODO: Will this work on the test for `TaintedPath.ql`, where the output arg
174+
// is a pointer addition expression?
175+
i2 = any(WriteSideEffectInstruction outNode |
176+
exists(CallInstruction call, int indexIn, int indexOut |
177+
modelTaintToParameter(call.getStaticCallTarget(), indexIn, indexOut) and
178+
i1 = getACallArgumentOrIndirection(call, indexIn) and
179+
outNode.getIndex() = indexOut and
180+
outNode.getPrimaryInstruction() = call
181+
)
182+
)
183+
}
184+
185+
/**
186+
* Get an instruction that goes into argument `argumentIndex` of `call`. This
187+
* can be either directly or through one pointer indirection.
188+
*/
189+
private Instruction getACallArgumentOrIndirection(CallInstruction call, int argumentIndex) {
190+
result = call.getPositionalArgument(argumentIndex)
191+
or
192+
exists(ReadSideEffectInstruction readSE |
193+
// TODO: why are read side effect operands imprecise?
194+
result = readSE.getSideEffectOperand().getAnyDef() and
195+
readSE.getPrimaryInstruction() = call and
196+
readSE.getIndex() = argumentIndex
197+
)
198+
}
199+
200+
private predicate modelTaintToParameter(Function f, int parameterIn, int parameterOut) {
201+
exists(FunctionInput modelIn, FunctionOutput modelOut |
202+
f.(TaintFunction).hasTaintFlow(modelIn, modelOut) and
203+
(modelIn.isParameter(parameterIn) or modelIn.isParameterDeref(parameterIn)) and
204+
modelOut.isParameterDeref(parameterOut)
205+
)
206+
}
207+
208+
private predicate modelTaintToReturnValue(Function f, int parameterIn) {
209+
// Taint flow from parameter to return value
210+
exists(FunctionInput modelIn, FunctionOutput modelOut |
211+
f.(TaintFunction).hasTaintFlow(modelIn, modelOut) and
212+
(modelIn.isParameter(parameterIn) or modelIn.isParameterDeref(parameterIn)) and
213+
(modelOut.isReturnValue() or modelOut.isReturnValueDeref())
214+
)
215+
or
216+
// Data flow (not taint flow) to where the return value points. For the time
217+
// being we will conflate pointers and objects in taint tracking.
218+
exists(FunctionInput modelIn, FunctionOutput modelOut |
219+
f.(DataFlowFunction).hasDataFlow(modelIn, modelOut) and
220+
(modelIn.isParameter(parameterIn) or modelIn.isParameterDeref(parameterIn)) and
221+
modelOut.isReturnValueDeref()
222+
)
223+
or
224+
// Taint flow from one argument to another and data flow from an argument to a
225+
// return value. This happens in functions like `strcat` and `memcpy`. We
226+
// could model this flow in two separate steps, but that would add reverse
227+
// flow from the write side-effect to the call instruction, which may not be
228+
// desirable.
229+
exists(int parameterMid, InParameter modelMid, OutReturnValue returnOut |
230+
modelTaintToParameter(f, parameterIn, parameterMid) and
231+
modelMid.isParameter(parameterMid) and
232+
f.(DataFlowFunction).hasDataFlow(modelMid, returnOut)
233+
)
171234
}
172235

173236
private Element adjustedSink(DataFlow::Node sink) {

cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,52 +1198,63 @@ class CallSideEffectInstruction extends SideEffectInstruction {
11981198
}
11991199

12001200
/**
1201-
* An instruction representing the side effect of a function call on any memory that might be read
1202-
* by that call.
1201+
* An instruction representing the side effect of a function call on any memory
1202+
* that might be read by that call. This instruction is emitted instead of
1203+
* `CallSideEffectInstruction` when it's certain that the call target cannot
1204+
* write to escaped memory.
12031205
*/
12041206
class CallReadSideEffectInstruction extends SideEffectInstruction {
12051207
CallReadSideEffectInstruction() { getOpcode() instanceof Opcode::CallReadSideEffect }
12061208
}
12071209

12081210
/**
1209-
* An instruction representing the read of an indirect parameter within a function call.
1211+
* An instruction representing a read side effect of a function call on a
1212+
* specific parameter.
12101213
*/
1211-
class IndirectReadSideEffectInstruction extends SideEffectInstruction {
1212-
IndirectReadSideEffectInstruction() { getOpcode() instanceof Opcode::IndirectReadSideEffect }
1214+
class ReadSideEffectInstruction extends SideEffectInstruction, IndexedInstruction {
1215+
ReadSideEffectInstruction() { getOpcode() instanceof ReadSideEffectOpcode }
12131216

1214-
Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() }
1217+
/** Gets the operand for the value that will be read from this instruction, if known. */
1218+
final SideEffectOperand getSideEffectOperand() { result = getAnOperand() }
1219+
1220+
/** Gets the value that will be read from this instruction, if known. */
1221+
final Instruction getSideEffect() { result = getSideEffectOperand().getDef() }
1222+
1223+
/** Gets the operand for the address from which this instruction may read. */
1224+
final AddressOperand getArgumentOperand() { result = getAnOperand() }
12151225

1216-
Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() }
1226+
/** Gets the address from which this instruction may read. */
1227+
final Instruction getArgumentDef() { result = getArgumentOperand().getDef() }
1228+
}
1229+
1230+
/**
1231+
* An instruction representing the read of an indirect parameter within a function call.
1232+
*/
1233+
class IndirectReadSideEffectInstruction extends ReadSideEffectInstruction {
1234+
IndirectReadSideEffectInstruction() { getOpcode() instanceof Opcode::IndirectReadSideEffect }
12171235
}
12181236

12191237
/**
12201238
* An instruction representing the read of an indirect buffer parameter within a function call.
12211239
*/
1222-
class BufferReadSideEffectInstruction extends SideEffectInstruction {
1240+
class BufferReadSideEffectInstruction extends ReadSideEffectInstruction {
12231241
BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect }
1224-
1225-
Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() }
1226-
1227-
Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() }
12281242
}
12291243

12301244
/**
12311245
* An instruction representing the read of an indirect buffer parameter within a function call.
12321246
*/
1233-
class SizedBufferReadSideEffectInstruction extends SideEffectInstruction {
1247+
class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction {
12341248
SizedBufferReadSideEffectInstruction() {
12351249
getOpcode() instanceof Opcode::SizedBufferReadSideEffect
12361250
}
12371251

1238-
Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() }
1239-
12401252
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
1241-
1242-
Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() }
12431253
}
12441254

12451255
/**
1246-
* An instruction representing a side effect of a function call.
1256+
* An instruction representing a write side effect of a function call on a
1257+
* specific parameter.
12471258
*/
12481259
class WriteSideEffectInstruction extends SideEffectInstruction, IndexedInstruction {
12491260
WriteSideEffectInstruction() { getOpcode() instanceof WriteSideEffectOpcode }

cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,52 +1198,63 @@ class CallSideEffectInstruction extends SideEffectInstruction {
11981198
}
11991199

12001200
/**
1201-
* An instruction representing the side effect of a function call on any memory that might be read
1202-
* by that call.
1201+
* An instruction representing the side effect of a function call on any memory
1202+
* that might be read by that call. This instruction is emitted instead of
1203+
* `CallSideEffectInstruction` when it's certain that the call target cannot
1204+
* write to escaped memory.
12031205
*/
12041206
class CallReadSideEffectInstruction extends SideEffectInstruction {
12051207
CallReadSideEffectInstruction() { getOpcode() instanceof Opcode::CallReadSideEffect }
12061208
}
12071209

12081210
/**
1209-
* An instruction representing the read of an indirect parameter within a function call.
1211+
* An instruction representing a read side effect of a function call on a
1212+
* specific parameter.
12101213
*/
1211-
class IndirectReadSideEffectInstruction extends SideEffectInstruction {
1212-
IndirectReadSideEffectInstruction() { getOpcode() instanceof Opcode::IndirectReadSideEffect }
1214+
class ReadSideEffectInstruction extends SideEffectInstruction, IndexedInstruction {
1215+
ReadSideEffectInstruction() { getOpcode() instanceof ReadSideEffectOpcode }
12131216

1214-
Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() }
1217+
/** Gets the operand for the value that will be read from this instruction, if known. */
1218+
final SideEffectOperand getSideEffectOperand() { result = getAnOperand() }
1219+
1220+
/** Gets the value that will be read from this instruction, if known. */
1221+
final Instruction getSideEffect() { result = getSideEffectOperand().getDef() }
1222+
1223+
/** Gets the operand for the address from which this instruction may read. */
1224+
final AddressOperand getArgumentOperand() { result = getAnOperand() }
12151225

1216-
Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() }
1226+
/** Gets the address from which this instruction may read. */
1227+
final Instruction getArgumentDef() { result = getArgumentOperand().getDef() }
1228+
}
1229+
1230+
/**
1231+
* An instruction representing the read of an indirect parameter within a function call.
1232+
*/
1233+
class IndirectReadSideEffectInstruction extends ReadSideEffectInstruction {
1234+
IndirectReadSideEffectInstruction() { getOpcode() instanceof Opcode::IndirectReadSideEffect }
12171235
}
12181236

12191237
/**
12201238
* An instruction representing the read of an indirect buffer parameter within a function call.
12211239
*/
1222-
class BufferReadSideEffectInstruction extends SideEffectInstruction {
1240+
class BufferReadSideEffectInstruction extends ReadSideEffectInstruction {
12231241
BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect }
1224-
1225-
Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() }
1226-
1227-
Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() }
12281242
}
12291243

12301244
/**
12311245
* An instruction representing the read of an indirect buffer parameter within a function call.
12321246
*/
1233-
class SizedBufferReadSideEffectInstruction extends SideEffectInstruction {
1247+
class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction {
12341248
SizedBufferReadSideEffectInstruction() {
12351249
getOpcode() instanceof Opcode::SizedBufferReadSideEffect
12361250
}
12371251

1238-
Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() }
1239-
12401252
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
1241-
1242-
Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() }
12431253
}
12441254

12451255
/**
1246-
* An instruction representing a side effect of a function call.
1256+
* An instruction representing a write side effect of a function call on a
1257+
* specific parameter.
12471258
*/
12481259
class WriteSideEffectInstruction extends SideEffectInstruction, IndexedInstruction {
12491260
WriteSideEffectInstruction() { getOpcode() instanceof WriteSideEffectOpcode }

cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,52 +1198,63 @@ class CallSideEffectInstruction extends SideEffectInstruction {
11981198
}
11991199

12001200
/**
1201-
* An instruction representing the side effect of a function call on any memory that might be read
1202-
* by that call.
1201+
* An instruction representing the side effect of a function call on any memory
1202+
* that might be read by that call. This instruction is emitted instead of
1203+
* `CallSideEffectInstruction` when it's certain that the call target cannot
1204+
* write to escaped memory.
12031205
*/
12041206
class CallReadSideEffectInstruction extends SideEffectInstruction {
12051207
CallReadSideEffectInstruction() { getOpcode() instanceof Opcode::CallReadSideEffect }
12061208
}
12071209

12081210
/**
1209-
* An instruction representing the read of an indirect parameter within a function call.
1211+
* An instruction representing a read side effect of a function call on a
1212+
* specific parameter.
12101213
*/
1211-
class IndirectReadSideEffectInstruction extends SideEffectInstruction {
1212-
IndirectReadSideEffectInstruction() { getOpcode() instanceof Opcode::IndirectReadSideEffect }
1214+
class ReadSideEffectInstruction extends SideEffectInstruction, IndexedInstruction {
1215+
ReadSideEffectInstruction() { getOpcode() instanceof ReadSideEffectOpcode }
12131216

1214-
Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() }
1217+
/** Gets the operand for the value that will be read from this instruction, if known. */
1218+
final SideEffectOperand getSideEffectOperand() { result = getAnOperand() }
1219+
1220+
/** Gets the value that will be read from this instruction, if known. */
1221+
final Instruction getSideEffect() { result = getSideEffectOperand().getDef() }
1222+
1223+
/** Gets the operand for the address from which this instruction may read. */
1224+
final AddressOperand getArgumentOperand() { result = getAnOperand() }
12151225

1216-
Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() }
1226+
/** Gets the address from which this instruction may read. */
1227+
final Instruction getArgumentDef() { result = getArgumentOperand().getDef() }
1228+
}
1229+
1230+
/**
1231+
* An instruction representing the read of an indirect parameter within a function call.
1232+
*/
1233+
class IndirectReadSideEffectInstruction extends ReadSideEffectInstruction {
1234+
IndirectReadSideEffectInstruction() { getOpcode() instanceof Opcode::IndirectReadSideEffect }
12171235
}
12181236

12191237
/**
12201238
* An instruction representing the read of an indirect buffer parameter within a function call.
12211239
*/
1222-
class BufferReadSideEffectInstruction extends SideEffectInstruction {
1240+
class BufferReadSideEffectInstruction extends ReadSideEffectInstruction {
12231241
BufferReadSideEffectInstruction() { getOpcode() instanceof Opcode::BufferReadSideEffect }
1224-
1225-
Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() }
1226-
1227-
Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() }
12281242
}
12291243

12301244
/**
12311245
* An instruction representing the read of an indirect buffer parameter within a function call.
12321246
*/
1233-
class SizedBufferReadSideEffectInstruction extends SideEffectInstruction {
1247+
class SizedBufferReadSideEffectInstruction extends ReadSideEffectInstruction {
12341248
SizedBufferReadSideEffectInstruction() {
12351249
getOpcode() instanceof Opcode::SizedBufferReadSideEffect
12361250
}
12371251

1238-
Instruction getArgumentDef() { result = getAnOperand().(AddressOperand).getDef() }
1239-
12401252
Instruction getSizeDef() { result = getAnOperand().(BufferSizeOperand).getDef() }
1241-
1242-
Instruction getSideEffect() { result = getAnOperand().(SideEffectOperand).getDef() }
12431253
}
12441254

12451255
/**
1246-
* An instruction representing a side effect of a function call.
1256+
* An instruction representing a write side effect of a function call on a
1257+
* specific parameter.
12471258
*/
12481259
class WriteSideEffectInstruction extends SideEffectInstruction, IndexedInstruction {
12491260
WriteSideEffectInstruction() { getOpcode() instanceof WriteSideEffectOpcode }

cpp/ql/src/semmle/code/cpp/models/implementations/Inet.qll

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class InetAton extends TaintFunction, ArrayFunction {
3030
}
3131
}
3232

33-
class InetAddr extends TaintFunction, ArrayFunction {
33+
class InetAddr extends TaintFunction, ArrayFunction, AliasFunction {
3434
InetAddr() { hasGlobalName("inet_addr") }
3535

3636
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
@@ -41,6 +41,12 @@ class InetAddr extends TaintFunction, ArrayFunction {
4141
override predicate hasArrayInput(int bufParam) { bufParam = 0 }
4242

4343
override predicate hasArrayWithNullTerminator(int bufParam) { bufParam = 0 }
44+
45+
override predicate parameterNeverEscapes(int index) { index = 0 }
46+
47+
override predicate parameterEscapesOnlyViaReturn(int index) { none() }
48+
49+
override predicate parameterIsAlwaysReturned(int index) { none() }
4450
}
4551

4652
class InetNetwork extends TaintFunction, ArrayFunction {

0 commit comments

Comments
 (0)