Work on issue #143085640: Per-process network access control

Fix some issues when apps start declaring processes, add validation
that apps don't use processes they haven't declared (if they
declared some).  Also add package dump output for the processes it
has declared.

Bug: 143085640
Test: atest CtsAppSecurityHostTestCases:UseProcessTest
Change-Id: If1d13bf402d2b0aea06f0c2c02d5e392c774c812
diff --git a/core/java/android/content/pm/PackageManager.java b/core/java/android/content/pm/PackageManager.java
index b64c001..6d5e8fb 100644
--- a/core/java/android/content/pm/PackageManager.java
+++ b/core/java/android/content/pm/PackageManager.java
@@ -1506,6 +1506,15 @@
      */
     public static final int INSTALL_FAILED_WRONG_INSTALLED_VERSION = -121;
 
+    /**
+     * Installation return code: this is passed in the {@link PackageInstaller#EXTRA_LEGACY_STATUS}
+     * if the new package failed because it contains a request to use a process that was not
+     * explicitly defined as part of its <processes> tag.
+     *
+     * @hide
+     */
+    public static final int INSTALL_FAILED_PROCESS_NOT_DEFINED = -122;
+
     /** @hide */
     @IntDef(flag = true, prefix = { "DELETE_" }, value = {
             DELETE_KEEP_DATA,
@@ -7237,6 +7246,7 @@
             case INSTALL_FAILED_MISSING_SPLIT: return "INSTALL_FAILED_MISSING_SPLIT";
             case INSTALL_FAILED_BAD_SIGNATURE: return "INSTALL_FAILED_BAD_SIGNATURE";
             case INSTALL_FAILED_WRONG_INSTALLED_VERSION: return "INSTALL_FAILED_WRONG_INSTALLED_VERSION";
+            case INSTALL_FAILED_PROCESS_NOT_DEFINED: return "INSTALL_FAILED_PROCESS_NOT_DEFINED";
             default: return Integer.toString(status);
         }
     }
diff --git a/core/java/android/content/pm/parsing/ComponentParseUtils.java b/core/java/android/content/pm/parsing/ComponentParseUtils.java
index 9a0a6d5..a0f5812 100644
--- a/core/java/android/content/pm/parsing/ComponentParseUtils.java
+++ b/core/java/android/content/pm/parsing/ComponentParseUtils.java
@@ -3414,16 +3414,12 @@
             proc.name = sa.getNonConfigurationString(
                     R.styleable.AndroidManifestProcess_process,0);
             proc.name = PackageParser.buildProcessName(parsingPackage.getPackageName(),
-                    null, proc.name, flags, separateProcesses, outError);
-
-            if (proc.name == null || proc.name.length() <= 0) {
-                outError[0] = "<process> does not specify android:process";
+                    parsingPackage.getPackageName(), proc.name, flags, separateProcesses, outError);
+            if (outError[0] != null) {
                 return null;
             }
-            proc.name = PackageParser.buildProcessName(parsingPackage.getPackageName(),
-                    parsingPackage.getPackageName(), proc.name,
-                    flags, separateProcesses, outError);
-            if (outError[0] != null) {
+            if (proc.name == null || proc.name.length() <= 0) {
+                outError[0] = "<process> does not specify android:process";
                 return null;
             }
         } finally {
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index fc33c25..2b4d15e 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -615,13 +615,20 @@
             int _uid) {
         mService = _service;
         info = _info;
+        ProcessInfo procInfo = null;
         if (_service.mPackageManagerInt != null) {
             ArrayMap<String, ProcessInfo> processes =
                     _service.mPackageManagerInt.getProcessesForUid(_uid);
-            processInfo = processes != null ? processes.get(_processName) : null;
-        } else {
-            processInfo = null;
+            if (processes != null) {
+                procInfo = processes.get(_processName);
+                if (procInfo != null && procInfo.deniedPermissions == null) {
+                    // If this process hasn't asked for permissions to be denied, then
+                    // we don't care about it.
+                    procInfo = null;
+                }
+            }
         }
+        processInfo = procInfo;
         isolated = _info.uid != _uid;
         appZygote = (UserHandle.getAppId(_uid) >= Process.FIRST_APP_ZYGOTE_ISOLATED_UID
                 && UserHandle.getAppId(_uid) <= Process.LAST_APP_ZYGOTE_ISOLATED_UID);
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 93a0506..e446b8c 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -55,6 +55,7 @@
 import static android.content.pm.PackageManager.INSTALL_FAILED_INVALID_INSTALL_LOCATION;
 import static android.content.pm.PackageManager.INSTALL_FAILED_MISSING_SHARED_LIBRARY;
 import static android.content.pm.PackageManager.INSTALL_FAILED_PACKAGE_CHANGED;
+import static android.content.pm.PackageManager.INSTALL_FAILED_PROCESS_NOT_DEFINED;
 import static android.content.pm.PackageManager.INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
 import static android.content.pm.PackageManager.INSTALL_FAILED_TEST_ONLY;
 import static android.content.pm.PackageManager.INSTALL_FAILED_UPDATE_INCOMPATIBLE;
@@ -205,6 +206,7 @@
 import android.content.pm.dex.IArtManager;
 import android.content.pm.parsing.AndroidPackage;
 import android.content.pm.parsing.ApkParseUtils;
+import android.content.pm.parsing.ComponentParseUtils;
 import android.content.pm.parsing.ComponentParseUtils.ParsedActivity;
 import android.content.pm.parsing.ComponentParseUtils.ParsedActivityIntentInfo;
 import android.content.pm.parsing.ComponentParseUtils.ParsedComponent;
@@ -11246,6 +11248,26 @@
         return object;
     }
 
+    private <T extends ComponentParseUtils.ParsedMainComponent>
+            void assertPackageProcesses(AndroidPackage pkg, List<T> components,
+            ArrayMap<String, ComponentParseUtils.ParsedProcess> procs, String compName)
+            throws PackageManagerException {
+        if (components == null) {
+            return;
+        }
+        for (int i = components.size() - 1; i >= 0; i--) {
+            final ComponentParseUtils.ParsedMainComponent<?> component = components.get(i);
+            if (!procs.containsKey(component.getProcessName())) {
+                throw new PackageManagerException(
+                        INSTALL_FAILED_PROCESS_NOT_DEFINED,
+                        "Can't install because " + compName + " " + component.className
+                                + "'s process attribute " + component.getProcessName()
+                                + " (in package " + pkg.getPackageName()
+                                + ") is not included in the <processes> list");
+            }
+        }
+    }
+
     /**
      * Asserts the parsed package is valid according to the given policy. If the
      * package is invalid, for whatever reason, throws {@link PackageManagerException}.
@@ -11475,6 +11497,24 @@
                 mComponentResolver.assertProvidersNotDefined(pkg);
             }
 
+            // If this package has defined explicit processes, then ensure that these are
+            // the only processes used by its components.
+            final ArrayMap<String, ComponentParseUtils.ParsedProcess> procs = pkg.getProcesses();
+            if (procs != null) {
+                if (!procs.containsKey(pkg.getProcessName())) {
+                    throw new PackageManagerException(
+                            INSTALL_FAILED_PROCESS_NOT_DEFINED,
+                            "Can't install because application tag's process attribute "
+                                    + pkg.getProcessName()
+                                    + " (in package " + pkg.getPackageName()
+                                    + ") is not included in the <processes> list");
+                }
+                assertPackageProcesses(pkg, pkg.getActivities(), procs, "activity");
+                assertPackageProcesses(pkg, pkg.getServices(), procs, "service");
+                assertPackageProcesses(pkg, pkg.getReceivers(), procs, "receiver");
+                assertPackageProcesses(pkg, pkg.getProviders(), procs, "provider");
+            }
+
             // Verify that packages sharing a user with a privileged app are marked as privileged.
             if (!pkg.isPrivileged() && (pkg.getSharedUserId() != null)) {
                 SharedUserSetting sharedUserSetting = null;
diff --git a/services/core/java/com/android/server/pm/Settings.java b/services/core/java/com/android/server/pm/Settings.java
index 5d948b2..eb2902d 100644
--- a/services/core/java/com/android/server/pm/Settings.java
+++ b/services/core/java/com/android/server/pm/Settings.java
@@ -4564,7 +4564,7 @@
                 pw.print("anyDensity");
             }
             pw.println("]");
-            List<String> libraryNames = pkg.getLibraryNames();
+            final List<String> libraryNames = pkg.getLibraryNames();
             if (libraryNames != null && libraryNames.size() > 0) {
                 pw.print(prefix); pw.println("  dynamic libraries:");
                 for (int i = 0; i< libraryNames.size(); i++) {
@@ -4579,7 +4579,7 @@
                 pw.print(" version:"); pw.println(pkg.getStaticSharedLibVersion());
             }
 
-            List<String> usesLibraries = pkg.getUsesLibraries();
+            final List<String> usesLibraries = pkg.getUsesLibraries();
             if (usesLibraries != null && usesLibraries.size() > 0) {
                 pw.print(prefix); pw.println("  usesLibraries:");
                 for (int i=0; i< usesLibraries.size(); i++) {
@@ -4587,8 +4587,8 @@
                 }
             }
 
-            List<String> usesStaticLibraries = pkg.getUsesStaticLibraries();
-            long[] usesStaticLibrariesVersions = pkg.getUsesStaticLibrariesVersions();
+            final List<String> usesStaticLibraries = pkg.getUsesStaticLibraries();
+            final long[] usesStaticLibrariesVersions = pkg.getUsesStaticLibrariesVersions();
             if (usesStaticLibraries != null
                     && usesStaticLibraries.size() > 0) {
                 pw.print(prefix); pw.println("  usesStaticLibraries:");
@@ -4599,7 +4599,7 @@
                 }
             }
 
-            List<String> usesOptionalLibraries = pkg.getUsesOptionalLibraries();
+            final List<String> usesOptionalLibraries = pkg.getUsesOptionalLibraries();
             if (usesOptionalLibraries != null
                     && usesOptionalLibraries.size() > 0) {
                 pw.print(prefix); pw.println("  usesOptionalLibraries:");
@@ -4609,7 +4609,7 @@
                 }
             }
 
-            String[] usesLibraryFiles = pkg.getUsesLibraryFiles();
+            final String[] usesLibraryFiles = pkg.getUsesLibraryFiles();
             if (usesLibraryFiles != null
                     && usesLibraryFiles.length > 0) {
                 pw.print(prefix); pw.println("  usesLibraryFiles:");
@@ -4617,6 +4617,20 @@
                     pw.print(prefix); pw.print("    "); pw.println(usesLibraryFiles[i]);
                 }
             }
+            final ArrayMap<String, ComponentParseUtils.ParsedProcess> procs = pkg.getProcesses();
+            if (procs != null) {
+                pw.print(prefix); pw.println("  processes:");
+                for (int i = 0; i < procs.size(); i++) {
+                    final ComponentParseUtils.ParsedProcess proc = procs.valueAt(i);
+                    pw.print(prefix); pw.print("    "); pw.println(proc.name);
+                    if (proc.deniedPermissions != null) {
+                        for (int j = 0; j < proc.deniedPermissions.size(); j++) {
+                            pw.print(prefix); pw.print("      deny: ");
+                            pw.println(proc.deniedPermissions.valueAt(j));
+                        }
+                    }
+                }
+            }
         }
         pw.print(prefix); pw.print("  timeStamp=");
             date.setTime(ps.timeStamp);
diff --git a/tools/aapt2/link/ManifestFixer.cpp b/tools/aapt2/link/ManifestFixer.cpp
index 954d401..2af118c 100644
--- a/tools/aapt2/link/ManifestFixer.cpp
+++ b/tools/aapt2/link/ManifestFixer.cpp
@@ -428,6 +428,12 @@
 
   application_action["meta-data"] = meta_data_action;
 
+  application_action["processes"];
+  application_action["processes"]["deny-permission"];
+  application_action["processes"]["allow-permission"];
+  application_action["processes"]["process"]["deny-permission"];
+  application_action["processes"]["process"]["allow-permission"];
+
   application_action["activity"] = component_action;
   application_action["activity"]["layout"];