Some system apps are more system than others
"signatureOrSystem" permissions are no longer available to all apps
residing en the /system partition. Instead, there is a new /system/priv-app
directory, and only apps whose APKs are in that directory are allowed
to use signatureOrSystem permissions without sharing the platform cert.
This will reduce the surface area for possible exploits of system-
bundled applications to try to gain access to permission-guarded
operations.
The ApplicationInfo.FLAG_SYSTEM flag continues to mean what it is
says in the documentation: it indicates that the application apk was
bundled on the /system partition. A new hidden flag FLAG_PRIVILEGED
has been introduced that reflects the actual right to access these
permissions.
At some point the "system" permission category will be
renamed to "privileged".
Bug 8765951
Change-Id: I6f0fd9cdb9170e076dfc66d83ecea76f8dd7335d
diff --git a/services/java/com/android/server/accounts/AccountManagerService.java b/services/java/com/android/server/accounts/AccountManagerService.java
index c5242f0..2145b76 100644
--- a/services/java/com/android/server/accounts/AccountManagerService.java
+++ b/services/java/com/android/server/accounts/AccountManagerService.java
@@ -2540,7 +2540,7 @@
return userId;
}
- private boolean inSystemImage(int callingUid) {
+ private boolean isPrivileged(int callingUid) {
final int callingUserId = UserHandle.getUserId(callingUid);
final PackageManager userPackageManager;
@@ -2556,7 +2556,7 @@
try {
PackageInfo packageInfo = userPackageManager.getPackageInfo(name, 0 /* flags */);
if (packageInfo != null
- && (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
+ && (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_PRIVILEGED) != 0) {
return true;
}
} catch (PackageManager.NameNotFoundException e) {
@@ -2567,7 +2567,7 @@
}
private boolean permissionIsGranted(Account account, String authTokenType, int callerUid) {
- final boolean inSystemImage = inSystemImage(callerUid);
+ final boolean isPrivileged = isPrivileged(callerUid);
final boolean fromAuthenticator = account != null
&& hasAuthenticatorUid(account.type, callerUid);
final boolean hasExplicitGrants = account != null
@@ -2578,7 +2578,7 @@
+ ": is authenticator? " + fromAuthenticator
+ ", has explicit permission? " + hasExplicitGrants);
}
- return fromAuthenticator || hasExplicitGrants || inSystemImage;
+ return fromAuthenticator || hasExplicitGrants || isPrivileged;
}
private boolean hasAuthenticatorUid(String accountType, int callingUid) {
diff --git a/services/java/com/android/server/pm/PackageManagerService.java b/services/java/com/android/server/pm/PackageManagerService.java
index 5e6e055..9ea4262 100644
--- a/services/java/com/android/server/pm/PackageManagerService.java
+++ b/services/java/com/android/server/pm/PackageManagerService.java
@@ -71,7 +71,6 @@
import android.content.pm.IPackageMoveObserver;
import android.content.pm.IPackageStatsObserver;
import android.content.pm.InstrumentationInfo;
-import android.content.pm.KeySet;
import android.content.pm.PackageCleanItem;
import android.content.pm.PackageInfo;
import android.content.pm.PackageInfoLite;
@@ -114,15 +113,12 @@
import android.os.UserHandle;
import android.os.Environment.UserEnvironment;
import android.os.UserManager;
-import android.provider.Settings.Secure;
import android.security.KeyStore;
import android.security.SystemKeyStore;
-import android.util.Base64;
import android.util.DisplayMetrics;
import android.util.EventLog;
import android.util.Log;
import android.util.LogPrinter;
-import android.util.LongSparseArray;
import android.util.Slog;
import android.util.SparseArray;
import android.util.Xml;
@@ -280,6 +276,9 @@
// This is the object monitoring the system app dir.
final FileObserver mSystemInstallObserver;
+ // This is the object monitoring the privileged system app dir.
+ final FileObserver mPrivilegedInstallObserver;
+
// This is the object monitoring the system app dir.
final FileObserver mVendorInstallObserver;
@@ -295,6 +294,7 @@
final File mFrameworkDir;
final File mSystemAppDir;
+ final File mPrivilegedAppDir;
final File mVendorAppDir;
final File mAppInstallDir;
final File mDalvikCacheDir;
@@ -1058,13 +1058,18 @@
mNoDexOpt = "eng".equals(SystemProperties.get("ro.build.type"));
mMetrics = new DisplayMetrics();
mSettings = new Settings(context);
- mSettings.addSharedUserLPw("android.uid.system",
- Process.SYSTEM_UID, ApplicationInfo.FLAG_SYSTEM);
- mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID, ApplicationInfo.FLAG_SYSTEM);
- mSettings.addSharedUserLPw("android.uid.log", LOG_UID, ApplicationInfo.FLAG_SYSTEM);
- mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID, ApplicationInfo.FLAG_SYSTEM);
- mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID, ApplicationInfo.FLAG_SYSTEM);
- mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID, ApplicationInfo.FLAG_SYSTEM);
+ mSettings.addSharedUserLPw("android.uid.system", Process.SYSTEM_UID,
+ ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
+ mSettings.addSharedUserLPw("android.uid.phone", RADIO_UID,
+ ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
+ mSettings.addSharedUserLPw("android.uid.log", LOG_UID,
+ ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
+ mSettings.addSharedUserLPw("android.uid.nfc", NFC_UID,
+ ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
+ mSettings.addSharedUserLPw("android.uid.bluetooth", BLUETOOTH_UID,
+ ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
+ mSettings.addSharedUserLPw("android.uid.shell", SHELL_UID,
+ ApplicationInfo.FLAG_SYSTEM|ApplicationInfo.FLAG_PRIVILEGED);
String separateProcesses = SystemProperties.get("debug.separate_processes");
if (separateProcesses != null && separateProcesses.length() > 0) {
@@ -1246,7 +1251,16 @@
| PackageParser.PARSE_IS_SYSTEM_DIR,
scanMode | SCAN_NO_DEX, 0);
- // Collect all system packages.
+ // Collected privileged system packages.
+ mPrivilegedAppDir = new File(Environment.getRootDirectory(), "priv-app");
+ mPrivilegedInstallObserver = new AppDirObserver(
+ mPrivilegedAppDir.getPath(), OBSERVER_EVENTS, true);
+ mPrivilegedInstallObserver.startWatching();
+ scanDirLI(mPrivilegedAppDir, PackageParser.PARSE_IS_SYSTEM
+ | PackageParser.PARSE_IS_SYSTEM_DIR
+ | PackageParser.PARSE_IS_PRIVILEGED, scanMode, 0);
+
+ // Collect ordinary system packages.
mSystemAppDir = new File(Environment.getRootDirectory(), "app");
mSystemInstallObserver = new AppDirObserver(
mSystemAppDir.getPath(), OBSERVER_EVENTS, true);
@@ -3240,7 +3254,6 @@
public List<ProviderInfo> queryContentProviders(String processName,
int uid, int flags) {
ArrayList<ProviderInfo> finalList = null;
-
// reader
synchronized (mPackages) {
final Iterator<PackageParser.Provider> i = mProvidersByComponent.values().iterator();
@@ -3316,7 +3329,8 @@
}
if (DEBUG_PACKAGE_SCANNING) {
- Log.d(TAG, "Scanning app dir " + dir);
+ Log.d(TAG, "Scanning app dir " + dir + " scanMode=" + scanMode
+ + " flags=0x" + Integer.toHexString(flags));
}
int i;
@@ -3972,6 +3986,10 @@
pkg.applicationInfo.flags |= ApplicationInfo.FLAG_SYSTEM;
}
+ if ((parseFlags&PackageParser.PARSE_IS_PRIVILEGED) != 0) {
+ pkg.applicationInfo.flags |= ApplicationInfo.FLAG_PRIVILEGED;
+ }
+
if (pkg.packageName.equals("android")) {
synchronized (mPackages) {
if (mAndroidApplication != null) {
@@ -5363,7 +5381,7 @@
== PackageManager.SIGNATURE_MATCH);
if (!allowed && (bp.protectionLevel
& PermissionInfo.PROTECTION_FLAG_SYSTEM) != 0) {
- if (isSystemApp(pkg)) {
+ if (isPrivilegedApp(pkg)) {
// For updated system applications, a system permission
// is granted only if it had been defined by the original application.
if (isUpdatedSystemApp(pkg)) {
@@ -8566,6 +8584,10 @@
return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
}
+ private static boolean isPrivilegedApp(PackageParser.Package pkg) {
+ return (pkg.applicationInfo.flags & ApplicationInfo.FLAG_PRIVILEGED) != 0;
+ }
+
private static boolean isSystemApp(ApplicationInfo info) {
return (info.flags & ApplicationInfo.FLAG_SYSTEM) != 0;
}