[quandary] cheaper handling of unknown code

Summary:
Let's introduce some concepts. A "known unknown" function is one for which no Java code exists (e.g., `native`, `abstract`, and `interface methods`). An "unknown unknown" function is one for which Java code may or may not exist, but we don't have the code or we choose not to analyze it (e.g., non-modeled methods from the core Java or Android libraries).

Previously, Quandary handled both known unknowns and unknown unknowns by propagating taint from the parameters of the unknown function to its return value. It turns out that it is really expensive to do this for known unknown functions. D4142697 was the diff that starting handling known unknown functions in this way, and bisecting shows that it was the start of the recent performance problems for Quandary.

This diff essentially reverts D4142697 by handling known unknowns as skips instead. Pragmatically, doing the propagation trick for Java/Android library functions (e.g., `String` functions!) matters much more, so i'm not too worried about the missed behaviors from this. Ideally, we will go back to the old handling once performance has improved (have lots of ideas there). But I need this to unblock me in the meantime.

Reviewed By: jeremydubreil

Differential Revision: D4205507

fbshipit-source-id: 79cb9c8
master
Sam Blackshear 8 years ago committed by Facebook Github Bot
parent 8301250213
commit 935018ae9e

@ -21,7 +21,12 @@ module Summary = Summary.Make(struct
{ payload with Specs.quandary = Some summary; } { payload with Specs.quandary = Some summary; }
let read_from_payload payload = let read_from_payload payload =
payload.Specs.quandary match payload.Specs.quandary with
| None ->
(* abstract/native/interface methods will have None as a summary. treat them as skip *)
Some []
| summary_opt ->
summary_opt
end) end)
module Make (TaintSpec : TaintSpec.S) = struct module Make (TaintSpec : TaintSpec.S) = struct
@ -526,12 +531,6 @@ module Make (TaintSpec : TaintSpec.S) = struct
AccessPath.BaseMap.empty AccessPath.BaseMap.empty
formals_with_nums in formals_with_nums in
let has_body pdesc =
let attrs = Procdesc.get_attributes pdesc in
attrs.is_defined && not attrs.is_abstract in
if has_body pdesc
then
begin
Preanal.doit ~handle_dynamic_dispatch:true pdesc dummy_cg tenv; Preanal.doit ~handle_dynamic_dispatch:true pdesc dummy_cg tenv;
let formals = make_formal_access_paths pdesc in let formals = make_formal_access_paths pdesc in
let proc_data = ProcData.make pdesc tenv formals in let proc_data = ProcData.make pdesc tenv formals in
@ -540,9 +539,9 @@ module Make (TaintSpec : TaintSpec.S) = struct
let summary = make_summary formals access_tree in let summary = make_summary formals access_tree in
Summary.write_summary (Procdesc.get_proc_name pdesc) summary; Summary.write_summary (Procdesc.get_proc_name pdesc) summary;
| None -> | None ->
if not (Procdesc.is_body_empty pdesc) if Procdesc.Node.get_succs (Procdesc.get_start_node pdesc) <> []
then failwith "Couldn't compute post" then failwith "Couldn't compute post" in
end in
let callbacks = let callbacks =
{ {
Ondemand.analyze_ondemand; Ondemand.analyze_ondemand;

@ -23,24 +23,6 @@ public abstract class UnknownCode {
Object interfaceMethod(Object o); Object interfaceMethod(Object o);
} }
void propagateViaUnknownNativeCodeBad() {
Object source = InferTaint.inferSecretSource();
Object launderedSource = nativeMethod(source);
InferTaint.inferSensitiveSink(launderedSource);
}
static void propagateViaUnknownAbstractCodeBad() {
Object source = InferTaint.inferSecretSource();
Object launderedSource = nativeMethod(source);
InferTaint.inferSensitiveSink(launderedSource);
}
static void propagateViaInterfaceCodeBad(Interface i) {
Object source = InferTaint.inferSecretSource();
Object launderedSource = i.interfaceMethod(source);
InferTaint.inferSensitiveSink(launderedSource);
}
static void propagateViaUnknownConstructorBad() { static void propagateViaUnknownConstructorBad() {
String source = (String) InferTaint.inferSecretSource(); String source = (String) InferTaint.inferSecretSource();
// we don't analyze the code for the core Java libraries, so this constructor will be unknown // we don't analyze the code for the core Java libraries, so this constructor will be unknown
@ -61,4 +43,22 @@ public abstract class UnknownCode {
InferTaint.inferSensitiveSink(launderedSource3); InferTaint.inferSensitiveSink(launderedSource3);
} }
static void FN_propagateViaInterfaceCodeBad(Interface i) {
Object source = InferTaint.inferSecretSource();
Object launderedSource = i.interfaceMethod(source);
InferTaint.inferSensitiveSink(launderedSource);
}
void FN_propagateViaUnknownNativeCodeBad() {
Object source = InferTaint.inferSecretSource();
Object launderedSource = nativeMethod(source);
InferTaint.inferSensitiveSink(launderedSource);
}
static void FN_propagateViaUnknownAbstractCodeBad() {
Object source = InferTaint.inferSecretSource();
Object launderedSource = nativeMethod(source);
InferTaint.inferSensitiveSink(launderedSource);
}
} }

@ -31,10 +31,10 @@ DynamicDispatch.java, void DynamicDispatch.FP_propagateViaConcreteTypeOk(), 10,
DynamicDispatch.java, void DynamicDispatch.callSinkViaInterfaceBad(DynamicDispatch$Interface), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void DynamicDispatch$BadInterfaceImpl2.callSink(Object),call to void InferTaint.inferSensitiveSink(Object)] DynamicDispatch.java, void DynamicDispatch.callSinkViaInterfaceBad(DynamicDispatch$Interface), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void DynamicDispatch$BadInterfaceImpl2.callSink(Object),call to void InferTaint.inferSensitiveSink(Object)]
DynamicDispatch.java, void DynamicDispatch.callSinkViaInterfaceBad(DynamicDispatch$Interface), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void DynamicDispatch$BadInterfaceImpl1.callSink(Object),call to void InferTaint.inferSensitiveSink(Object)] DynamicDispatch.java, void DynamicDispatch.callSinkViaInterfaceBad(DynamicDispatch$Interface), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void DynamicDispatch$BadInterfaceImpl1.callSink(Object),call to void InferTaint.inferSensitiveSink(Object)]
DynamicDispatch.java, void DynamicDispatch.callSinkViaSubtypeBad(DynamicDispatch$Supertype), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void DynamicDispatch$BadSubtype.callSink(Object),call to void InferTaint.inferSensitiveSink(Object)] DynamicDispatch.java, void DynamicDispatch.callSinkViaSubtypeBad(DynamicDispatch$Supertype), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void DynamicDispatch$BadSubtype.callSink(Object),call to void InferTaint.inferSensitiveSink(Object)]
DynamicDispatch.java, void DynamicDispatch.propagateViaInterfaceBad(DynamicDispatch$Interface), 3, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),flow through Object DynamicDispatch$BadInterfaceImpl1.propagate(Object),flow through Object DynamicDispatch$BadInterfaceImpl2.propagate(Object),flow through Object DynamicDispatch$Interface.propagate(Object),call to void InferTaint.inferSensitiveSink(Object)] DynamicDispatch.java, void DynamicDispatch.propagateViaInterfaceBad(DynamicDispatch$Interface), 3, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),flow through Object DynamicDispatch$BadInterfaceImpl1.propagate(Object),flow through Object DynamicDispatch$BadInterfaceImpl2.propagate(Object),call to void InferTaint.inferSensitiveSink(Object)]
DynamicDispatch.java, void DynamicDispatch.propagateViaSubtypeBad(DynamicDispatch$Supertype), 3, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),flow through Object DynamicDispatch$BadSubtype.propagate(Object),call to void InferTaint.inferSensitiveSink(Object)] DynamicDispatch.java, void DynamicDispatch.propagateViaSubtypeBad(DynamicDispatch$Supertype), 3, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),flow through Object DynamicDispatch$BadSubtype.propagate(Object),call to void InferTaint.inferSensitiveSink(Object)]
DynamicDispatch.java, void DynamicDispatch.returnSourceViaInterfaceBad(DynamicDispatch$Interface), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),return from Object DynamicDispatch$BadInterfaceImpl1.returnSource(),flow through Object DynamicDispatch$Interface.returnSource(),call to void InferTaint.inferSensitiveSink(Object)] DynamicDispatch.java, void DynamicDispatch.returnSourceViaInterfaceBad(DynamicDispatch$Interface), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),return from Object DynamicDispatch$BadInterfaceImpl1.returnSource(),call to void InferTaint.inferSensitiveSink(Object)]
DynamicDispatch.java, void DynamicDispatch.returnSourceViaInterfaceBad(DynamicDispatch$Interface), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),return from Object DynamicDispatch$BadInterfaceImpl2.returnSource(),flow through Object DynamicDispatch$Interface.returnSource(),call to void InferTaint.inferSensitiveSink(Object)] DynamicDispatch.java, void DynamicDispatch.returnSourceViaInterfaceBad(DynamicDispatch$Interface), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),return from Object DynamicDispatch$BadInterfaceImpl2.returnSource(),call to void InferTaint.inferSensitiveSink(Object)]
DynamicDispatch.java, void DynamicDispatch.returnSourceViaSubtypeBad(DynamicDispatch$Supertype), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),return from Object DynamicDispatch$BadSubtype.returnSource(),call to void InferTaint.inferSensitiveSink(Object)] DynamicDispatch.java, void DynamicDispatch.returnSourceViaSubtypeBad(DynamicDispatch$Supertype), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),return from Object DynamicDispatch$BadSubtype.returnSource(),call to void InferTaint.inferSensitiveSink(Object)]
Exceptions.java, void Exceptions.callSinkThenThrowBad(), 1, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void Exceptions.callSinkThenThrow(Object),call to void InferTaint.inferSensitiveSink(Object)] Exceptions.java, void Exceptions.callSinkThenThrowBad(), 1, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void Exceptions.callSinkThenThrow(Object),call to void InferTaint.inferSensitiveSink(Object)]
Exceptions.java, void Exceptions.sinkAfterCatchBad(), 7, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void InferTaint.inferSensitiveSink(Object)] Exceptions.java, void Exceptions.sinkAfterCatchBad(), 7, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),call to void InferTaint.inferSensitiveSink(Object)]
@ -155,7 +155,4 @@ Strings.java, void Strings.viaStringBufferIgnoreReturnBad(), 4, QUANDARY_TAINT_E
Strings.java, void Strings.viaStringBuilderBad(), 3, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),flow through StringBuilder StringBuilder.append(Object),flow through StringBuilder StringBuilder.append(String),flow through String StringBuilder.toString(),call to void InferTaint.inferSensitiveSink(Object)] Strings.java, void Strings.viaStringBuilderBad(), 3, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),flow through StringBuilder StringBuilder.append(Object),flow through StringBuilder StringBuilder.append(String),flow through String StringBuilder.toString(),call to void InferTaint.inferSensitiveSink(Object)]
Strings.java, void Strings.viaStringBuilderIgnoreReturnBad(), 5, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),flow through StringBuilder StringBuilder.append(Object),flow through String StringBuilder.toString(),call to void InferTaint.inferSensitiveSink(Object)] Strings.java, void Strings.viaStringBuilderIgnoreReturnBad(), 5, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),flow through StringBuilder StringBuilder.append(Object),flow through String StringBuilder.toString(),call to void InferTaint.inferSensitiveSink(Object)]
Strings.java, void Strings.viaStringBuilderSugarBad(), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),flow through StringBuilder StringBuilder.append(Object),flow through StringBuilder StringBuilder.append(String),flow through String StringBuilder.toString(),call to void InferTaint.inferSensitiveSink(Object)] Strings.java, void Strings.viaStringBuilderSugarBad(), 2, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),flow through StringBuilder StringBuilder.append(Object),flow through StringBuilder StringBuilder.append(String),flow through String StringBuilder.toString(),call to void InferTaint.inferSensitiveSink(Object)]
UnknownCode.java, void UnknownCode.propagateViaInterfaceCodeBad(UnknownCode$Interface), 3, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),flow through Object UnknownCode$Interface.interfaceMethod(Object),call to void InferTaint.inferSensitiveSink(Object)]
UnknownCode.java, void UnknownCode.propagateViaUnknownAbstractCodeBad(), 3, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),flow through Object UnknownCode.nativeMethod(Object),call to void InferTaint.inferSensitiveSink(Object)]
UnknownCode.java, void UnknownCode.propagateViaUnknownConstructorBad(), 4, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),flow through String.<init>(String),call to void InferTaint.inferSensitiveSink(Object)] UnknownCode.java, void UnknownCode.propagateViaUnknownConstructorBad(), 4, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),flow through String.<init>(String),call to void InferTaint.inferSensitiveSink(Object)]
UnknownCode.java, void UnknownCode.propagateViaUnknownNativeCodeBad(), 3, QUANDARY_TAINT_ERROR, [return from Object InferTaint.inferSecretSource(),flow through Object UnknownCode.nativeMethod(Object),call to void InferTaint.inferSensitiveSink(Object)]

Loading…
Cancel
Save