mirror of
https://github.com/hohn/codeql-sample-polkit.git
synced 2025-12-16 22:03:03 +01:00
Produce two-color CFG using pure codeql, remove external Python hacks
This commit is contained in:
committed by
=Michael Hohn
parent
1e8971afab
commit
1b8412ca1d
@@ -1,34 +0,0 @@
|
|||||||
/**
|
|
||||||
* @name Print part of the CFG
|
|
||||||
* @description Outputs a subset of the control flow graph
|
|
||||||
* @id cpp/example/polkit/cfg-false-successor
|
|
||||||
* @kind graph
|
|
||||||
*/
|
|
||||||
|
|
||||||
import cpp
|
|
||||||
|
|
||||||
query predicate edges(ControlFlowNode n1, ControlFlowNode n2) {
|
|
||||||
exists(
|
|
||||||
RelationalOperation cmp, Parameter argc, ControlFlowNode startFrom, Variable n, ForStmt forloop
|
|
||||||
|
|
|
||||||
// minimal restriction: start from comparison
|
|
||||||
argc.getName() = "argc" and
|
|
||||||
argc.getAnAccess() = cmp.getAnOperand().getAChild*() and
|
|
||||||
n.getAnAccess() = cmp.getAnOperand().getAChild*() and
|
|
||||||
not n instanceof Parameter and
|
|
||||||
n.getName() = "n" and
|
|
||||||
forloop.getCondition() = cmp and
|
|
||||||
forloop.getControlFlowScope().getName() = "main" and
|
|
||||||
//
|
|
||||||
startFrom = cmp.getAFalseSuccessor() and
|
|
||||||
startFrom.getASuccessor*() = n1 and
|
|
||||||
//
|
|
||||||
n1.getASuccessor() = n2 and
|
|
||||||
n1.getControlFlowScope().getName() = "main" and
|
|
||||||
// polkit has many `main` functions, grab the one from pkexec.c
|
|
||||||
n1.getLocation().getFile().getBaseName() = "pkexec.c"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
// For reference, see the file
|
|
||||||
// db/polkit-0.119.db/tmp/polkit/src/programs/pkexec.c
|
|
||||||
// (after extracting src.zip)
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
#
|
|
||||||
# Print a two-colored graph by using two queries' output; one with all nodes for
|
|
||||||
# layout, the other with false-successor nodes for coloring.
|
|
||||||
#
|
|
||||||
|
|
||||||
#* Add codeql binary PATH
|
|
||||||
export PATH=$HOME/local/codeql-2.7.6/codeql:"$PATH"
|
|
||||||
|
|
||||||
#* Graph in dgml format
|
|
||||||
cd ~/local/codeql-sample-polkit/
|
|
||||||
codeql database analyze \
|
|
||||||
./db/polkit-0.119.db \
|
|
||||||
./PrintCFG-false-successor.ql \
|
|
||||||
--rerun \
|
|
||||||
-j8 -v --ram=16000 \
|
|
||||||
--search-path $HOME/local/codeql-2.7.6/ql \
|
|
||||||
--format=dgml \
|
|
||||||
--output=PrintCFG.dgml
|
|
||||||
|
|
||||||
# Clean up the dgml (xml) output
|
|
||||||
OUT=PrintCFG.dgml/cpp/example/polkit/cfg-false-successor.dgml
|
|
||||||
tidy -xml $OUT | sponge $OUT
|
|
||||||
|
|
||||||
# Compare node Ids. They overlap, so graph visuals should work.
|
|
||||||
em PrintCFG.dgml/cpp/example/polkit/cfg-false-successor.dgml
|
|
||||||
em PrintCFG.dgml/cpp/example/polkit/cfg.dgml
|
|
||||||
|
|
||||||
# Produce a full graph with false-successor nodes colored
|
|
||||||
./dgml2dot -m PrintCFG.dgml/cpp/example/polkit/cfg-false-successor.dgml < \
|
|
||||||
PrintCFG.dgml/cpp/example/polkit/cfg.dgml > \
|
|
||||||
PrintCFG.dgml/cpp/example/polkit/cfg-false-successor-colored.dot
|
|
||||||
|
|
||||||
# Produce the DAG we really want
|
|
||||||
CFG=PrintCFG.dgml/cpp/example/polkit/cfg-false-successor-colored
|
|
||||||
dot -Tpdf < $CFG.dot > $CFG.pdf &
|
|
||||||
open $CFG.pdf
|
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
3032
PrintCFG.dgml/cpp/example/polkit/cfg.dot
Normal file
3032
PrintCFG.dgml/cpp/example/polkit/cfg.dot
Normal file
File diff suppressed because it is too large
Load Diff
BIN
PrintCFG.dgml/cpp/example/polkit/cfg.pdf
Normal file
BIN
PrintCFG.dgml/cpp/example/polkit/cfg.pdf
Normal file
Binary file not shown.
30
PrintCFG.ql
30
PrintCFG.ql
@@ -14,6 +14,36 @@ query predicate edges(ControlFlowNode n1, ControlFlowNode n2) {
|
|||||||
n1.getLocation().getFile().getBaseName() = "pkexec.c"
|
n1.getLocation().getFile().getBaseName() = "pkexec.c"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query predicate nodes(ControlFlowNode n1, string key, string value) {
|
||||||
|
exists(
|
||||||
|
RelationalOperation cmp, Parameter argc, ControlFlowNode startFrom, Variable n, ForStmt forloop
|
||||||
|
|
|
||||||
|
// Find the comparison
|
||||||
|
argc.getName() = "argc" and
|
||||||
|
argc.getAnAccess() = cmp.getAnOperand().getAChild*() and
|
||||||
|
n.getAnAccess() = cmp.getAnOperand().getAChild*() and
|
||||||
|
not n instanceof Parameter and
|
||||||
|
n.getName() = "n" and
|
||||||
|
forloop.getCondition() = cmp and
|
||||||
|
forloop.getControlFlowScope().getName() = "main" and
|
||||||
|
// Find the false branch's starting node
|
||||||
|
startFrom = cmp.getAFalseSuccessor() and
|
||||||
|
//
|
||||||
|
(edges(n1, _) or edges(_, n1)) and
|
||||||
|
(
|
||||||
|
if startFrom.getASuccessor*() = n1
|
||||||
|
then (
|
||||||
|
key = "color" and value = "red"
|
||||||
|
or
|
||||||
|
key = "line" and value = n1.getLocation().getStartLine().toString()
|
||||||
|
) else (
|
||||||
|
key = "color" and value = "black"
|
||||||
|
or
|
||||||
|
key = "line" and value = n1.getLocation().getStartLine().toString()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
// For reference, see the file
|
// For reference, see the file
|
||||||
// db/polkit-0.119.db/tmp/polkit/src/programs/pkexec.c
|
// db/polkit-0.119.db/tmp/polkit/src/programs/pkexec.c
|
||||||
// (after extracting src.zip)
|
// (after extracting src.zip)
|
||||||
|
|||||||
16
PrintCFG.sh
16
PrintCFG.sh
@@ -16,19 +16,21 @@ codeql database analyze \
|
|||||||
--format=dgml \
|
--format=dgml \
|
||||||
--output=PrintCFG.dgml
|
--output=PrintCFG.dgml
|
||||||
|
|
||||||
|
PRE=PrintCFG.dgml/cpp/example/polkit/cfg
|
||||||
|
|
||||||
# Clean up the dgml (xml) output
|
# Clean up the dgml (xml) output
|
||||||
tidy -xml PrintCFG.dgml/cpp/example/polkit/cfg.dgml | sponge PrintCFG.dgml/cpp/example/polkit/cfg.dgml
|
tidy -xml $PRE.dgml | sponge $PRE.dgml
|
||||||
|
|
||||||
# Convert dgml to dot
|
# Convert dgml to dot
|
||||||
./dgml2dot < PrintCFG.dgml/cpp/example/polkit/cfg.dgml > cfg.dot
|
./dgml2dot < $PRE.dgml > $PRE.dot
|
||||||
|
|
||||||
# Produce the DAG we really want
|
# Produce the layed-out DAG
|
||||||
dot -Tpdf < cfg.dot > cfg.pdf
|
dot -Tpdf < $PRE.dot > $PRE.pdf &
|
||||||
open cfg.pdf
|
open $PRE.pdf
|
||||||
|
|
||||||
# Faster than dot, as sanity check:
|
# Faster than dot, as sanity check:
|
||||||
sfdp -Tpdf < cfg.dot > cfg.sfdp.pdf
|
sfdp -Tpdf < $PRE.dot > $PRE.sfdp.pdf
|
||||||
open cfg.sfdp.pdf
|
open $PRE.sfdp.pdf
|
||||||
|
|
||||||
#* Full dot graph from codeql
|
#* Full dot graph from codeql
|
||||||
#
|
#
|
||||||
|
|||||||
Reference in New Issue
Block a user