Skip to content

Commit

Permalink
Protected apps
Browse files Browse the repository at this point in the history
Fix up protected apps filter.

Move filtering to correct place (when querying providers,
ResolveInfo.activityInfo is null), and port over commit
4dad4a4 from cm-11.0.

Protected Apps: do not filter components from the same UID

pm: Use ArraySet instead of HashSet

packagemanager: Use ArrayMap/ArraySet as per AOSP

 * To reduce memory consumption

Change-Id: Ic690387cd21fdfa09ef5fb19bd3de9305050cf6e

fw: Fix protected apps implementation.

 Currently a protected component could be accessed
 from any other means other than the launcher, entirely
 defeating its purpose. Instead, hook into the activity
 stack supervisor and quelch attempts at invocation
 of protected components.

 This implementation also provides feedback to the user
 on any attempt to start the component when its in a
 protected state.

TICKET: CYNGNOS-84
Change-Id: Ib0165e7504adb08e21e9566c7394b37dffd280d4

pm: Avoid filtering out protected components in implicit queries.

  Implicity queries resolve the target component for an intent, the
  intent (if fired) will be gated by the protected apps feature
  implementation within the activity stack supervisor.

Change-Id: Ib079cfa6093f472d4b85f6b4a986440a764affa3
TICKET: FEIJ-1449

am: Don't protect apps that atttempt to grant uri perms.

  If an application is delegating uri permissions through
  the disambiguation dialog, we need to ignore the global
  protected apps concept to make sure the functionality still
  works.

  TODO: Refactor the protected apps implementation to function
  with startActivityAsCaller within the system process and the
  android package.

  TICKET: FEIJ-420

Change-Id: I8ba974a7b25dffe654d32e859064ae86cd9dc7f8

am: Handle unchecked activity starts for protected components.

  Previously if you received a notification from a protected app,
  since AM would state that the calling package was also the target
  package, the protected apps implementation would allow you to
  launch into the application. Mitigate this by hooking into
  the unchecked activity start stack (pending intent launches)
  globally.

Change-Id: I0371593ade9e4af2554962873d89a0f82a639b57
TICKET: PAELLA-216 FEIJ-160 FEIJ-177

pm: Allow fall through for protected apps validator activity.

  Otherwise protecting the settings application leads to some weird
  behavior.

TICKET: CYNGNOS-1915
Change-Id: I4821a07aadf73e7664c44275d8ed80709c7fde8c

am: Cancel protected app notification on validation launch.

Change-Id: I89d7366e97db04874baa5b19c2dfee7f0100c848
TICKET: CYNGNOS-2130

am: clear protected apps from recents

Remove newly protected apps from recent tasks if any activity
in the stack is a restricted component.

FEIJ-1361
Change-Id: Ifd337bfe8356613d098ff00c575db117d35f2017

am: clear state for every protected app invocation.

Change-Id: I7766e050b8bedb46ff9293a5d61451e6c998fb0b
TICKET: CYNGNOS-2962

pm: Use sourcerecord if available for protected app validation.

  A source record serves as a beneficial historical record to
  see if an activity start has been redirected numerous times.

  This fixes issues where applications that redirect implicitly
  and are protected would constantly spam to be authed.

Change-Id: Ibeb9eae4279a0cdd65635392316eabb485adfa27
TICKET: PAELLA-216 FEIJ-160 FEIJ-177

core: Improve protected apps notification message

Change-Id: Ib8bce9494bae2203260bdc844fe1f367d599b719
  • Loading branch information
Raj Yengisetty authored and ryzenforce990 committed Sep 13, 2016
1 parent 8617c54 commit ad00cb0
Show file tree
Hide file tree
Showing 19 changed files with 577 additions and 7 deletions.
22 changes: 22 additions & 0 deletions core/java/android/app/ApplicationPackageManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -2216,6 +2216,28 @@ public boolean isUpgrade() {
}
}

@Override
public void setComponentProtectedSetting(ComponentName componentName, boolean newState) {
try {
mPM.setComponentProtectedSetting(componentName, newState, mContext.getUserId());
} catch (RemoteException re) {
Log.e(TAG, "Failed to set component protected setting", re);
}
}

/** @hide */
@Override
public boolean isComponentProtected(String callingPackage, int callingUid,
ComponentName componentName) {
try {
return mPM.isComponentProtected(callingPackage, callingUid, componentName,
mContext.getUserId());
} catch (RemoteException re) {
Log.e(TAG, "Failed to get component protected setting", re);
return false;
}
}

@Override
public PackageInstaller getPackageInstaller() {
synchronized (mLock) {
Expand Down
10 changes: 10 additions & 0 deletions core/java/android/content/pm/ApplicationInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -777,6 +777,13 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
*/
public int networkSecurityConfigRes;

/**
* When true, indicates that any one component within this application is
* protected.
* @hide
*/
public boolean protect = false;

public void dump(Printer pw, String prefix) {
dump(pw, prefix, DUMP_FLAG_ALL);
}
Expand Down Expand Up @@ -940,6 +947,7 @@ public ApplicationInfo(ApplicationInfo orig) {
backupAgentName = orig.backupAgentName;
fullBackupContent = orig.fullBackupContent;
networkSecurityConfigRes = orig.networkSecurityConfigRes;
protect = orig.protect;
}

public String toString() {
Expand Down Expand Up @@ -997,6 +1005,7 @@ public void writeToParcel(Parcel dest, int parcelableFlags) {
dest.writeInt(uiOptions);
dest.writeInt(fullBackupContent);
dest.writeInt(networkSecurityConfigRes);
dest.writeInt(protect ? 1 : 0);
}

public static final Parcelable.Creator<ApplicationInfo> CREATOR
Expand Down Expand Up @@ -1054,6 +1063,7 @@ private ApplicationInfo(Parcel source) {
uiOptions = source.readInt();
fullBackupContent = source.readInt();
networkSecurityConfigRes = source.readInt();
protect = source.readInt() != 0;
}

/**
Expand Down
8 changes: 8 additions & 0 deletions core/java/android/content/pm/IPackageManager.aidl
Original file line number Diff line number Diff line change
Expand Up @@ -573,4 +573,12 @@ interface IPackageManager {
boolean isPackageDeviceAdminOnAnyUser(String packageName);

List<String> getPreviousCodePaths(in String packageName);

/** Protected Apps */
void setComponentProtectedSetting(in ComponentName componentName,
in boolean newState, int userId);

/** Protected Apps */
boolean isComponentProtected(in String callingPackage, in int callingUid,
in ComponentName componentName, int userId);
}
27 changes: 27 additions & 0 deletions core/java/android/content/pm/PackageManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -2366,6 +2366,20 @@ public interface OnPermissionsChangedListener {
public static final String EXTRA_REQUEST_PERMISSIONS_RESULTS
= "android.content.pm.extra.REQUEST_PERMISSIONS_RESULTS";

/**
* Flag for {@link #setComponentProtectedSetting(android.content.ComponentName, boolean)}:
* This component or application has set to protected status
* @hide
*/
public static final boolean COMPONENT_PROTECTED_STATUS = false;

/**
* Flag for {@link #setComponentProtectedSetting(android.content.ComponentName, boolean)}:
* This component or application has been explicitly set to visible status
* @hide
*/
public static final boolean COMPONENT_VISIBLE_STATUS = true;

/**
* String extra for {@link PackageInstallObserver} in the 'extras' Bundle in case of
* {@link #INSTALL_FAILED_DUPLICATE_PERMISSION}. This extra names the package which provides
Expand Down Expand Up @@ -5596,6 +5610,19 @@ public void onCreated(int moveId, Bundle extras) {}
*/
public abstract @NonNull PackageInstaller getPackageInstaller();

/**
* Update Component protection state
* @hide
*/
public abstract void setComponentProtectedSetting(ComponentName componentName, boolean newState);

/**
* Return whether or not a specific component is protected
* @hide
*/
public abstract boolean isComponentProtected(String callingPackage, int callingUid,
ComponentName componentName);

/**
* Adds a {@code CrossProfileIntentFilter}. After calling this method all
* intents sent from the user with id sourceUserId can also be be resolved
Expand Down
9 changes: 9 additions & 0 deletions core/java/android/content/pm/PackageParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -5416,6 +5416,12 @@ private static boolean copyNeeded(int flags, Package p,
&& p.usesLibraryFiles != null) {
return true;
}
if (state.protectedComponents != null) {
boolean protect = state.protectedComponents.size() > 0;
if (p.applicationInfo.protect != protect) {
return true;
}
}
return false;
}

Expand Down Expand Up @@ -5454,6 +5460,9 @@ private static void updateApplicationInfo(ApplicationInfo ai, int flags,
ai.enabled = false;
}
ai.enabledSetting = state.enabled;
if (state.protectedComponents != null) {
ai.protect = state.protectedComponents.size() > 0;
}
}

public static ApplicationInfo generateApplicationInfo(Package p, int flags,
Expand Down
7 changes: 7 additions & 0 deletions core/java/android/content/pm/PackageUserState.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ public class PackageUserState {

public ArraySet<String> disabledComponents;
public ArraySet<String> enabledComponents;
public ArraySet<String> protectedComponents;
public ArraySet<String> visibleComponents;

public PackageUserState() {
installed = true;
Expand All @@ -74,6 +76,11 @@ public PackageUserState(PackageUserState o) {
appLinkGeneration = o.appLinkGeneration;
disabledComponents = ArrayUtils.cloneOrNull(o.disabledComponents);
enabledComponents = ArrayUtils.cloneOrNull(o.enabledComponents);
protectedComponents = o.protectedComponents != null
? new ArraySet<String>(o.protectedComponents) : null;
visibleComponents = o.visibleComponents != null
? new ArraySet<String>(o.visibleComponents) : null;

}

/**
Expand Down
5 changes: 5 additions & 0 deletions core/java/android/provider/Settings.java
Original file line number Diff line number Diff line change
Expand Up @@ -6332,6 +6332,11 @@ public static boolean putFloatForUser(ContentResolver cr, String name, float val
*/
public static final String SLEEP_TIMEOUT = "sleep_timeout";

/** Protected Components
* @hide
*/
public static final String PROTECTED_COMPONENTS = "protected_components";

/**
* Controls whether double tap to wake is enabled.
* @hide
Expand Down
28 changes: 28 additions & 0 deletions core/res/res/drawable/stat_notify_protected.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2016 The CyanogenMod 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.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="26dp"
android:height="24dp"
android:viewportWidth="26"
android:viewportHeight="24">

<path
android:pathData="M0 0h24v24H0z" />
<path
android:fillColor="#000000"
android:pathData="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z" />
</vector>
4 changes: 4 additions & 0 deletions core/res/res/values/cm_strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -154,4 +154,8 @@
<string name="app_ops_run_in_background">run in background</string>
<string name="app_ops_wifi_change">change WiFI state</string>
<string name="app_ops_su">get Superuser access</string>

<!-- Protected Apps Notification -->
<string name="notify_package_component_protected_title">Activity launch blocked</string>
<string name="notify_package_component_protected_text"><xliff:g id="app_name">%1$s</xliff:g> is protected from being launched. Tap to authenticate and launch the application.</string>
</resources>
5 changes: 5 additions & 0 deletions core/res/res/values/cm_symbols.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,9 @@

<!-- Carrier Apps -->
<java-symbol type="array" name="config_enabledPreinstalledCarrierApps" />

<!-- Protected Apps -->
<java-symbol type="drawable" name="stat_notify_protected" />
<java-symbol type="string" name="notify_package_component_protected_title" />
<java-symbol type="string" name="notify_package_component_protected_text" />
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

import android.app.PackageInstallObserver;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
Expand Down Expand Up @@ -3869,4 +3870,21 @@ public void testInstall_BadDex_CleanUp() throws Exception {
* how to do tests on updated system apps?
* verify updates to system apps cannot be installed on the sdcard.
*/

//CM Tests
public void testIsComponentProtectedFromSamePackage() {
ComponentName testComponentName = new ComponentName("com.android.test",
"com.android.test.component.protected");
getPm().setComponentProtectedSetting(testComponentName, true);
assertFalse(getPm().isComponentProtected(testComponentName.getPackageName(),
testComponentName));
}

public void testIsComponentProtectedFromManagers() {
ComponentName testComponentName = new ComponentName("com.android.test",
"com.android.test.component.protected");
getPm().setComponentProtectedSetting(testComponentName, true);
assertFalse(getPm().isComponentProtected(testComponentName.getPackageName(),
testComponentName));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1551,6 +1551,8 @@ public void binderDied() {

static final int POST_PRIVACY_NOTIFICATION_MSG = 90;
static final int CANCEL_PRIVACY_NOTIFICATION_MSG = 91;
static final int POST_COMPONENT_PROTECTED_MSG = 92;
static final int CANCEL_PROTECTED_APP_NOTIFICATION = 93;

static final int FIRST_ACTIVITY_STACK_MSG = 100;
static final int FIRST_BROADCAST_QUEUE_MSG = 200;
Expand Down Expand Up @@ -2428,6 +2430,87 @@ public void handleMessage(Message msg) {
r.info.getComponentName(), false);
}
} break;
case POST_COMPONENT_PROTECTED_MSG: {
INotificationManager inm = NotificationManager.getService();
if (inm == null) {
return;
}

Intent targetIntent = (Intent) msg.obj;
if (targetIntent == null) {
return;
}

int currentUserId = mUserController.getCurrentUserIdLocked();
int targetUserId = targetIntent.getIntExtra(
"com.android.settings.PROTECTED_APPS_USER_ID", currentUserId);
// Resolve for labels and whatnot
ActivityInfo root = resolveActivityInfo(targetIntent, targetIntent.getFlags(),
targetUserId);

try {
Intent protectedAppIntent = new Intent();
protectedAppIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
protectedAppIntent.setComponent(
new ComponentName("com.android.settings",
"com.android.settings.applications.ProtectedAppsActivity"));
protectedAppIntent.putExtra(
"com.android.settings.PROTECTED_APP_TARGET_INTENT",
targetIntent);
Context context = mContext.createPackageContext("com.android.settings", 0);
String title = mContext.getString(
com.android.internal.R.string
.notify_package_component_protected_title);
String text = mContext.getString(
com.android.internal.R.string
.notify_package_component_protected_text,
root.applicationInfo.loadLabel(mContext.getPackageManager()));
Notification notification = new Notification.Builder(context)
.setSmallIcon(com.android.internal.R.drawable.stat_notify_protected)
.setWhen(0)
.setTicker(title)
.setColor(mContext.getColor(
com.android.internal.R.color
.system_notification_accent_color))
.setContentTitle(title)
.setContentText(text)
.setDefaults(Notification.DEFAULT_VIBRATE)
.setPriority(Notification.PRIORITY_MAX)
.setStyle(new Notification.BigTextStyle().bigText(text))
.setContentIntent(PendingIntent.getActivityAsUser(mContext, 0,
protectedAppIntent, PendingIntent.FLAG_CANCEL_CURRENT, null,
new UserHandle(currentUserId)))
.build();
try {
int[] outId = new int[1];
inm.cancelNotificationWithTag("android", null,
R.string.notify_package_component_protected_title, msg.arg1);
inm.enqueueNotificationWithTag("android", "android", null,
R.string.notify_package_component_protected_title,
notification, outId, currentUserId);
} catch (RuntimeException e) {
Slog.w(ActivityManagerService.TAG,
"Error showing notification for protected app component", e);
} catch (RemoteException e) {
}
} catch (NameNotFoundException e) {
Slog.w(TAG, "Unable to create context for protected app notification", e);
}
} break;
case CANCEL_PROTECTED_APP_NOTIFICATION: {
INotificationManager inm = NotificationManager.getService();
if (inm == null) {
return;
}
try {
inm.cancelNotificationWithTag("android", null,
R.string.notify_package_component_protected_title, msg.arg1);
} catch (RuntimeException e) {
Slog.w(ActivityManagerService.TAG,
"Error canceling notification for service", e);
} catch (RemoteException e) {
}
} break;
}
}
};
Expand Down Expand Up @@ -17949,7 +18032,6 @@ final int broadcastIntentLocked(ProcessRecord callerApp,
+ callingPid + ", uid=" + callingUid;
Slog.w(TAG, msg);
throw new SecurityException(msg);

} else if (AppWidgetManager.ACTION_APPWIDGET_CONFIGURE.equals(action)
|| AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
// Special case for compatibility: we don't want apps to send this,
Expand Down Expand Up @@ -18204,6 +18286,15 @@ final int broadcastIntentLocked(ProcessRecord callerApp,
}
// Lie; we don't want to crash the app.
return ActivityManager.BROADCAST_SUCCESS;
case cyanogenmod.content.Intent.ACTION_PROTECTED_CHANGED:
final boolean state =
intent.getBooleanExtra(
cyanogenmod.content.Intent.EXTRA_PROTECTED_STATE, false);
if (state == PackageManager.COMPONENT_PROTECTED_STATUS) {
mRecentTasks.cleanupProtectedComponentTasksLocked(
mUserController.getCurrentUserIdLocked());
}
break;
}
}

Expand Down
Loading

0 comments on commit ad00cb0

Please sign in to comment.