Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 48 additions & 30 deletions soot-infoflow/src/soot/jimple/infoflow/problems/AliasProblem.java
Original file line number Diff line number Diff line change
Expand Up @@ -120,21 +120,6 @@ private Set<Abstraction> computeAliases(final DefinitionStmt defStmt, Value left

final Set<Abstraction> res = new MutableTwoElementSet<Abstraction>();

// Check whether the left side of the assignment matches our
// current taint abstraction
final boolean leftSideMatches = Aliasing.baseMatches(leftValue, source);
if (!leftSideMatches)
res.add(source);
else {
// The left side is overwritten completely

// If we have an assignment to the base local of the current
// taint, all taint propagations must be below that point,
// so this is the right point to turn around.
for (Unit u : interproceduralCFG().getPredsOf(defStmt))
manager.getMainSolver().processEdge(new PathEdge<Unit, Abstraction>(d1, u, source));
}

// We only handle assignments and identity statements
if (defStmt instanceof IdentityStmt) {
res.add(source);
Expand All @@ -143,6 +128,12 @@ private Set<Abstraction> computeAliases(final DefinitionStmt defStmt, Value left
if (!(defStmt instanceof AssignStmt))
return res;

// Check whether the left side of the assignment matches our
// current taint abstraction
final boolean leftSideMatches = Aliasing.baseMatches(leftValue, source);
if (!leftSideMatches)
res.add(source);

// Get the right side of the assignment
final Value rightValue = BaseSelector.selectBase(defStmt.getRightOp(), false);

Expand Down Expand Up @@ -240,21 +231,12 @@ else if (defStmt.getRightOp() instanceof LengthExpr) {
newLeftAbs = checkAbstraction(source.deriveNewAbstraction(ap, defStmt));
}

if (newLeftAbs != null) {
// If we ran into a new abstraction that points to a
// primitive value, we can remove it
if (newLeftAbs.getAccessPath().getLastFieldType() instanceof PrimType)
return res;

if (!newLeftAbs.getAccessPath().equals(source.getAccessPath())) {
// Propagate the new alias upwards
res.add(newLeftAbs);

// Inject the new alias into the forward solver
for (Unit u : interproceduralCFG().getPredsOf(defStmt))
manager.getMainSolver()
.processEdge(new PathEdge<Unit, Abstraction>(d1, u, newLeftAbs));
}
if (newLeftAbs != null && !newLeftAbs.getAccessPath().equals(source.getAccessPath())) {
// Only inject the new alias into the forward solver but never propagate it upwards
// because the alias was created at this program point and won't be valid above.
for (Unit u : interproceduralCFG().getPredsOf(defStmt))
manager.getMainSolver()
.processEdge(new PathEdge<Unit, Abstraction>(d1, u, newLeftAbs));
}
}

Expand Down Expand Up @@ -734,6 +716,42 @@ public Set<Abstraction> computeTargets(Abstraction source, Abstraction d1,
if (abs != null) {
res.add(abs);
registerActivationCallSite(callSite, callee, abs);

// Check whether the call site created an alias by having two equal
// arguments, e.g. caller(o, o);. If yes, inject the other parameter
// back into the callee.
for (int argIndex = 0; !isReflectiveCallSite && argIndex < ie.getArgCount(); argIndex++) {
if (i != argIndex && originalCallArg == ie.getArg(argIndex)) {
AccessPath aliasAp = manager.getAccessPathFactory().copyWithNewValue(
source.getAccessPath(), paramLocals[argIndex],
source.getAccessPath().getBaseType(),
false);
Abstraction aliasAbs = checkAbstraction(
source.deriveNewAbstraction(aliasAp, (Stmt) exitStmt));

manager.getMainSolver()
.processEdge(new PathEdge<>(d1, exitStmt, aliasAbs));
}
}

// A foo(A a) {
// return a;
// }
// A b = foo(a);
// An alias is created using the returned value. If no assignment
// happen inside the method, also no handover is triggered. Thus,
// for this special case, we hand over the current taint and let the
// forward analysis find out whether the return value actually created
// an alias or not.
for (Unit u : manager.getICFG().getStartPointsOf(callee)) {
if (!(u instanceof ReturnStmt))
continue;

if (paramLocals[i] == ((ReturnStmt) u).getOp()) {
manager.getMainSolver().processEdge(new PathEdge<>(d1, exitStmt, source));
break;
}
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,7 @@
import soot.Type;
import soot.Unit;
import soot.Value;
import soot.jimple.ArrayRef;
import soot.jimple.AssignStmt;
import soot.jimple.BinopExpr;
import soot.jimple.CastExpr;
import soot.jimple.DefinitionStmt;
import soot.jimple.FieldRef;
import soot.jimple.IdentityStmt;
import soot.jimple.InstanceFieldRef;
import soot.jimple.InstanceInvokeExpr;
import soot.jimple.InstanceOfExpr;
import soot.jimple.InvokeExpr;
import soot.jimple.NewArrayExpr;
import soot.jimple.ReturnStmt;
import soot.jimple.StaticFieldRef;
import soot.jimple.Stmt;
import soot.jimple.UnopExpr;
import soot.jimple.*;
import soot.jimple.infoflow.InfoflowConfiguration;
import soot.jimple.infoflow.InfoflowManager;
import soot.jimple.infoflow.aliasing.Aliasing;
Expand Down Expand Up @@ -135,42 +120,57 @@ private Set<Abstraction> computeAliases(final DefinitionStmt defStmt, Abstractio

AccessPath ap = source.getAccessPath();
Value sourceBase = ap.getPlainValue();
Type rightType = rightOp.getType();
boolean handoverLeftValue = false;
boolean cutSubfield = false;
boolean leftSideOverwritten = false;
if (leftOp instanceof StaticFieldRef) {
if (manager.getConfig()
.getStaticFieldTrackingMode() != InfoflowConfiguration.StaticFieldTrackingMode.None
&& ap.firstFieldMatches(((StaticFieldRef) leftOp).getField())) {
handoverLeftValue = true;
cutSubfield = true;
}
} else if (leftOp instanceof InstanceFieldRef) {
InstanceFieldRef instRef = (InstanceFieldRef) leftOp;

// base matches
if (instRef.getBase() == sourceBase) {
// field matches
if (ap.firstFieldMatches(instRef.getField())) {
handoverLeftValue = true;
}
// whole object matches
else if (ap.getTaintSubFields() && ap.getFragmentCount() == 0) {
handoverLeftValue = true;
}
// due to cut down access path we can not know better
else if (source.dependsOnCutAP() || isCircularType(leftVal)) {
AccessPath mappedAp = Aliasing.getReferencedAPBase(ap,
new SootField[] { instRef.getField() }, manager);
if (mappedAp != null) {
handoverLeftValue = true;
cutSubfield = true;
if (!mappedAp.equals(ap))
ap = mappedAp;
}
}
} else if (leftVal == sourceBase) {
// Either the alias is overwritten here or a write to an array element
handoverLeftValue = leftOp instanceof ArrayRef;
handoverLeftValue = leftOp instanceof ArrayRef
&& ap.getArrayTaintType() != AccessPath.ArrayTaintType.Length;
leftSideOverwritten = !handoverLeftValue;
}

if (handoverLeftValue) {
// We found a missed path upwards
// inject same stmt in infoflow solver
handOver(d1, srcUnit, source);
Abstraction newAbs = null;
if (rightVal instanceof Constant) {
if (manager.getConfig().getImplicitFlowMode().trackControlFlowDependencies()) {
newAbs = source.deriveConditionalUpdate(assignStmt);
for (Unit pred : manager.getICFG().getPredsOf(srcUnit))
handOver(d1, pred, newAbs);
}
} else {
AccessPath newAp = manager.getAccessPathFactory().copyWithNewValue(ap, rightOp, rightType, cutSubfield);
newAbs = source.deriveNewAbstraction(newAp, assignStmt);
}

if (newAbs != null && !newAbs.equals(source)) {
// We found a missed path upwards
// inject same stmt in infoflow solver
for (Unit pred : manager.getICFG().getPredsOf(srcUnit))
handOver(d1, pred, newAbs);
}
}

if (leftSideOverwritten)
Expand Down
57 changes: 57 additions & 0 deletions soot-infoflow/test/soot/jimple/infoflow/test/HeapTestCode.java
Original file line number Diff line number Diff line change
Expand Up @@ -793,6 +793,24 @@ public void singleAliasTest() {
cm.publish(b.b);
}

public void negativeSingleAliasTest() {
A a = new A();
A b = fakeAlias(a);
a.b = TelephonyManager.getDeviceId();
ConnectionManager cm = new ConnectionManager();
cm.publish(b.b);
}

public A doNotFold() {
A a = new A();
System.out.println("XXX");
return a;
}

private A fakeAlias(A a) {
return doNotFold();
}

private int intData;

private void setIntData() {
Expand Down Expand Up @@ -1611,4 +1629,43 @@ public void activationStatementTest1() {
cm.publish(specialName);
}

public void callSiteCreatesAlias() {
String tainted = TelephonyManager.getDeviceId();

Book book1 = new Book();
leakingCallee(tainted, new Book(), book1);
leakingCallee(tainted, book1, book1);
}

void leakingCallee(String tainted, Book book1, Book book2) {
book1.name = tainted;
ConnectionManager cm = new ConnectionManager();
cm.publish(book2.name);
}

public Book alias;
public void lhsNotUpwardsInAliasFlow() {
alias = new Book();

Book book = new Book();
Book alias2 = alias;
alias = book; // alias only aliases book downwards from this program point
book.name = TelephonyManager.getDeviceId();
ConnectionManager cm = new ConnectionManager();
cm.publish(alias2.name);
}

public void identityStmtIsNotAGoodHandoverPoint() {
Book book = new Book();
// No need to propagate book forward again
callee(book);
book.name = TelephonyManager.getDeviceId();

ConnectionManager cm = new ConnectionManager();
cm.publish(book.name);
}

void callee(Book b) {
System.out.println(b);
}
}
56 changes: 52 additions & 4 deletions soot-infoflow/test/soot/jimple/infoflow/test/junit/HeapTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,7 @@
import org.junit.Ignore;
import org.junit.Test;

import soot.RefType;
import soot.Scene;
import soot.SootField;
import soot.SootMethod;
import soot.*;
import soot.jimple.AssignStmt;
import soot.jimple.DefinitionStmt;
import soot.jimple.InstanceInvokeExpr;
Expand All @@ -38,6 +35,7 @@
import soot.jimple.infoflow.data.SootMethodAndClass;
import soot.jimple.infoflow.entryPointCreators.DefaultEntryPointCreator;
import soot.jimple.infoflow.entryPointCreators.SequentialEntryPointCreator;
import soot.jimple.infoflow.handlers.TaintPropagationHandler;
import soot.jimple.infoflow.results.InfoflowResults;
import soot.jimple.infoflow.sourcesSinks.definitions.MethodSourceSinkDefinition;
import soot.jimple.infoflow.sourcesSinks.manager.ISourceSinkManager;
Expand Down Expand Up @@ -674,6 +672,18 @@ public void singleAliasTest() {
checkInfoflow(infoflow, 1);
}

@Test(timeout = 300000)
public void negativeSingleAliasTest() {
IInfoflow infoflow = initInfoflow();
infoflow.getConfig().setInspectSources(false);
infoflow.getConfig().setInspectSinks(false);

List<String> epoints = new ArrayList<String>();
epoints.add("<soot.jimple.infoflow.test.HeapTestCode: void negativeSingleAliasTest()>");
infoflow.computeInfoflow(appPath, libPath, epoints, sources, sinks);
negativeCheckInfoflow(infoflow);
}

@Test(timeout = 300000)
public void intAliasTest() {
IInfoflow infoflow = initInfoflow();
Expand Down Expand Up @@ -1269,4 +1279,42 @@ public void activationStatementTest1() {
negativeCheckInfoflow(infoflow);
}


@Test(timeout = 300000)
public void callSiteCreatesAlias() {
IInfoflow infoflow = initInfoflow();
List<String> epoints = new ArrayList<String>();
epoints.add("<soot.jimple.infoflow.test.HeapTestCode: void callSiteCreatesAlias()>");
infoflow.computeInfoflow(appPath, libPath, epoints, sources, sinks);
checkInfoflow(infoflow, 1);
}

@Test(timeout = 300000)
public void lhsNotUpwardsInAliasFlow() {
IInfoflow infoflow = initInfoflow();
List<String> epoints = new ArrayList<String>();
epoints.add("<soot.jimple.infoflow.test.HeapTestCode: void lhsNotUpwardsInAliasFlow()>");
infoflow.computeInfoflow(appPath, libPath, epoints, sources, sinks);
negativeCheckInfoflow(infoflow);
}

@Test(timeout = 300000)
public void identityStmtIsNotAGoodHandoverPoint() {
IInfoflow infoflow = initInfoflow();
List<String> epoints = new ArrayList<String>();
infoflow.setTaintPropagationHandler(new TaintPropagationHandler() {
@Override
public void notifyFlowIn(Unit stmt, Abstraction taint, InfoflowManager manager, FlowFunctionType type) {
Assert.assertTrue(taint.isAbstractionActive());
}

@Override
public Set<Abstraction> notifyFlowOut(Unit stmt, Abstraction d1, Abstraction incoming, Set<Abstraction> outgoing, InfoflowManager manager, FlowFunctionType type) {
return outgoing;
}
});
epoints.add("<soot.jimple.infoflow.test.HeapTestCode: void identityStmtIsNotAGoodHandoverPoint()>");
infoflow.computeInfoflow(appPath, libPath, epoints, sources, sinks);
checkInfoflow(infoflow, 1);
}
}