diff options
19 files changed, 292 insertions, 142 deletions
| diff --git a/core/java/android/app/LoadedApk.java b/core/java/android/app/LoadedApk.java index f6d9710dae69..de6230cf825a 100644 --- a/core/java/android/app/LoadedApk.java +++ b/core/java/android/app/LoadedApk.java @@ -638,8 +638,7 @@ public final class LoadedApk {          final String defaultSearchPaths = System.getProperty("java.library.path");          final boolean treatVendorApkAsUnbundled = !defaultSearchPaths.contains("/vendor/lib");          if (mApplicationInfo.getCodePath() != null -                && mApplicationInfo.getCodePath().startsWith("/vendor/") -                && treatVendorApkAsUnbundled) { +                && mApplicationInfo.isVendor() && treatVendorApkAsUnbundled) {              isBundledApp = false;          } diff --git a/core/java/android/content/pm/ApplicationInfo.java b/core/java/android/content/pm/ApplicationInfo.java index edb27cd4ecf1..5298f57b4ef2 100644 --- a/core/java/android/content/pm/ApplicationInfo.java +++ b/core/java/android/content/pm/ApplicationInfo.java @@ -594,6 +594,13 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {       */      public static final int PRIVATE_FLAG_OEM = 1 << 17; +    /** +     * Value for {@linl #privateFlags}: whether this app is pre-installed on the +     * vendor partition of the system image. +     * @hide +     */ +    public static final int PRIVATE_FLAG_VENDOR = 1 << 18; +      /** @hide */      @IntDef(flag = true, prefix = { "PRIVATE_FLAG_" }, value = {              PRIVATE_FLAG_ACTIVITIES_RESIZE_MODE_RESIZEABLE, @@ -613,6 +620,7 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {              PRIVATE_FLAG_PRIVILEGED,              PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER,              PRIVATE_FLAG_STATIC_SHARED_LIBRARY, +            PRIVATE_FLAG_VENDOR,              PRIVATE_FLAG_VIRTUAL_PRELOAD,      })      @Retention(RetentionPolicy.SOURCE) @@ -1569,6 +1577,11 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {          return (flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0;      } +    /** @hide */ +    public boolean isVendor() { +        return (privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0; +    } +      /**       * Returns whether or not this application was installed as a virtual preload.       */ diff --git a/core/java/android/content/pm/PackageParser.java b/core/java/android/content/pm/PackageParser.java index ebeaad78ea6a..98c824dbf8f6 100644 --- a/core/java/android/content/pm/PackageParser.java +++ b/core/java/android/content/pm/PackageParser.java @@ -6267,6 +6267,11 @@ public class PackageParser {          }          /** @hide */ +        public boolean isVendor() { +            return applicationInfo.isVendor(); +        } + +        /** @hide */          public boolean isPrivileged() {              return applicationInfo.isPrivilegedApp();          } diff --git a/core/java/android/content/pm/PermissionInfo.java b/core/java/android/content/pm/PermissionInfo.java index 75887624eef3..551d53b631cd 100644 --- a/core/java/android/content/pm/PermissionInfo.java +++ b/core/java/android/content/pm/PermissionInfo.java @@ -144,6 +144,15 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {      public static final int PROTECTION_FLAG_OEM = 0x4000;      /** +     * Additional flag for {${link #protectionLevel}, corresponding +     * to the <code>vendorPrivileged</code> value of +     * {@link android.R.attr#protectionLevel}. +     * +     * @hide +     */ +    public static final int PROTECTION_FLAG_VENDOR_PRIVILEGED = 0x8000; + +    /**       * Mask for {@link #protectionLevel}: the basic protection type.       */      public static final int PROTECTION_MASK_BASE = 0xf; @@ -231,6 +240,12 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {          if (level == PROTECTION_SIGNATURE_OR_SYSTEM) {              level = PROTECTION_SIGNATURE | PROTECTION_FLAG_PRIVILEGED;          } +        if ((level & PROTECTION_FLAG_VENDOR_PRIVILEGED) != 0 +                && (level & PROTECTION_FLAG_PRIVILEGED) == 0) { +            // 'vendorPrivileged' must be 'privileged'. If not, +            // drop the vendorPrivileged. +            level = level & ~PROTECTION_FLAG_VENDOR_PRIVILEGED; +        }          return level;      } @@ -284,6 +299,9 @@ public class PermissionInfo extends PackageItemInfo implements Parcelable {          if ((level & PermissionInfo.PROTECTION_FLAG_OEM) != 0) {              protLevel += "|oem";          } +        if ((level & PermissionInfo.PROTECTION_FLAG_VENDOR_PRIVILEGED) != 0) { +            protLevel += "|vendorPrivileged"; +        }          return protLevel;      } diff --git a/core/java/com/android/server/SystemConfig.java b/core/java/com/android/server/SystemConfig.java index b5031f23918f..b7a67192f01f 100644 --- a/core/java/com/android/server/SystemConfig.java +++ b/core/java/com/android/server/SystemConfig.java @@ -146,6 +146,9 @@ public class SystemConfig {      final ArrayMap<String, ArraySet<String>> mPrivAppPermissions = new ArrayMap<>();      final ArrayMap<String, ArraySet<String>> mPrivAppDenyPermissions = new ArrayMap<>(); +    final ArrayMap<String, ArraySet<String>> mVendorPrivAppPermissions = new ArrayMap<>(); +    final ArrayMap<String, ArraySet<String>> mVendorPrivAppDenyPermissions = new ArrayMap<>(); +      final ArrayMap<String, ArrayMap<String, Boolean>> mOemPermissions = new ArrayMap<>();      public static SystemConfig getInstance() { @@ -229,6 +232,14 @@ public class SystemConfig {          return mPrivAppDenyPermissions.get(packageName);      } +    public ArraySet<String> getVendorPrivAppPermissions(String packageName) { +        return mVendorPrivAppPermissions.get(packageName); +    } + +    public ArraySet<String> getVendorPrivAppDenyPermissions(String packageName) { +        return mVendorPrivAppDenyPermissions.get(packageName); +    } +      public Map<String, Boolean> getOemPermissions(String packageName) {          final Map<String, Boolean> oemPermissions = mOemPermissions.get(packageName);          if (oemPermissions != null) { @@ -248,7 +259,7 @@ public class SystemConfig {          // Allow Vendor to customize system configs around libs, features, permissions and apps          int vendorPermissionFlag = ALLOW_LIBS | ALLOW_FEATURES | ALLOW_PERMISSIONS | -                ALLOW_APP_CONFIGS; +                ALLOW_APP_CONFIGS | ALLOW_PRIVAPP_PERMISSIONS;          readPermissions(Environment.buildPath(                  Environment.getVendorDirectory(), "etc", "sysconfig"), vendorPermissionFlag);          readPermissions(Environment.buildPath( @@ -587,7 +598,19 @@ public class SystemConfig {                      }                      XmlUtils.skipCurrentTag(parser);                  } else if ("privapp-permissions".equals(name) && allowPrivappPermissions) { -                    readPrivAppPermissions(parser); +                    // privapp permissions from system and vendor partitions are stored +                    // separately. This is to prevent xml files in the vendor partition from +                    // granting permissions to priv apps in the system partition and vice +                    // versa. +                    boolean vendor = permFile.toPath().startsWith( +                            Environment.getVendorDirectory().toPath()); +                    if (vendor) { +                        readPrivAppPermissions(parser, mVendorPrivAppPermissions, +                                mVendorPrivAppDenyPermissions); +                    } else { +                        readPrivAppPermissions(parser, mPrivAppPermissions, +                                mPrivAppDenyPermissions); +                    }                  } else if ("oem-permissions".equals(name) && allowOemPermissions) {                      readOemPermissions(parser);                  } else { @@ -674,7 +697,10 @@ public class SystemConfig {          }      } -    void readPrivAppPermissions(XmlPullParser parser) throws IOException, XmlPullParserException { +    private void readPrivAppPermissions(XmlPullParser parser, +            ArrayMap<String, ArraySet<String>> grantMap, +            ArrayMap<String, ArraySet<String>> denyMap) +            throws IOException, XmlPullParserException {          String packageName = parser.getAttributeValue(null, "package");          if (TextUtils.isEmpty(packageName)) {              Slog.w(TAG, "package is required for <privapp-permissions> in " @@ -682,11 +708,11 @@ public class SystemConfig {              return;          } -        ArraySet<String> permissions = mPrivAppPermissions.get(packageName); +        ArraySet<String> permissions = grantMap.get(packageName);          if (permissions == null) {              permissions = new ArraySet<>();          } -        ArraySet<String> denyPermissions = mPrivAppDenyPermissions.get(packageName); +        ArraySet<String> denyPermissions = denyMap.get(packageName);          int depth = parser.getDepth();          while (XmlUtils.nextElementWithin(parser, depth)) {              String name = parser.getName(); @@ -711,9 +737,9 @@ public class SystemConfig {                  denyPermissions.add(permName);              }          } -        mPrivAppPermissions.put(packageName, permissions); +        grantMap.put(packageName, permissions);          if (denyPermissions != null) { -            mPrivAppDenyPermissions.put(packageName, denyPermissions); +            denyMap.put(packageName, denyPermissions);          }      } diff --git a/core/res/res/values/attrs_manifest.xml b/core/res/res/values/attrs_manifest.xml index 4d410e5447de..4d67494be21d 100644 --- a/core/res/res/values/attrs_manifest.xml +++ b/core/res/res/values/attrs_manifest.xml @@ -262,6 +262,9 @@               and the OEM has white-listed the app to receive this permission by the OEM.           -->          <flag name="oem" value="0x4000" /> +        <!-- Additional flag from base permission type: this permission can be granted to +             privileged apps in vendor partition. --> +        <flag name="vendorPrivileged" value="0x8000" />      </attr>      <!-- Flags indicating more context for a permission group. --> diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java index 2d5f7c7124c4..b34de7140b6b 100644 --- a/services/core/java/com/android/server/pm/PackageManagerService.java +++ b/services/core/java/com/android/server/pm/PackageManagerService.java @@ -467,6 +467,7 @@ public class PackageManagerService extends IPackageManager.Stub      static final int SCAN_AS_SYSTEM = 1<<17;      static final int SCAN_AS_PRIVILEGED = 1<<18;      static final int SCAN_AS_OEM = 1<<19; +    static final int SCAN_AS_VENDOR = 1<<20;      @IntDef(flag = true, prefix = { "SCAN_" }, value = {              SCAN_NO_DEX, @@ -2574,8 +2575,25 @@ public class PackageManagerService extends IPackageManager.Stub                      | SCAN_AS_SYSTEM,                      0); -            // Collect all vendor packages. -            File vendorAppDir = new File("/vendor/app"); +            // Collected privileged vendor packages. +                File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), +                        "priv-app"); +            try { +                privilegedVendorAppDir = privilegedVendorAppDir.getCanonicalFile(); +            } catch (IOException e) { +                // failed to look up canonical path, continue with original one +            } +            scanDirTracedLI(privilegedVendorAppDir, +                    mDefParseFlags +                    | PackageParser.PARSE_IS_SYSTEM_DIR, +                    scanFlags +                    | SCAN_AS_SYSTEM +                    | SCAN_AS_VENDOR +                    | SCAN_AS_PRIVILEGED, +                    0); + +            // Collect ordinary vendor packages. +            File vendorAppDir = new File(Environment.getVendorDirectory(), "app");              try {                  vendorAppDir = vendorAppDir.getCanonicalFile();              } catch (IOException e) { @@ -2585,7 +2603,8 @@ public class PackageManagerService extends IPackageManager.Stub                      mDefParseFlags                      | PackageParser.PARSE_IS_SYSTEM_DIR,                      scanFlags -                    | SCAN_AS_SYSTEM, +                    | SCAN_AS_SYSTEM +                    | SCAN_AS_VENDOR,                      0);              // Collect all OEM packages. @@ -2770,13 +2789,23 @@ public class PackageManagerService extends IPackageManager.Stub                              rescanFlags =                                      scanFlags                                      | SCAN_AS_SYSTEM; +                        } else if (FileUtils.contains(privilegedVendorAppDir, scanFile)) { +                            reparseFlags = +                                    mDefParseFlags | +                                    PackageParser.PARSE_IS_SYSTEM_DIR; +                            rescanFlags = +                                    scanFlags +                                    | SCAN_AS_SYSTEM +                                    | SCAN_AS_VENDOR +                                    | SCAN_AS_PRIVILEGED;                          } else if (FileUtils.contains(vendorAppDir, scanFile)) {                              reparseFlags =                                      mDefParseFlags |                                      PackageParser.PARSE_IS_SYSTEM_DIR;                              rescanFlags =                                      scanFlags -                                    | SCAN_AS_SYSTEM; +                                    | SCAN_AS_SYSTEM +                                    | SCAN_AS_VENDOR;                          } else if (FileUtils.contains(oemAppDir, scanFile)) {                              reparseFlags =                                      mDefParseFlags | @@ -8335,6 +8364,13 @@ public class PackageManagerService extends IPackageManager.Stub              } else {                  updatedPs.pkgPrivateFlags &= ~ApplicationInfo.PRIVATE_FLAG_OEM;              } +            // If new package is not located in "/vendor" (e.g. due to an OTA), +            // it needs to drop FLAG_VENDOR. +            if (locationIsVendor(pkg.codePath)) { +                updatedPs.pkgPrivateFlags |= ApplicationInfo.PRIVATE_FLAG_VENDOR; +            } else { +                updatedPs.pkgPrivateFlags &= ~ApplicationInfo.PRIVATE_FLAG_VENDOR; +            }              if (ps != null && !ps.codePathString.equals(pkg.codePath)) {                  // The path has changed from what was last scanned...  check the @@ -8455,11 +8491,17 @@ public class PackageManagerService extends IPackageManager.Stub                  scanFlags |= SCAN_AS_PRIVILEGED;              } -            // An updated OEM app will not have the PARSE_IS_OEM +            // An updated OEM app will not have the SCAN_AS_OEM              // flag set initially              if ((updatedPs.pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_OEM) != 0) {                  scanFlags |= SCAN_AS_OEM;              } + +            // An updated vendor app will not have the SCAN_AS_VENDOR +            // flag set initially +            if ((updatedPs.pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0) { +                scanFlags |= SCAN_AS_VENDOR; +            }          }          // Verify certificates against what was last scanned @@ -10208,6 +10250,10 @@ public class PackageManagerService extends IPackageManager.Stub              pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_OEM;          } +        if ((scanFlags & SCAN_AS_VENDOR) != 0) { +            pkg.applicationInfo.privateFlags |= ApplicationInfo.PRIVATE_FLAG_VENDOR; +        } +          if (!isSystemApp(pkg)) {              // Only system apps can use these features.              pkg.mOriginalPackages = null; @@ -15574,18 +15620,22 @@ public class PackageManagerService extends IPackageManager.Stub          boolean sysPkg = (isSystemApp(oldPackage));          if (sysPkg) { -            // Set the system/privileged/oem flags as needed +            // Set the system/privileged/oem/vendor flags as needed              final boolean privileged =                      (oldPackage.applicationInfo.privateFlags                              & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;              final boolean oem =                      (oldPackage.applicationInfo.privateFlags                              & ApplicationInfo.PRIVATE_FLAG_OEM) != 0; +            final boolean vendor = +                    (oldPackage.applicationInfo.privateFlags +                            & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0;              final @ParseFlags int systemParseFlags = parseFlags;              final @ScanFlags int systemScanFlags = scanFlags                      | SCAN_AS_SYSTEM                      | (privileged ? SCAN_AS_PRIVILEGED : 0) -                    | (oem ? SCAN_AS_OEM : 0); +                    | (oem ? SCAN_AS_OEM : 0) +                    | (vendor ? SCAN_AS_VENDOR : 0);              replaceSystemPackageLIF(oldPackage, pkg, systemParseFlags, systemScanFlags,                      user, allUsers, installerPackageName, res, installReason); @@ -16759,6 +16809,10 @@ public class PackageManagerService extends IPackageManager.Stub          return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_OEM) != 0;      } +    private static boolean isVendorApp(PackageParser.Package pkg) { +        return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0; +    } +      private static boolean hasDomainURLs(PackageParser.Package pkg) {          return (pkg.applicationInfo.privateFlags & ApplicationInfo.PRIVATE_FLAG_HAS_DOMAIN_URLS) != 0;      } @@ -17493,7 +17547,9 @@ public class PackageManagerService extends IPackageManager.Stub      static boolean locationIsPrivileged(String path) {          try {              final File privilegedAppDir = new File(Environment.getRootDirectory(), "priv-app"); -            return path.startsWith(privilegedAppDir.getCanonicalPath()); +            final File privilegedVendorAppDir = new File(Environment.getVendorDirectory(), "priv-app"); +            return path.startsWith(privilegedAppDir.getCanonicalPath()) +                    || path.startsWith(privilegedVendorAppDir.getCanonicalPath());          } catch (IOException e) {              Slog.e(TAG, "Unable to access code path " + path);          } @@ -17509,6 +17565,15 @@ public class PackageManagerService extends IPackageManager.Stub          return false;      } +    static boolean locationIsVendor(String path) { +        try { +            return path.startsWith(Environment.getVendorDirectory().getCanonicalPath()); +        } catch (IOException e) { +            Slog.e(TAG, "Unable to access code path " + path); +        } +        return false; +    } +      /*       * Tries to delete system package.       */ @@ -17630,6 +17695,9 @@ public class PackageManagerService extends IPackageManager.Stub          if (locationIsOem(codePathString)) {              scanFlags |= SCAN_AS_OEM;          } +        if (locationIsVendor(codePathString)) { +            scanFlags |= SCAN_AS_VENDOR; +        }          final File codePath = new File(codePathString);          final PackageParser.Package pkg = diff --git a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java index 44f36d1734c8..45b94a468514 100644 --- a/services/core/java/com/android/server/pm/PackageManagerShellCommand.java +++ b/services/core/java/com/android/server/pm/PackageManagerShellCommand.java @@ -1538,13 +1538,26 @@ class PackageManagerShellCommand extends ShellCommand {          return 0;      } +    private boolean isVendorApp(String pkg) { +        try { +            final PackageInfo info = mInterface.getPackageInfo(pkg, 0, UserHandle.USER_SYSTEM); +            return info != null && info.applicationInfo.isVendor(); +        } catch (RemoteException e) { +            return false; +        } +    } +      private int runGetPrivappPermissions() {          final String pkg = getNextArg();          if (pkg == null) {              getErrPrintWriter().println("Error: no package specified.");              return 1;          } -        ArraySet<String> privAppPermissions = SystemConfig.getInstance().getPrivAppPermissions(pkg); + +        ArraySet<String> privAppPermissions = isVendorApp(pkg) ? +                SystemConfig.getInstance().getVendorPrivAppPermissions(pkg) +                    : SystemConfig.getInstance().getPrivAppPermissions(pkg); +          getOutPrintWriter().println(privAppPermissions == null                  ? "{}" : privAppPermissions.toString());          return 0; @@ -1556,10 +1569,13 @@ class PackageManagerShellCommand extends ShellCommand {              getErrPrintWriter().println("Error: no package specified.");              return 1;          } -        ArraySet<String> privAppDenyPermissions = -                SystemConfig.getInstance().getPrivAppDenyPermissions(pkg); -        getOutPrintWriter().println(privAppDenyPermissions == null -                ? "{}" : privAppDenyPermissions.toString()); + +        ArraySet<String> privAppPermissions = isVendorApp(pkg) ? +                SystemConfig.getInstance().getVendorPrivAppDenyPermissions(pkg) +                    : SystemConfig.getInstance().getPrivAppDenyPermissions(pkg); + +        getOutPrintWriter().println(privAppPermissions == null +                ? "{}" : privAppPermissions.toString());          return 0;      } diff --git a/services/core/java/com/android/server/pm/PackageSetting.java b/services/core/java/com/android/server/pm/PackageSetting.java index 3b414e9a0dc5..258dd4d4dcb3 100644 --- a/services/core/java/com/android/server/pm/PackageSetting.java +++ b/services/core/java/com/android/server/pm/PackageSetting.java @@ -140,6 +140,10 @@ public final class PackageSetting extends PackageSettingBase {          return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_OEM) != 0;      } +    public boolean isVendor() { +        return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR) != 0; +    } +      public boolean isForwardLocked() {          return (pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK) != 0;      } diff --git a/services/core/java/com/android/server/pm/SettingBase.java b/services/core/java/com/android/server/pm/SettingBase.java index c97f5e5443a3..46ba0060d93e 100644 --- a/services/core/java/com/android/server/pm/SettingBase.java +++ b/services/core/java/com/android/server/pm/SettingBase.java @@ -61,6 +61,7 @@ abstract class SettingBase {          this.pkgPrivateFlags = pkgPrivateFlags                  & (ApplicationInfo.PRIVATE_FLAG_PRIVILEGED                  | ApplicationInfo.PRIVATE_FLAG_OEM +                | ApplicationInfo.PRIVATE_FLAG_VENDOR                  | ApplicationInfo.PRIVATE_FLAG_FORWARD_LOCK                  | ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER);      } diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java index ddad6774871d..af1a4d148856 100644 --- a/services/core/java/com/android/server/pm/Settings.java +++ b/services/core/java/com/android/server/pm/Settings.java @@ -847,6 +847,8 @@ public final class Settings {                  pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED;          pkgSetting.pkgPrivateFlags |=                  pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_OEM; +        pkgSetting.pkgPrivateFlags |= +                pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_VENDOR;          pkgSetting.primaryCpuAbiString = primaryCpuAbi;          pkgSetting.secondaryCpuAbiString = secondaryCpuAbi;          if (childPkgNames != null) { @@ -4421,6 +4423,7 @@ public final class Settings {              ApplicationInfo.PRIVATE_FLAG_PRIVILEGED, "PRIVILEGED",              ApplicationInfo.PRIVATE_FLAG_REQUIRED_FOR_SYSTEM_USER, "REQUIRED_FOR_SYSTEM_USER",              ApplicationInfo.PRIVATE_FLAG_STATIC_SHARED_LIBRARY, "STATIC_SHARED_LIBRARY", +            ApplicationInfo.PRIVATE_FLAG_VENDOR, "VENDOR",              ApplicationInfo.PRIVATE_FLAG_VIRTUAL_PRELOAD, "VIRTUAL_PRELOAD",      }; diff --git a/services/core/java/com/android/server/pm/permission/BasePermission.java b/services/core/java/com/android/server/pm/permission/BasePermission.java index 8c86db64471d..75a61064c1c9 100644 --- a/services/core/java/com/android/server/pm/permission/BasePermission.java +++ b/services/core/java/com/android/server/pm/permission/BasePermission.java @@ -225,6 +225,9 @@ public final class BasePermission {      public boolean isVerifier() {          return (protectionLevel & PermissionInfo.PROTECTION_FLAG_VERIFIER) != 0;      } +    public boolean isVendorPrivileged() { +        return (protectionLevel & PermissionInfo.PROTECTION_FLAG_VENDOR_PRIVILEGED) != 0; +    }      public void transfer(@NonNull String origPackageName, @NonNull String newPackageName) {          if (!origPackageName.equals(sourcePackageName)) { diff --git a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java index 7d8e20696aff..90ac4ab7dd42 100644 --- a/services/core/java/com/android/server/pm/permission/PermissionManagerService.java +++ b/services/core/java/com/android/server/pm/permission/PermissionManagerService.java @@ -959,8 +959,9 @@ Slog.e(TAG, "TODD: Packages: " + Arrays.toString(packages));       * <p>This handles parent/child apps.       */      private boolean hasPrivappWhitelistEntry(String perm, PackageParser.Package pkg) { -        ArraySet<String> wlPermissions = SystemConfig.getInstance() -                .getPrivAppPermissions(pkg.packageName); +        ArraySet<String> wlPermissions = pkg.isVendor() ? +                SystemConfig.getInstance().getVendorPrivAppPermissions(pkg.packageName) +                    : SystemConfig.getInstance().getPrivAppPermissions(pkg.packageName);          // Let's check if this package is whitelisted...          boolean whitelisted = wlPermissions != null && wlPermissions.contains(perm);          // If it's not, we'll also tail-recurse to the parent. @@ -971,7 +972,8 @@ Slog.e(TAG, "TODD: Packages: " + Arrays.toString(packages));      private boolean grantSignaturePermission(String perm, PackageParser.Package pkg,              BasePermission bp, PermissionsState origPermissions) {          boolean oemPermission = bp.isOEM(); -        boolean privilegedPermission = bp.isPrivileged(); +        boolean vendorPrivilegedPermission = bp.isVendorPrivileged(); +        boolean privilegedPermission = bp.isPrivileged() || bp.isVendorPrivileged();          boolean privappPermissionsDisable =                  RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_DISABLE;          boolean platformPermission = PLATFORM_PACKAGE_NAME.equals(bp.getSourcePackageName()); @@ -982,8 +984,11 @@ Slog.e(TAG, "TODD: Packages: " + Arrays.toString(packages));                  // Only report violations for apps on system image                  if (!mSystemReady && !pkg.isUpdatedSystemApp()) {                      // it's only a reportable violation if the permission isn't explicitly denied -                    final ArraySet<String> deniedPermissions = SystemConfig.getInstance() -                            .getPrivAppDenyPermissions(pkg.packageName); +                    final ArraySet<String> deniedPermissions = pkg.isVendor() ? +                            SystemConfig.getInstance() +                                    .getVendorPrivAppDenyPermissions(pkg.packageName) +                            : SystemConfig.getInstance() +                                    .getPrivAppDenyPermissions(pkg.packageName);                      final boolean permissionViolation =                              deniedPermissions == null || !deniedPermissions.contains(perm);                      if (permissionViolation) { @@ -1086,6 +1091,15 @@ Slog.e(TAG, "TODD: Packages: " + Arrays.toString(packages));                              || (oemPermission && pkg.isOem()                                      && canGrantOemPermission(ps, perm));                  } +                // In any case, don't grant a privileged permission to privileged vendor apps, if +                // the permission's protectionLevel does not have the extra 'vendorPrivileged' +                // flag. +                if (allowed && privilegedPermission && +                        !vendorPrivilegedPermission && pkg.isVendor()) { +                   Slog.w(TAG, "Permission " + perm + " cannot be granted to privileged vendor apk " +                           + pkg.packageName + " because it isn't a 'vendorPrivileged' permission."); +                   allowed = false; +                }              }          }          if (!allowed) { diff --git a/services/tests/servicestests/src/com/android/server/pm/PackageManagerPresubmitTest.java b/services/tests/servicestests/src/com/android/server/pm/PackageManagerPresubmitTest.java deleted file mode 100644 index e6b4540f73c9..000000000000 --- a/services/tests/servicestests/src/com/android/server/pm/PackageManagerPresubmitTest.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * 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.server.pm; - -import android.content.Context; -import android.content.pm.PackageInfo; -import android.content.pm.PackageManager; -import android.content.pm.PermissionInfo; -import android.platform.test.annotations.GlobalPresubmit; -import android.support.test.InstrumentationRegistry; -import android.support.test.filters.SmallTest; -import android.support.test.runner.AndroidJUnit4; -import android.util.ArraySet; - -import com.android.internal.os.RoSystemProperties; -import com.android.internal.util.ArrayUtils; -import com.android.server.SystemConfig; - -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; - -import java.util.List; - -import static android.content.pm.PackageManager.GET_PERMISSIONS; -import static junit.framework.Assert.assertTrue; - - -/** - * Presubmit tests for {@link PackageManager}. - */ -@RunWith(AndroidJUnit4.class) -public class PackageManagerPresubmitTest { - -    private Context mContext; - -    private PackageManager mPackageManager; - -    @Before -    public void setUp() { -        mContext = InstrumentationRegistry.getContext(); -        mPackageManager = mContext.getPackageManager(); -    } - -    /** -     * <p>This test ensures that all signature|privileged permissions are granted to priv-apps. -     * If CONTROL_PRIVAPP_PERMISSIONS_ENFORCE is set, the test also verifies that -     * granted permissions are whitelisted in {@link SystemConfig} -     */ -    @Test -    @SmallTest -    @GlobalPresubmit -    public void testPrivAppPermissions() throws PackageManager.NameNotFoundException { -        List<PackageInfo> installedPackages = mPackageManager -                .getInstalledPackages(PackageManager.MATCH_UNINSTALLED_PACKAGES | GET_PERMISSIONS); -        for (PackageInfo packageInfo : installedPackages) { -            if (!packageInfo.applicationInfo.isPrivilegedApp() -                    || PackageManagerService.PLATFORM_PACKAGE_NAME.equals(packageInfo.packageName)) { -                continue; -            } -            testPackagePrivAppPermission(packageInfo); -        } - -    } - -    private void testPackagePrivAppPermission(PackageInfo packageInfo) -            throws PackageManager.NameNotFoundException { -        String packageName = packageInfo.packageName; -        ArraySet<String> privAppPermissions = SystemConfig.getInstance() -                .getPrivAppPermissions(packageName); -        if (ArrayUtils.isEmpty(packageInfo.requestedPermissions)) { -            return; -        } -        for (int i = 0; i < packageInfo.requestedPermissions.length; i++) { -            String pName = packageInfo.requestedPermissions[i]; -            int protectionLevel; -            boolean platformPermission; -            try { -                PermissionInfo permissionInfo = mPackageManager.getPermissionInfo(pName, 0); -                platformPermission = PackageManagerService.PLATFORM_PACKAGE_NAME.equals( -                        permissionInfo.packageName); -                protectionLevel = permissionInfo.protectionLevel; -            } catch (PackageManager.NameNotFoundException e) { -                continue; -            } -            if ((protectionLevel & PermissionInfo.PROTECTION_FLAG_PRIVILEGED) != 0) { -                boolean granted = (packageInfo.requestedPermissionsFlags[i] -                        & PackageInfo.REQUESTED_PERMISSION_GRANTED) != 0; -                // if privapp permissions are enforced, platform permissions must be whitelisted -                // in SystemConfig -                if (platformPermission && RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) { -                    assertTrue("Permission " + pName + " should be declared in " -                                    + "privapp-permissions-<category>.xml file for package " -                                    + packageName, -                            privAppPermissions != null && privAppPermissions.contains(pName)); -                } -                assertTrue("Permission " + pName + " should be granted to " + packageName, granted); -            } -        } -    } -} diff --git a/tests/privapp-permissions/Android.mk b/tests/privapp-permissions/Android.mk new file mode 100644 index 000000000000..b001c8c466a9 --- /dev/null +++ b/tests/privapp-permissions/Android.mk @@ -0,0 +1,31 @@ +LOCAL_PATH:= $(call my-dir) + +include $(CLEAR_VARS) +LOCAL_PACKAGE_NAME := PrivAppPermissionTest +LOCAL_PRIVILEGED_MODULE := true +LOCAL_MANIFEST_FILE := system/AndroidManifest.xml +LOCAL_REQUIRED_MODULES := privapp-permissions-test.xml +include $(BUILD_PACKAGE) + +include $(CLEAR_VARS) +LOCAL_MODULE := privapp-permissions-test.xml +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_PATH := $(TARGET_OUT_ETC)/permissions +LOCAL_SRC_FILES:= system/privapp-permissions-test.xml +include $(BUILD_PREBUILT) + +include $(CLEAR_VARS) +LOCAL_PACKAGE_NAME := VendorPrivAppPermissionTest +LOCAL_PRIVILEGED_MODULE := true +LOCAL_MANIFEST_FILE := vendor/AndroidManifest.xml +LOCAL_VENDOR_MODULE := true +LOCAL_REQUIRED_MODULES := vendorprivapp-permissions-test.xml +include $(BUILD_PACKAGE) + +include $(CLEAR_VARS) +LOCAL_MODULE := vendorprivapp-permissions-test.xml +LOCAL_MODULE_CLASS := ETC +LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_ETC)/permissions +LOCAL_SRC_FILES:= vendor/privapp-permissions-test.xml +include $(BUILD_PREBUILT) + diff --git a/tests/privapp-permissions/system/AndroidManifest.xml b/tests/privapp-permissions/system/AndroidManifest.xml new file mode 100644 index 000000000000..2099e31bd2c1 --- /dev/null +++ b/tests/privapp-permissions/system/AndroidManifest.xml @@ -0,0 +1,23 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + * Copyright (C) 2017 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. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" +          package="com.android.framework.permission.privapp.tests.system"> + +    <!-- MANAGE_USB is signature|privileged --> +    <uses-permission android:name="android.permission.MANAGE_USB"/> +</manifest> diff --git a/tests/privapp-permissions/system/privapp-permissions-test.xml b/tests/privapp-permissions/system/privapp-permissions-test.xml new file mode 100644 index 000000000000..a0cb6bc74195 --- /dev/null +++ b/tests/privapp-permissions/system/privapp-permissions-test.xml @@ -0,0 +1,6 @@ +<?xml version="1.0" encoding="utf-8"?> +<permissions> +    <privapp-permissions package="com.android.framework.permission.privapp.tests.system"> +        <permission name="android.permission.MANAGE_USB"/> +    </privapp-permissions> +</permissions> diff --git a/tests/privapp-permissions/vendor/AndroidManifest.xml b/tests/privapp-permissions/vendor/AndroidManifest.xml new file mode 100644 index 000000000000..78dedc5f199b --- /dev/null +++ b/tests/privapp-permissions/vendor/AndroidManifest.xml @@ -0,0 +1,25 @@ +<?xml version="1.0" encoding="utf-8"?> +<!-- + * Copyright (C) 2017 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. + --> + +<manifest xmlns:android="http://schemas.android.com/apk/res/android" +          package="com.android.framework.permission.privapp.tests.vendor"> + +    <!-- BIND_IMS_SERVICE is signature|privileged|vendorPrivileged --> +    <uses-permission android:name="android.permission.BIND_IMS_SERVICE"/> +    <!-- MANAGE_USB is signature|privileged and thus cannot be granted to this app --> +    <uses-permission android:name="android.permission.MANAGE_USB"/> +</manifest> diff --git a/tests/privapp-permissions/vendor/privapp-permissions-test.xml b/tests/privapp-permissions/vendor/privapp-permissions-test.xml new file mode 100644 index 000000000000..51c588f0dea7 --- /dev/null +++ b/tests/privapp-permissions/vendor/privapp-permissions-test.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="utf-8"?> +<permissions> +    <privapp-permissions package="com.android.framework.permission.privapp.tests.vendor"> +        <permission name="android.permission.BIND_IMS_SERVICE"/> +        <permission name="android.permission.MANAGE_USB"/> +    </privapp-permissions> +</permissions> |