From 04989073225435ffdbd04f795dcc99c269fa35d5 Mon Sep 17 00:00:00 2001 From: Arc Wang Date: Mon, 12 Dec 2022 14:44:16 +0800 Subject: [PATCH 1/5] Allow 2-pane deep link to access unexported Activity If an Activity is not exported, the Activity still can be launched by components of the same application, applications with the same user ID, or privileged system components. Bug: 261678674 Bug: 250589026 Test: manual visual Launcher -> context menu -> Wallpaper & style Change-Id: I662df6cb287361b135e2c596abe946ddeb03bda4 Merged-In: I662df6cb287361b135e2c596abe946ddeb03bda4 --- .../homepage/SettingsHomepageActivity.java | 65 +++++++++++++++---- 1 file changed, 53 insertions(+), 12 deletions(-) diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java index 467f0aa10fe..ddc1d775d7c 100644 --- a/src/com/android/settings/homepage/SettingsHomepageActivity.java +++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java @@ -32,6 +32,8 @@ import android.content.pm.PackageManager; import android.content.pm.UserInfo; import android.content.res.Configuration; import android.os.Bundle; +import android.os.Process; +import android.os.RemoteException; import android.os.UserHandle; import android.os.UserManager; import android.text.TextUtils; @@ -436,20 +438,19 @@ public class SettingsHomepageActivity extends FragmentActivity implements return; } - if (!TextUtils.equals(PasswordUtils.getCallingAppPackageName(getActivityToken()), - getPackageName())) { - ActivityInfo targetActivityInfo = null; - try { - targetActivityInfo = getPackageManager().getActivityInfo(targetComponentName, - /* flags= */ 0); - } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, "Failed to get target ActivityInfo: " + e); - finish(); - return; - } + ActivityInfo targetActivityInfo = null; + try { + targetActivityInfo = getPackageManager().getActivityInfo(targetComponentName, + /* flags= */ 0); + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "Failed to get target ActivityInfo: " + e); + finish(); + return; + } + if (!hasPrivilegedAccess(targetActivityInfo)) { if (!targetActivityInfo.exported) { - Log.e(TAG, "Must not launch an unexported Actvity for deep link"); + Log.e(TAG, "Target Activity is not exported"); finish(); return; } @@ -502,6 +503,46 @@ public class SettingsHomepageActivity extends FragmentActivity implements } } + // Check if calling app has privileged access to launch Activity of activityInfo. + private boolean hasPrivilegedAccess(ActivityInfo activityInfo) { + if (TextUtils.equals(PasswordUtils.getCallingAppPackageName(getActivityToken()), + getPackageName())) { + return true; + } + + int callingUid = -1; + try { + callingUid = ActivityManager.getService().getLaunchedFromUid(getActivityToken()); + } catch (RemoteException re) { + Log.e(TAG, "Not able to get callingUid: " + re); + return false; + } + + int targetUid = -1; + try { + targetUid = getPackageManager().getApplicationInfo(activityInfo.packageName, + /* flags= */ 0).uid; + } catch (PackageManager.NameNotFoundException nnfe) { + Log.e(TAG, "Not able to get targetUid: " + nnfe); + return false; + } + + // When activityInfo.exported is false, Activity still can be launched if applications have + // the same user ID. + if (UserHandle.isSameApp(callingUid, targetUid)) { + return true; + } + + // When activityInfo.exported is false, Activity still can be launched if calling app has + // root or system privilege. + int callingAppId = UserHandle.getAppId(callingUid); + if (callingAppId == Process.ROOT_UID || callingAppId == Process.SYSTEM_UID) { + return true; + } + + return false; + } + @VisibleForTesting boolean isCallingAppPermitted(String permission) { return TextUtils.isEmpty(permission) || PasswordUtils.isCallingAppPermitted( From 960c96474dcf17ee7f306e1496f5fab223b2500e Mon Sep 17 00:00:00 2001 From: Arc Wang Date: Mon, 12 Dec 2022 14:44:16 +0800 Subject: [PATCH 2/5] Allow 2-pane deep link to access unexported Activity If an Activity is not exported, the Activity still can be launched by components of the same application, applications with the same user ID, or privileged system components. Bug: 261678674 Bug: 250589026 Test: manual visual Launcher -> context menu -> Wallpaper & style Change-Id: I662df6cb287361b135e2c596abe946ddeb03bda4 Merged-In: I662df6cb287361b135e2c596abe946ddeb03bda4 --- .../homepage/SettingsHomepageActivity.java | 66 +++++++++++++++---- 1 file changed, 54 insertions(+), 12 deletions(-) diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java index 4726059455e..073ce6ae3a0 100644 --- a/src/com/android/settings/homepage/SettingsHomepageActivity.java +++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java @@ -29,6 +29,9 @@ import android.content.pm.ActivityInfo; import android.content.pm.PackageManager; import android.content.res.Configuration; import android.os.Bundle; +import android.os.Process; +import android.os.RemoteException; +import android.os.UserHandle; import android.text.TextUtils; import android.util.ArraySet; import android.util.FeatureFlagUtils; @@ -356,20 +359,19 @@ public class SettingsHomepageActivity extends FragmentActivity implements return; } - if (!TextUtils.equals(PasswordUtils.getCallingAppPackageName(getActivityToken()), - getPackageName())) { - ActivityInfo targetActivityInfo = null; - try { - targetActivityInfo = getPackageManager().getActivityInfo(targetComponentName, - /* flags= */ 0); - } catch (PackageManager.NameNotFoundException e) { - Log.e(TAG, "Failed to get target ActivityInfo: " + e); - finish(); - return; - } + ActivityInfo targetActivityInfo = null; + try { + targetActivityInfo = getPackageManager().getActivityInfo(targetComponentName, + /* flags= */ 0); + } catch (PackageManager.NameNotFoundException e) { + Log.e(TAG, "Failed to get target ActivityInfo: " + e); + finish(); + return; + } + if (!hasPrivilegedAccess(targetActivityInfo)) { if (!targetActivityInfo.exported) { - Log.e(TAG, "Must not launch an unexported Actvity for deep link"); + Log.e(TAG, "Target Activity is not exported"); finish(); return; } @@ -416,6 +418,46 @@ public class SettingsHomepageActivity extends FragmentActivity implements startActivity(targetIntent); } + // Check if calling app has privileged access to launch Activity of activityInfo. + private boolean hasPrivilegedAccess(ActivityInfo activityInfo) { + if (TextUtils.equals(PasswordUtils.getCallingAppPackageName(getActivityToken()), + getPackageName())) { + return true; + } + + int callingUid = -1; + try { + callingUid = ActivityManager.getService().getLaunchedFromUid(getActivityToken()); + } catch (RemoteException re) { + Log.e(TAG, "Not able to get callingUid: " + re); + return false; + } + + int targetUid = -1; + try { + targetUid = getPackageManager().getApplicationInfo(activityInfo.packageName, + /* flags= */ 0).uid; + } catch (PackageManager.NameNotFoundException nnfe) { + Log.e(TAG, "Not able to get targetUid: " + nnfe); + return false; + } + + // When activityInfo.exported is false, Activity still can be launched if applications have + // the same user ID. + if (UserHandle.isSameApp(callingUid, targetUid)) { + return true; + } + + // When activityInfo.exported is false, Activity still can be launched if calling app has + // root or system privilege. + int callingAppId = UserHandle.getAppId(callingUid); + if (callingAppId == Process.ROOT_UID || callingAppId == Process.SYSTEM_UID) { + return true; + } + + return false; + } + @VisibleForTesting boolean isCallingAppPermitted(String permission) { return TextUtils.isEmpty(permission) || PasswordUtils.isCallingAppPermitted( From 17cd85b946a71a3afaa569da326ac029f28c7794 Mon Sep 17 00:00:00 2001 From: Arc Wang Date: Wed, 14 Dec 2022 11:08:53 +0800 Subject: [PATCH 3/5] Check Uri permission for FLAG_GRANT_READ/WRITE_URI_PERMISSION To improve security, calling app must be granted Uri permission if it sets FLAG_GRANT_READ/WRITE_URI_PERMISSION in the Intent of ACTION_SETTINGS_EMBED_DEEP_LINK_ACTIVITY. Bug: 250589026 Test: manual Change-Id: I48f88c662b843212b1066369badff84cf98935a8 Merged-In: I48f88c662b843212b1066369badff84cf98935a8 --- .../homepage/SettingsHomepageActivity.java | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java index 073ce6ae3a0..0311ea3fbe9 100644 --- a/src/com/android/settings/homepage/SettingsHomepageActivity.java +++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java @@ -369,7 +369,16 @@ public class SettingsHomepageActivity extends FragmentActivity implements return; } - if (!hasPrivilegedAccess(targetActivityInfo)) { + int callingUid = -1; + try { + callingUid = ActivityManager.getService().getLaunchedFromUid(getActivityToken()); + } catch (RemoteException re) { + Log.e(TAG, "Not able to get callingUid: " + re); + finish(); + return; + } + + if (!hasPrivilegedAccess(callingUid, targetActivityInfo)) { if (!targetActivityInfo.exported) { Log.e(TAG, "Target Activity is not exported"); finish(); @@ -400,6 +409,19 @@ public class SettingsHomepageActivity extends FragmentActivity implements targetIntent.setData(intent.getParcelableExtra( SettingsHomepageActivity.EXTRA_SETTINGS_LARGE_SCREEN_DEEP_LINK_INTENT_DATA)); + // Only allow FLAG_GRANT_READ/WRITE_URI_PERMISSION if calling app has the permission to + // access specified Uri. + int uriPermissionFlags = targetIntent.getFlags() + & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + if (targetIntent.getData() != null + && uriPermissionFlags != 0 + && checkUriPermission(targetIntent.getData(), /* pid= */ -1, callingUid, + uriPermissionFlags) == PackageManager.PERMISSION_DENIED) { + Log.e(TAG, "Calling app must have the permission to access Uri and grant permission"); + finish(); + return; + } + // Set 2-pane pair rule for the deep link page. ActivityEmbeddingRulesController.registerTwoPanePairRule(this, new ComponentName(getApplicationContext(), getClass()), @@ -419,20 +441,12 @@ public class SettingsHomepageActivity extends FragmentActivity implements } // Check if calling app has privileged access to launch Activity of activityInfo. - private boolean hasPrivilegedAccess(ActivityInfo activityInfo) { + private boolean hasPrivilegedAccess(int callingUid, ActivityInfo activityInfo) { if (TextUtils.equals(PasswordUtils.getCallingAppPackageName(getActivityToken()), getPackageName())) { return true; } - int callingUid = -1; - try { - callingUid = ActivityManager.getService().getLaunchedFromUid(getActivityToken()); - } catch (RemoteException re) { - Log.e(TAG, "Not able to get callingUid: " + re); - return false; - } - int targetUid = -1; try { targetUid = getPackageManager().getApplicationInfo(activityInfo.packageName, From 0f7f913281fff39d533b4ae325ba2fd11f0ae204 Mon Sep 17 00:00:00 2001 From: Arc Wang Date: Wed, 14 Dec 2022 11:08:53 +0800 Subject: [PATCH 4/5] Check Uri permission for FLAG_GRANT_READ/WRITE_URI_PERMISSION To improve security, calling app must be granted Uri permission if it sets FLAG_GRANT_READ/WRITE_URI_PERMISSION in the Intent of ACTION_SETTINGS_EMBED_DEEP_LINK_ACTIVITY. Bug: 250589026 Test: manual Change-Id: I48f88c662b843212b1066369badff84cf98935a8 Merged-In: I48f88c662b843212b1066369badff84cf98935a8 --- .../homepage/SettingsHomepageActivity.java | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/src/com/android/settings/homepage/SettingsHomepageActivity.java b/src/com/android/settings/homepage/SettingsHomepageActivity.java index ddc1d775d7c..a23b743aade 100644 --- a/src/com/android/settings/homepage/SettingsHomepageActivity.java +++ b/src/com/android/settings/homepage/SettingsHomepageActivity.java @@ -448,7 +448,16 @@ public class SettingsHomepageActivity extends FragmentActivity implements return; } - if (!hasPrivilegedAccess(targetActivityInfo)) { + int callingUid = -1; + try { + callingUid = ActivityManager.getService().getLaunchedFromUid(getActivityToken()); + } catch (RemoteException re) { + Log.e(TAG, "Not able to get callingUid: " + re); + finish(); + return; + } + + if (!hasPrivilegedAccess(callingUid, targetActivityInfo)) { if (!targetActivityInfo.exported) { Log.e(TAG, "Target Activity is not exported"); finish(); @@ -479,6 +488,19 @@ public class SettingsHomepageActivity extends FragmentActivity implements targetIntent.setData(intent.getParcelableExtra( SettingsHomepageActivity.EXTRA_SETTINGS_LARGE_SCREEN_DEEP_LINK_INTENT_DATA)); + // Only allow FLAG_GRANT_READ/WRITE_URI_PERMISSION if calling app has the permission to + // access specified Uri. + int uriPermissionFlags = targetIntent.getFlags() + & (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION); + if (targetIntent.getData() != null + && uriPermissionFlags != 0 + && checkUriPermission(targetIntent.getData(), /* pid= */ -1, callingUid, + uriPermissionFlags) == PackageManager.PERMISSION_DENIED) { + Log.e(TAG, "Calling app must have the permission to access Uri and grant permission"); + finish(); + return; + } + // Set 2-pane pair rule for the deep link page. ActivityEmbeddingRulesController.registerTwoPanePairRule(this, new ComponentName(getApplicationContext(), getClass()), @@ -504,20 +526,12 @@ public class SettingsHomepageActivity extends FragmentActivity implements } // Check if calling app has privileged access to launch Activity of activityInfo. - private boolean hasPrivilegedAccess(ActivityInfo activityInfo) { + private boolean hasPrivilegedAccess(int callingUid, ActivityInfo activityInfo) { if (TextUtils.equals(PasswordUtils.getCallingAppPackageName(getActivityToken()), getPackageName())) { return true; } - int callingUid = -1; - try { - callingUid = ActivityManager.getService().getLaunchedFromUid(getActivityToken()); - } catch (RemoteException re) { - Log.e(TAG, "Not able to get callingUid: " + re); - return false; - } - int targetUid = -1; try { targetUid = getPackageManager().getApplicationInfo(activityInfo.packageName, From e45ab97777dee3086e3189a7fa9b0a55db7ef271 Mon Sep 17 00:00:00 2001 From: Zoey Chen Date: Fri, 16 Dec 2022 10:13:19 +0000 Subject: [PATCH 5/5] [Settings] Add search keywords for APN controller Screenshot: https://hsv.googleplex.com/4816766300585984 Bug: 254024521 Test: atest ApnPreferenceController Change-Id: I219256efff8d5859d029b190bf2cc73b8e83a746 --- res/values/strings.xml | 2 ++ res/xml/mobile_network_settings.xml | 1 + 2 files changed, 3 insertions(+) diff --git a/res/values/strings.xml b/res/values/strings.xml index 63b634beab8..88a6ec8bd24 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -13102,6 +13102,8 @@ Invalid Network Mode %1$d. Ignore. Access Point Names + + apn Unavailable when connected to %1$s diff --git a/res/xml/mobile_network_settings.xml b/res/xml/mobile_network_settings.xml index 8206223689c..8fd6dc85d50 100644 --- a/res/xml/mobile_network_settings.xml +++ b/res/xml/mobile_network_settings.xml @@ -233,6 +233,7 @@ android:persistent="false" android:title="@string/mobile_network_apn_title" settings:allowDividerAbove="true" + settings:keywords="@string/keywords_access_point_names" settings:controller="com.android.settings.network.telephony.ApnPreferenceController"/>