1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
open Core_kernel
open Bap.Std
open Log_utils
let name = "CWE367"
let version = "0.1"
let get_calls_to_symbol symbol_name callsites program =
match Symbol_utils.find_symbol program symbol_name with
| Some symbol ->
begin
Seq.filter callsites ~f:(fun callsite -> match Jmp.kind callsite with
| Goto _ | Ret _ | Int (_,_) -> false
| Call destination -> match Call.target destination with
| Direct addr -> addr = symbol
| _ -> false)
end
| None -> Seq.empty
let get_blk_tid_of_tid sub tid =
let blk = Seq.find (Term.enum blk_t sub) ~f:(
fun b ->
match Term.last jmp_t b with
| Some last_term -> tid = (Term.tid last_term)
| None -> false) in
match blk with
| Some b -> Term.tid b
| _ -> assert(false)
let is_reachable sub source sink =
let cfg = Sub.to_graph sub in
let source_tid = Term.tid source in
let sink_tid = Term.tid sink in
let source_blk = get_blk_tid_of_tid sub source_tid in
let sink_blk = get_blk_tid_of_tid sub sink_tid in
Graphlib.Std.Graphlib.is_reachable (module Graphs.Tid) cfg source_blk sink_blk
let handle_sub sub program tid_map _symbols source_sink_pair =
match source_sink_pair with
| [source;sink;] -> begin
if (Symbol_utils.sub_calls_symbol program sub source) && (Symbol_utils.sub_calls_symbol program sub sink) then
begin
let calls = Symbol_utils.get_direct_callsites_of_sub sub in
let source_calls = get_calls_to_symbol source calls program in
let sink_calls = get_calls_to_symbol sink calls program in
Seq.iter source_calls ~f:(fun source_call ->
Seq.iter sink_calls ~f:(fun sink_call ->
if is_reachable sub source_call sink_call then
let address = (Address_translation.translate_tid_to_assembler_address_string (Term.tid sub) tid_map) in
let tid = Address_translation.tid_to_string @@ Term.tid sub in
let symbol = (Term.name sub) in
let other = [["source"; source]; ["sink"; sink]] in
let description = sprintf
"(Time-of-check Time-of-use Race Condition) %s is reachable from %s at %s (%s). This could lead to a TOCTOU."
sink
source
address
symbol in
let cwe_warning = cwe_warning_factory
name
version
description
~other:other
~addresses:[address]
~tids:[tid]
~symbols:[symbol] in
collect_cwe_warning cwe_warning
else
()))
end
else
()
end
| _ -> ()
let check_cwe program _proj tid_map symbol_pairs _ =
List.iter symbol_pairs ~f:(fun current_pair ->
let symbols = Symbol_utils.build_symbols current_pair in
Seq.iter (Term.enum sub_t program) ~f:(fun s -> handle_sub s program tid_map symbols current_pair))