-
Hi all, I wrote a simple c example, and the following query works. So it is tracking the pointer to the struct very well!. #include <stdio.h>
struct s_tls{
int *len1;
}tls;
void hal_dma_copy(struct s_tls *ptls6)
{
int x = 5;
ptls6->len1 = &x;
}
void intermediate3(struct s_tls *ptls5)
{
hal_dma_copy(ptls5);
}
void intermediate2(struct s_tls *ptls4)
{
intermediate3(ptls4);
}
void intermediate1(struct s_tls *ptls3)
{
intermediate2(ptls3);
}
void parse_baseline_request(struct s_tls *ptls2)
{
intermediate1(ptls2);
}
int main()
{
struct s_tls tls;
struct s_tls *ptls1 = &tls;
parse_baseline_request(ptls1);
return 0;
} import cpp
import semmle.code.cpp.dataflow.TaintTracking
import DataFlow::PathGraph
class ParserToDMAMemCopy extends TaintTracking::Configuration {
ParserToDMAMemCopy() { this = "ParserToDMAMemCopy" }
override predicate isSource(DataFlow::Node source) {
exists(Parameter ptls2 |
source.asParameter() = ptls2 and ptls2.hasName("ptls2") and
ptls2.getFunction().hasName("parse_baseline_request")
)
}
override predicate isSink(DataFlow::Node sink) {
exists(FunctionCall call |
sink.asExpr() = call.getArgument(0) and
call.getTarget().hasName("hal_dma_copy")
)
}
}
from ParserToDMAMemCopy config, DataFlow::PathNode source, DataFlow::PathNode sink
where config.hasFlowPath(source, sink)
select sink, source Then, I changed the example code to be similar to the case that we saw in the S500 code, in away that a pointer to a struct member len1 is sent to the callee functions not the pointer to the struct itself, in this case the same query doesn't work. #include <stdio.h>
struct s_tls{
int *len1;
}tls;
void hal_dma_copy(int **plen4)
{
int x = 6;
*plen4 = &x;
}
void intermediate3(int **plen3)
{
hal_dma_copy(plen3);
}
void intermediate2(int **plen2)
{
intermediate3(plen2);
}
void intermediate1(int **plen1)
{
intermediate2(plen1);
}
void parse_baseline_request(struct s_tls *ptls2)
{
intermediate1(&ptls2->len1);
}
int main()
{
struct s_tls tls;
struct s_tls *ptls1 = &tls;
parse_baseline_request(ptls1);
return 0;
} It seems that codeQL is not able to follow the What do you think I did wrong here? |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
Hi @xreinheitx, The flow in the second example isn't reported because we're only seeing a read of the address of override predicate isAdditionalTaintStep(DataFlow::Node n1, DataFlow::Node n2) {
exists(FieldAccess fa |
// flow from the qualifier
n1.asExpr() = fa.getQualifier() and
// to the result of the field access
n2.asExpr() = fa and
// when we're accessing the `len1` field
fa.getTarget().hasName("len1") and
// on a struct of type `s_tls` (or `s_tls*` or `s_tls&`, etc.)
fa.getQualifier().getUnspecifiedType().stripType().hasName("s_tls")
)
} You can fine-tune the last two lines of this predicate to suite your need. In general, adding flow from the qualifier of a field to the result of field access will cause a lot of spurious flow (which is why I restricted the above predicate to only be this one field on the struct), but if you have any additional domain-knowledge you can probably find a more generic solution to fit your need. For example: maybe you want flow from qualifiers to field accesses for all fields on the |
Beta Was this translation helpful? Give feedback.
Hi @xreinheitx,
The flow in the second example isn't reported because we're only seeing a read of the address of
len1
with no preceding write. So in order to get flow in this example you need to add an additional taint step to your taint configueration like: