Skip to content

Commit 58ba24b

Browse files
author
Chris Casinghino
authored
User-provided space for patches (#138)
This adds a new config-file field for the user to provide us with information about regions in the binary that can be replaced with overflow patch code. It's threaded through to the patcher, which already had support for using that information.
1 parent abb8527 commit 58ba24b

File tree

18 files changed

+456
-8
lines changed

18 files changed

+456
-8
lines changed

bap-vibes/src/config.ml

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ type patch =
2727
patch_vars : Hvar.t list
2828
}
2929

30+
(** A type to represent known regions that may be overwritten with patch code *)
31+
type patch_space = {
32+
space_offset : int64;
33+
space_size : int64
34+
}
35+
3036
(* The configuration for a run of the VIBES pipeline. *)
3137
type t = {
3238
exe : string; (* The filename (path) of the executable to patch. *)
@@ -35,6 +41,7 @@ type t = {
3541
max_tries : int option; (* Optional number of CEGIS iterations to allow *)
3642
minizinc_model_filepath : string; (* Path to a minizinc model file *)
3743
ogre : string option;
44+
patch_spaces : patch_space list;
3845
wp_params : Wp_params.t;
3946
}
4047

@@ -52,6 +59,7 @@ let patched_exe_filepath t : string option = t.patched_exe_filepath
5259
let max_tries t : int option = t.max_tries
5360
let minizinc_model_filepath t : string = t.minizinc_model_filepath
5461
let ogre t : string option = t.ogre
62+
let patch_spaces t : patch_space list = t.patch_spaces
5563
let wp_params t : Wp_params.t = t.wp_params
5664

5765
(* For displaying a higher var. *)
@@ -94,6 +102,19 @@ let patch_to_string (p : patch) : string =
94102
let patches_to_string (ps : patch list) : string =
95103
String.concat ~sep:",\n" (List.map ~f:patch_to_string ps)
96104

105+
(* For displaying a patch space. *)
106+
let patch_space_to_string (p : patch_space) : string =
107+
String.concat ~sep:";\n" [
108+
Printf.sprintf " {";
109+
Printf.sprintf " Space_offset: %s" (Int64.to_string p.space_offset);
110+
Printf.sprintf " Space_size: %s" (Int64.to_string p.space_size);
111+
Printf.sprintf " }";
112+
]
113+
114+
(* For displaying a list of patch spaces *)
115+
let patch_spaces_to_string (ps : patch_space list) : string =
116+
String.concat ~sep:",\n" (List.map ~f:patch_space_to_string ps)
117+
97118
(* For displaying WP params. *)
98119
let wp_params_to_string (wp_params : Wp_params.t) : string =
99120
let opt (s : string option) : string =
@@ -109,7 +130,7 @@ let wp_params_to_string (wp_params : Wp_params.t) : string =
109130
let triple_list (t_list : (string * string * string) list) : string =
110131
lst @@ List.map t_list ~f:triple
111132
in
112-
let params = [
133+
let params = [
113134
Printf.sprintf "func: %s" wp_params.func;
114135
Printf.sprintf "precond: %s" wp_params.precond;
115136
Printf.sprintf "postcond: %s" wp_params.postcond;
@@ -118,11 +139,11 @@ let wp_params_to_string (wp_params : Wp_params.t) : string =
118139
Printf.sprintf "show: %s" (lst wp_params.show);
119140
Printf.sprintf "use-fun-input-regs: %b" wp_params.use_fun_input_regs;
120141
Printf.sprintf "fun-specs: %s" (lst wp_params.fun_specs);
121-
Printf.sprintf
142+
Printf.sprintf
122143
"user-fun-specs-orig: %s" (triple_list wp_params.user_func_specs_orig);
123144
Printf.sprintf
124145
"user-fun-specs-mod: %s" (triple_list wp_params.user_func_specs_mod);
125-
]
146+
]
126147
in
127148
String.concat ~sep:"\n" params
128149

@@ -132,9 +153,13 @@ let pp (ppf : Format.formatter) t : unit =
132153
Printf.sprintf "Exe: %s" t.exe;
133154
Printf.sprintf "Patches: %s" (patches_to_string t.patches);
134155
Printf.sprintf "Output filepath: %s"
135-
(Option.value t.patched_exe_filepath ~default:"none provided");
156+
(Option.value t.patched_exe_filepath ~default:"<none provided>");
136157
Printf.sprintf "Max tries: %d" (Option.value t.max_tries ~default:0);
137158
Printf.sprintf "Minizinc model: %s" t.minizinc_model_filepath;
159+
Printf.sprintf "Ogre file: %s"
160+
(Option.value t.ogre ~default:"<none provided>");
161+
Printf.sprintf "Patch spaces: %s"
162+
(patch_spaces_to_string t.patch_spaces);
138163
Printf.sprintf "WP-params: %s" (wp_params_to_string t.wp_params);
139164
] in
140165
Format.fprintf ppf "@[%s@]@." info
@@ -156,7 +181,8 @@ let create
156181
~max_tries:(max_tries : int option)
157182
~minizinc_model_filepath:(minizinc_model_filepath : string)
158183
~ogre:(ogre : string option)
184+
~patch_spaces:(patch_spaces : patch_space list)
159185
~wp_params:(wp_params : Wp_params.t)
160186
: t =
161-
{ exe; patches; patched_exe_filepath;
162-
max_tries; minizinc_model_filepath; ogre; wp_params }
187+
{ exe; patches; patched_exe_filepath; max_tries;
188+
minizinc_model_filepath; ogre; patch_spaces; wp_params }

bap-vibes/src/config.mli

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ type t
1515
(** A type to represent patch cody which may either be C or literal assembly *)
1616
type patch_code = CCode of Cabs.definition | ASMCode of string
1717

18+
(** A type to represent known regions that may be overwritten with patch code *)
19+
type patch_space = {
20+
space_offset : int64;
21+
space_size : int64
22+
}
23+
1824
(** [patch_name p] returns the name of the patch [p]. *)
1925
val patch_name : patch -> string
2026

@@ -53,6 +59,10 @@ val ogre : t -> string option
5359
(** [wp_params config] returns the input parameters for the invocation to WP *)
5460
val wp_params : t -> Wp_params.t
5561

62+
(** [patch_spaces config] returns known dead regions suitable for patch
63+
placement *)
64+
val patch_spaces : t -> patch_space list
65+
5666
(** [pp ppf config] is a pretty printer for a configuration record. *)
5767
val pp : Format.formatter -> t -> unit
5868

@@ -79,6 +89,8 @@ val create_patch :
7989
- [~max_tries] is the optional number of tries to allow
8090
- [~minizinc_model_filepath] is the minizinc model file location
8191
- [~ogre] is the optional filepath to an ogre file
92+
- [~patch_spaces] is the list of known empty regions for patch code (which
93+
may be empty)
8294
- [~wp_params] is the parameter struct for WP *)
8395
val create :
8496
exe:string
@@ -87,5 +99,6 @@ val create :
8799
-> max_tries : int option
88100
-> minizinc_model_filepath:string
89101
-> ogre:string option
102+
-> patch_spaces:patch_space list
90103
-> wp_params:Wp_params.t
91104
-> t

bap-vibes/src/data.ml

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,11 @@ let int_domain : int option KB.Domain.t = KB.Domain.optional
2828
~equal:Int.(=)
2929
"int-domain"
3030

31+
(* Optional int64 domain *)
32+
let int64_domain : int64 option KB.Domain.t = KB.Domain.optional
33+
~equal:Int64.(=)
34+
"int64-domain"
35+
3136
(* Optional bitvector domain *)
3237
let bitvec_domain : Bitvec.t option KB.Domain.t = KB.Domain.optional
3338
~equal:Bitvec.equal
@@ -246,9 +251,60 @@ end
246251
(* Sets of patches *)
247252
module Patch_set = Set.Make (Patch)
248253

254+
(* Properties pertaining to space for patches *)
255+
module Patch_space = struct
256+
257+
(* Declare patche spaces as a KB class. A patch space is a KB object of its
258+
own corresponding to a single region of space available for patch code. We
259+
may know of multiple such regions. *)
260+
type patch_space_cls
261+
let patch_space : (patch_space_cls, unit) KB.cls =
262+
KB.Class.declare ~package "patch-space" ()
263+
264+
(* This provides equality / comparisons for objects of this class *)
265+
include (val KB.Object.derive patch_space)
266+
267+
let offset : (patch_space_cls, int64 option) KB.slot =
268+
KB.Class.property ~package patch_space "patch-space-offset" int64_domain
269+
270+
let size : (patch_space_cls, int64 option) KB.slot =
271+
KB.Class.property ~package patch_space "patch-space-size" int64_domain
272+
273+
let set_offset (obj : t) (data : int64 option) : unit KB.t =
274+
KB.provide offset obj data
275+
276+
let get_offset (obj : t) : int64 option KB.t =
277+
KB.collect offset obj
278+
279+
let get_offset_exn (obj : t) : int64 KB.t =
280+
get_offset obj >>= fun result ->
281+
match result with
282+
| None -> Kb_error.fail Kb_error.Missing_patch_space_offset
283+
| Some value -> KB.return value
284+
285+
let set_size (obj : t) (data : int64 option) : unit KB.t =
286+
KB.provide size obj data
287+
288+
let get_size (obj : t) : int64 option KB.t =
289+
KB.collect size obj
290+
291+
let get_size_exn (obj : t) : int64 KB.t =
292+
get_size obj >>= fun result ->
293+
match result with
294+
| None -> Kb_error.fail Kb_error.Missing_patch_space_size
295+
| Some value -> KB.return value
296+
end
297+
298+
(* Sets of patch spaces *)
299+
module Patch_space_set = Set.Make (Patch_space)
300+
249301
(* Properties pertaining to the original executable *)
250302
module Original_exe = struct
251303

304+
let patch_spaces_domain : Patch_space_set.t KB.domain =
305+
KB.Domain.flat ~empty:Patch_space_set.empty ~equal:Patch_space_set.equal
306+
"patch-spaces"
307+
252308
let filepath : (cls, string option) KB.slot =
253309
KB.Class.property ~package cls "original-exe-filepath"
254310
string_domain
@@ -257,6 +313,10 @@ module Original_exe = struct
257313
KB.Class.property ~package cls "original-exe-target"
258314
Theory.Target.domain
259315

316+
let patch_spaces : (cls, Patch_space_set.t) KB.slot =
317+
KB.Class.property ~package cls "original-exe-patch-spaces"
318+
patch_spaces_domain
319+
260320
let set_filepath (obj : t) (data : string option) : unit KB.t =
261321
KB.provide filepath obj data
262322

@@ -282,6 +342,12 @@ module Original_exe = struct
282342
else
283343
KB.return tgt
284344

345+
let set_patch_spaces (obj : t) (data : Patch_space_set.t) : unit KB.t =
346+
KB.provide patch_spaces obj data
347+
348+
let get_patch_spaces (obj : t) : Patch_space_set.t KB.t =
349+
KB.collect patch_spaces obj
350+
285351
end
286352

287353
(* Properties pertaining to the patched executable *)

bap-vibes/src/data.mli

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ module Hvar = Higher_var
1111
(** We define "domains" for the types used in our properties. *)
1212
val string_domain : string option KB.Domain.t
1313
val int_domain : int option KB.Domain.t
14+
val int64_domain : int64 option KB.Domain.t
1415
val bitvec_domain : Bitvec.t option KB.Domain.t
1516
val sexp_domain : Sexp.t option KB.Domain.t
1617
val source_domain : Cabs.definition option KB.Domain.t
@@ -113,10 +114,40 @@ end
113114
(** Sets of patches *)
114115
module Patch_set : Set.S with type Elt.t = Patch.t
115116

117+
(** The Patch_space module defines an additional class holding all properties
118+
related to regions in the original binary that can be used for the patch
119+
(e.g., dead code). *)
120+
module Patch_space : sig
121+
122+
(* The KB infrastructure *)
123+
type patch_space_cls
124+
type t = patch_space_cls KB.obj
125+
val patch_space : (patch_space_cls, unit) KB.cls
126+
127+
(* equal, compare, and other things for patch spaces *)
128+
include Knowledge.Object.S with type t := t
129+
130+
val offset : (patch_space_cls, int64 option) KB.slot
131+
val size : (patch_space_cls, int64 option) KB.slot
132+
133+
val set_offset : t -> int64 option -> unit KB.t
134+
val get_offset : t -> int64 option KB.t
135+
val get_offset_exn : t -> int64 KB.t
136+
137+
val set_size : t -> int64 option -> unit KB.t
138+
val get_size : t -> int64 option KB.t
139+
val get_size_exn : t -> int64 KB.t
140+
end
141+
142+
(** Sets of patch spaces *)
143+
144+
module Patch_space_set : Set.S with type Elt.t = Patch_space.t
145+
116146
(** Properties pertaining to the original executable *)
117147
module Original_exe : sig
118148
val filepath : (cls, string option) KB.slot
119149
val target : (cls, Theory.target) KB.slot
150+
val patch_spaces : (cls, Patch_space_set.t) KB.slot
120151

121152
val set_filepath : t -> string option -> unit KB.t
122153
val get_filepath : t -> string option KB.t
@@ -128,6 +159,9 @@ module Original_exe : sig
128159
(** Raises if the target is empty *)
129160
val get_target_exn : t -> Theory.target KB.t
130161

162+
val set_patch_spaces : t -> Patch_space_set.t -> unit KB.t
163+
val get_patch_spaces : t -> Patch_space_set.t KB.t
164+
131165
end
132166

133167
(** Properties pertaining to the patched executable *)

bap-vibes/src/kb_error.ml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ type t =
2020
| Missing_patch_size
2121
| Missing_lower_patch_code
2222
| Missing_patch_vars
23+
| Missing_patch_space_offset
24+
| Missing_patch_space_size
2325
| Missing_func
2426
| Missing_property
2527
| Missing_raw_ir
@@ -57,6 +59,8 @@ let pp ppf (e : t) =
5759
| Missing_patch_size -> "No patch size was stashed in KB"
5860
| Missing_lower_patch_code -> "No lower patch code was stashed in KB"
5961
| Missing_patch_vars -> "No patch vars were stashed in KB"
62+
| Missing_patch_space_offset -> "No patch space offset was stashed in KB"
63+
| Missing_patch_space_size -> "No patch space size was stashed in KB"
6064
| Missing_func -> "No function name to verify was stashed in KB"
6165
| Missing_property -> "No correctness property was stashed in KB"
6266
| Missing_raw_ir -> "Raw Ir compiled from core_theory not found in KB"

bap-vibes/src/kb_error.mli

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ type t =
2222
| Missing_patch_size
2323
| Missing_lower_patch_code
2424
| Missing_patch_vars
25+
| Missing_patch_space_offset
26+
| Missing_patch_space_size
2527
| Missing_func
2628
| Missing_property
2729
| Missing_raw_ir

bap-vibes/src/patcher.ml

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,26 @@ let reify_patch
351351
orig_loc = patch_file_offset;
352352
orig_size = Int64.of_int patch_size}
353353

354+
(* Turn a KB patch space into a patch site (the type used by this module to
355+
represent the same information *)
356+
let reify_patch_site (obj : Data.Patch_space.t) : patch_site KB.t =
357+
let open KB.Let in
358+
let* location = Data.Patch_space.get_offset_exn obj in
359+
let* size = Data.Patch_space.get_size_exn obj in
360+
KB.return {location; size}
361+
362+
(* Get the patch_spaces out of the kb monad and into the form used by this
363+
module *)
364+
let reify_patch_sites (obj : Data.t) : patch_site list KB.t =
365+
let open KB.Let in
366+
let* patch_space_set : Data.Patch_space_set.t =
367+
Data.Original_exe.get_patch_spaces obj
368+
in
369+
let patch_spaces : Data.Patch_space.t list =
370+
Data.Patch_space_set.to_list patch_space_set
371+
in
372+
KB.List.map ~f:reify_patch_site patch_spaces
373+
354374
(* Patches the original exe, to produce a patched exe. *)
355375
let patch
356376
?compute_region:(compute_region=ogre_compute_region)
@@ -369,7 +389,9 @@ let patch
369389
let reify_patch = reify_patch
370390
~compute_region:compute_region ~exe_unit:original_exe_unit in
371391
let* patch_list = KB.List.map ~f:reify_patch patch_list in
372-
let patch_sites = naive_find_patch_sites original_exe_filename in
392+
let naive_patch_sites = naive_find_patch_sites original_exe_filename in
393+
let* provided_patch_sites = reify_patch_sites obj in
394+
let patch_sites = naive_patch_sites @ provided_patch_sites in
373395
let* lang =
374396
let patch = Data.Patch_set.choose_exn patches in
375397
Data.Patch.get_lang patch

0 commit comments

Comments
 (0)