mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Add support for Slices
This commit is contained in:
@@ -2,10 +2,8 @@
|
||||
|
||||
import java
|
||||
private import semmle.code.java.dataflow.ExternalFlow
|
||||
private import semmle.code.java.dataflow.TaintTracking
|
||||
private import semmle.code.java.frameworks.android.Intent
|
||||
|
||||
private class PendingIntentModels extends SinkModelCsv {
|
||||
private class PendingIntentCreationModels extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
@@ -17,6 +15,16 @@ private class PendingIntentModels extends SinkModelCsv {
|
||||
}
|
||||
}
|
||||
|
||||
private class PendingIntentSentSinkModels extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
"androidx.slice;SliceProvider;true;onBindSlice;;;ReturnValue;pending-intent-sent",
|
||||
"androidx.slice;SliceProvider;true;onCreatePermissionRequest;;;ReturnValue;pending-intent-sent"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Remove when https://github.com/github/codeql/pull/6397 gets merged
|
||||
private class DefaultIntentRedirectionSinkModel extends SinkModelCsv {
|
||||
override predicate row(string row) {
|
||||
|
||||
@@ -17,16 +17,7 @@ class ImplicitPendingIntentStartConf extends TaintTracking::Configuration {
|
||||
source.asExpr() instanceof ImplicitPendingIntentCreation
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
sink instanceof IntentStartSink and
|
||||
// startService can't actually start implicit intents since API 21
|
||||
not exists(MethodAccess ma, Method m |
|
||||
ma.getMethod() = m and
|
||||
m.getDeclaringType().getASupertype*() instanceof TypeContext and
|
||||
m.hasName("startService") and
|
||||
sink.asExpr() = ma.getArgument(0)
|
||||
)
|
||||
}
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof SendPendingIntent }
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node sanitizer) {
|
||||
sanitizer instanceof ExplicitIntentSanitizer
|
||||
@@ -49,8 +40,19 @@ private class ImplicitPendingIntentCreation extends Expr {
|
||||
}
|
||||
}
|
||||
|
||||
private class IntentStartSink extends DataFlow::Node {
|
||||
IntentStartSink() { sinkNode(this, "intent-start") }
|
||||
private class SendPendingIntent extends DataFlow::Node {
|
||||
SendPendingIntent() {
|
||||
sinkNode(this, "intent-start") and
|
||||
// startService can't actually start implicit intents since API 21
|
||||
not exists(MethodAccess ma, Method m |
|
||||
ma.getMethod() = m and
|
||||
m.getDeclaringType().getASupertype*() instanceof TypeContext and
|
||||
m.hasName("startService") and
|
||||
this.asExpr() = ma.getArgument(0)
|
||||
)
|
||||
or
|
||||
sinkNode(this, "pending-intent-sent")
|
||||
}
|
||||
}
|
||||
|
||||
private class ImplicitPendingIntentConf extends DataFlow2::Configuration {
|
||||
|
||||
@@ -1,9 +1,21 @@
|
||||
package com.example.test;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import android.app.Activity;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.AssetFileDescriptor;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.CancellationSignal;
|
||||
import android.os.RemoteException;
|
||||
import androidx.core.graphics.drawable.IconCompat;
|
||||
import androidx.slice.Slice;
|
||||
import androidx.slice.SliceProvider;
|
||||
import androidx.slice.builders.ListBuilder;
|
||||
import androidx.slice.builders.SliceAction;
|
||||
import androidx.slice.core.SliceHints.ImageMode;
|
||||
|
||||
public class ImplicitPendingIntentsTest {
|
||||
|
||||
@@ -75,4 +87,71 @@ public class ImplicitPendingIntentsTest {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static class TestSliceProvider extends SliceProvider {
|
||||
|
||||
@Override
|
||||
public Slice onBindSlice(Uri sliceUri) {
|
||||
if (sliceUri.getAuthority().equals("1")) {
|
||||
Intent baseIntent = new Intent();
|
||||
PendingIntent pi = PendingIntent.getActivity(getContext(), 0, baseIntent, 0);
|
||||
SliceAction activityAction = SliceAction.createDeeplink(pi, null, 0, "Test");
|
||||
ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, null);
|
||||
listBuilder.addRow(new ListBuilder.RowBuilder().setTitle("Title")
|
||||
.setPrimaryAction(activityAction));
|
||||
return listBuilder.build(); // $hasTaintFlow
|
||||
|
||||
} else if (sliceUri.getAuthority().equals("2")) {
|
||||
Intent baseIntent = new Intent(getContext(), Activity.class); // Sanitizer
|
||||
PendingIntent pi = PendingIntent.getActivity(getContext(), 0, baseIntent, 0);
|
||||
SliceAction activityAction = SliceAction.createDeeplink(pi, null, 0, "Test");
|
||||
ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, null);
|
||||
listBuilder.addRow(new ListBuilder.RowBuilder().setTitle("Title")
|
||||
.setPrimaryAction(activityAction));
|
||||
return listBuilder.build(); // Safe
|
||||
|
||||
} else {
|
||||
Intent baseIntent = new Intent();
|
||||
PendingIntent pi = PendingIntent.getActivity(getContext(), 0, baseIntent,
|
||||
PendingIntent.FLAG_IMMUTABLE); // Sanitizer
|
||||
SliceAction activityAction = SliceAction.createDeeplink(pi, null, 0, "Test");
|
||||
ListBuilder listBuilder = new ListBuilder(getContext(), sliceUri, null);
|
||||
listBuilder.addRow(new ListBuilder.RowBuilder().setTitle("Title")
|
||||
.setPrimaryAction(activityAction));
|
||||
return listBuilder.build(); // Safe
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PendingIntent onCreatePermissionRequest(Uri sliceUri, String callingPackage) {
|
||||
if (sliceUri.getAuthority().equals("1")) {
|
||||
Intent baseIntent = new Intent();
|
||||
PendingIntent pi = PendingIntent.getActivity(getContext(), 0, baseIntent, 0);
|
||||
return pi; // $hasTaintFlow
|
||||
} else {
|
||||
Intent baseIntent = new Intent();
|
||||
PendingIntent pi = PendingIntent.getActivity(getContext(), 0, baseIntent,
|
||||
PendingIntent.FLAG_IMMUTABLE); // Sanitizer
|
||||
return pi; // Safe
|
||||
}
|
||||
}
|
||||
|
||||
// Implementations needed for compilation
|
||||
@Override
|
||||
public boolean onCreateSliceProvider() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AssetFileDescriptor openTypedAssetFile(Uri uri, String mimeTypeFilter, Bundle opts,
|
||||
CancellationSignal signal) throws RemoteException, FileNotFoundException {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Bundle call(String authority, String method, String arg, Bundle extras)
|
||||
throws RemoteException {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user