private static boolean isSimpleCopy(Unit u) { if (!(u instanceof DefinitionStmt)) return false; DefinitionStmt defstmt = (DefinitionStmt) u; if (!(defstmt.getRightOp() instanceof Local)) return false; if (!(defstmt.getLeftOp() instanceof Local)) return false; return true; }
private Map<Pair<Unit, Set<String>>, Set<Unit>> createProvidesConfigMap( Collection<Unit> unitsInSelection, LiftedReachingDefinitions reachingDefinitions, Body body) { Map<Pair<Unit, Set<String>>, Set<Unit>> unitConfigurationMap = new HashMap<Pair<Unit, Set<String>>, Set<Unit>>(); for (Unit unitFromSelection : unitsInSelection) { if (unitFromSelection instanceof DefinitionStmt) { /* * exclude definitions when it's $temp on the leftOp. */ DefinitionStmt definition = (DefinitionStmt) unitFromSelection; Local leftOp = (Local) definition.getLeftOp(); if (leftOp.getName().charAt(0) == '$') { continue; } System.out.println("Definition:" + definition); // for every unit in the body... Iterator<Unit> iterator = body.getUnits().snapshotIterator(); while (iterator.hasNext()) { Unit nextUnit = iterator.next(); LiftedFlowSet<Collection<Set<Object>>> liftedFlowAfter = reachingDefinitions.getFlowAfter(nextUnit); Set<String>[] configurations = liftedFlowAfter.getConfigurations(); FlowSet[] lattices = liftedFlowAfter.getLattices(); // and for every configuration... for (int configurationIndex = 0; configurationIndex < configurations.length; configurationIndex++) { FlowSet flowSet = lattices[configurationIndex]; Set<String> currConfiguration = configurations[configurationIndex]; FeatureTag nextUnitTag = (FeatureTag) nextUnit.getTag("FeatureTag"); // if the unit belongs to the current configuration... if (nextUnitTag.belongsToConfiguration(currConfiguration)) { // if the definition reaches this unit... if (flowSet.contains(definition)) { List<ValueBox> useBoxes = nextUnit.getUseBoxes(); for (ValueBox vbox : useBoxes) { /* * and the definition is used, add to the * map... */ if (vbox.getValue().equivTo(leftOp)) { Pair<Unit, Set<String>> currentPair = new Pair<Unit, Set<String>>(definition, currConfiguration); Set<Unit> unitConfigurationReachesSet = unitConfigurationMap.get(currentPair); if (unitConfigurationReachesSet == null) { unitConfigurationReachesSet = new HashSet<Unit>(); unitConfigurationReachesSet.add(nextUnit); unitConfigurationMap.put(currentPair, unitConfigurationReachesSet); } else { unitConfigurationReachesSet.add(nextUnit); } } } } } } } } } return unitConfigurationMap; }
/** * Generate Policy Enforcement Point (PEP) for Unit 'unit'. * * @param unit * @param invExpr * @param body * @param dataFlowAvailable * @param assignmentStatement * @return */ private List<Unit> generatePolicyEnforcementPoint( Unit unit, InvokeExpr invExpr, Body body, int dataFlowAvailable, boolean assignmentStatement) { log.debug("Dataflow available: " + dataFlowAvailable); List<Unit> generated = new ArrayList<Unit>(); // store all new units that are generated String methodSignature = invExpr.getMethod().getSignature(); EventInformation eventInfo = allEventInformation.get(methodSignature); String eventName = eventInfo.getEventName(); Set<Pair<Integer, String>> allParameterInformation = eventInfo.getParameterInformation(); // This list containts types and parameters that are used to build the // invoke expression to "isStmtExecutionAllowed': // // java.lang.String "eventName" // IntType "dataFlowAvailable" // java.lang.Object[] "parameters" // List<Object> parameterForHelperMethod = new ArrayList<Object>(); List<Object> categories = new ArrayList<Object>(); // add event name information Type eventNameType = RefType.v("java.lang.String"); parameterForHelperMethod.add(eventNameType); StringConstant eventNameConstant = StringConstant.v(eventName); parameterForHelperMethod.add(eventNameConstant); // add information about dataflow availability parameterForHelperMethod.add(IntType.v()); parameterForHelperMethod.add(IntConstant.v(dataFlowAvailable)); // add information about parameters parameterForHelperMethod.add(getParameterArrayType()); List<Value> paramValues = new ArrayList<Value>(); for (Pair<Integer, String> parameterInfo : allParameterInformation) { paramValues.add(StringConstant.v("param" + parameterInfo.getLeft() + "value")); paramValues.add(invExpr.getArg(parameterInfo.getLeft())); } Pair<Value, List<Unit>> arrayRefAndInstrumentation = generateParameterArray(paramValues, body); generated.addAll(arrayRefAndInstrumentation.getRight()); parameterForHelperMethod.add(arrayRefAndInstrumentation.getLeft()); // Generate PEP call to the PDP. Store the result send by the PDP to 'resultPDPLocal' // Pseudo code looks like this: // // resultPDPLocal = isStmtExecutionAllowed(eventName, dataFlowAvailable, parameters); // StaticInvokeExpr sie = Instrumentation.createJimpleStaticInvokeExpr( Settings.INSTRUMENTATION_HELPER_JAVA, "isStmtExecutionAllowed", parameterForHelperMethod); Local resultPDPLocal = generateFreshLocal(body, soot.IntType.v()); AssignStmt asssCondition = Jimple.v().newAssignStmt(resultPDPLocal, sie); generated.add(asssCondition); for (Unit u : generated) { System.out.println("isStmt gen: " + u); } if (assignmentStatement) { // If the method call before which the PEP in inserted is an assignment statement of // the form "resultPDPLocal = originalCallThatIsChecked()", generate a new assignment // statement that stores a default value to "resultPDPLocal" if the PDP does not // allow the call of method originalCallThatIsChecked(). // // Pseudo-code: // // if(resultPDPLocal == 0) goto dummyLabel: // result = originalCallThatIsChecked(); // goto dummyLabel2: // dummyLabel: // result = dummyValue (i.e., 0 for IntType, false for BooleanType, ...) // dummyLabel2: // nop // if (unit instanceof DefinitionStmt) { DefinitionStmt defStmt = (DefinitionStmt) unit; Value pepCondition = Jimple.v().newEqExpr(resultPDPLocal, IntConstant.v(0)); // insert nop Unit label2Nop = Jimple.v().newNopStmt(); body.getUnits().insertAfter(label2Nop, unit); // insert result = dummyValue Unit dummyStatement = createCorrectDummyAssignment((Local) defStmt.getLeftOp()); body.getUnits().insertAfter(dummyStatement, unit); log.debug("insert c: " + dummyStatement); // insert goto dummyLabel2: body.getUnits().insertAfter(Jimple.v().newGotoStmt(label2Nop), unit); IfStmt ifStmt = Jimple.v().newIfStmt(pepCondition, dummyStatement); generated.add(ifStmt); } else { throw new RuntimeException( "error: expected DefinitionStmt got " + unit + " -> " + unit.getClass()); } } else { // If the method call before which the PEP in inserted is a call statement of // the form "originalCallThatIsChecked()", generate a new nop statement // to jump to if the PDP does not allow the call of method originalCallThatIsChecked(). // // Pseudo-code: // // if(resultPDPLocal == 0) goto nopLabel: // result = originalCallThatIsChecked(); // nopLabel: // nop // Value pepCondition = Jimple.v().newEqExpr(resultPDPLocal, IntConstant.v(0)); NopStmt nopStmt = Jimple.v().newNopStmt(); body.getUnits().insertAfter(nopStmt, unit); log.debug("insert d: " + nopStmt); IfStmt ifStmt = Jimple.v().newIfStmt(pepCondition, nopStmt); generated.add(ifStmt); } return generated; }
/** * @param cfg * @param sink * @param assignmentStatement */ private void instrumentSourceToSinkConnections( BiDiInterproceduralCFG<Unit, SootMethod> cfg, ResultSinkInfo sink, boolean assignmentStatement) { sourceSinkConnectionCounter += 1; // loop through the sinks for (ResultSinkInfo key : results.getResults().keySet()) { log.debug("compare: " + key); log.debug(" to: " + sink); // if the current sink is the sink at the unit tagged with 'sink' if (key.equals(sink)) { // loop through the sources for (ResultSourceInfo si : results.getResults().get(key)) { Stmt stmt = si.getSource(); SootMethod sm = cfg.getMethodOf(stmt); Body body = sm.retrieveActiveBody(); // Source instrumentation. The three type categories for the source are: // - callback // - ICC source method (i.e., Intent.getExtras()) // - not a callback and not an ICC source method (i.e., getLine1Number()) // if (isInterComponentSourceCallback(si, cfg)) { throw new RuntimeException("Callbacks as sources are not supported right now"); } else if (isInterComponentSourceNoCallback(si, cfg)) { // only invoke expression are treated here if (stmt.containsInvokeExpr()) { // only statements that return a android.os.Bundle are currently supported if (stmt instanceof DefinitionStmt) { DefinitionStmt defStmt = (DefinitionStmt) stmt; Value leftValue = defStmt.getLeftOp(); if (leftValue.getType().equals(RefType.v("android.os.Bundle"))) { List<Object> args = new ArrayList<Object>(); args.add(IntType.v()); args.add(IntConstant.v(sourceSinkConnectionCounter)); args.add(RefType.v("android.os.Bundle")); args.add(leftValue); InvokeExpr invExpr = Instrumentation.createJimpleStaticInvokeExpr( Settings.INSTRUMENTATION_HELPER_JAVA, "registerNewSourceSinkConnection", args); InvokeStmt invStmt = Jimple.v().newInvokeStmt(invExpr); Unit instrumentationPoint = null; if (stmt instanceof IdentityStmt) { instrumentationPoint = getLastIdentityStmt(body); } else { instrumentationPoint = stmt; } body.getUnits().insertAfter(invStmt, instrumentationPoint); log.debug("insert a: " + invStmt); } else { System.err.println("We do only support android.os.Bundle right now!"); } } } } else { String sourceCat = getSourceCategory(si); if (sourceCat != null) { List<Object> args = new ArrayList<Object>(); args.add(IntType.v()); args.add(IntConstant.v(sourceSinkConnectionCounter)); args.add(RefType.v("java.lang.String")); args.add(StringConstant.v(sourceCat)); InvokeExpr invExpr = Instrumentation.createJimpleStaticInvokeExpr( Settings.INSTRUMENTATION_HELPER_JAVA, "registerNewSourceSinkConnection", args); InvokeStmt invStmt = Jimple.v().newInvokeStmt(invExpr); Unit instrumentationPoint = null; if (stmt instanceof IdentityStmt) instrumentationPoint = getLastIdentityStmt(body); else instrumentationPoint = stmt; body.getUnits().insertAfter(invStmt, instrumentationPoint); log.debug("insert b: " + invStmt); } } // sink instrumentation if (sink.getSink().containsInvokeExpr()) { Body bodyOfSink = cfg.getMethodOf(key.getSink()).getActiveBody(); InvokeExpr invExpr = sink.getSink().getInvokeExpr(); List<Unit> generated = new ArrayList<Unit>(); generated.addAll( instrumentIntentAddings(cfg, stmt, invExpr, results.getResults().get(key))); EventInformation sinkEventInfo = allEventInformation.get(invExpr.getMethod().getSignature()); EventInformation sourceEventInfo = allEventInformation.get(si.getSource().getInvokeExpr().getMethod().getSignature()); generated.addAll( generatePolicyEnforcementPoint( key.getSink(), invExpr, bodyOfSink, sourceSinkConnectionCounter, assignmentStatement)); log.debug("body with data flow:\n" + body); for (Unit u : generated) { log.debug("gen: " + u); } if (sinkEventInfo.isInstrumentAfterStatement()) bodyOfSink.getUnits().insertAfter(generated, key.getSink()); else bodyOfSink.getUnits().insertBefore(generated, key.getSink()); } else throw new RuntimeException("Double-Check the assumption"); } // loop through the sources } // if the sink at the unit is the current sink } // loop through the sinks }