OSDN Git Service

Revert "Revert "pm: SharedUserId: Assign seinfo using actual targetSdkVersion""
authorJeff Vander Stoep <jeffv@google.com>
Tue, 6 Mar 2018 23:52:22 +0000 (15:52 -0800)
committerJeffrey Vander Stoep <jeffv@google.com>
Wed, 7 Mar 2018 18:49:12 +0000 (18:49 +0000)
Commit 042f4bb6 'pm: Modify getPackage() to only return non-null
packages' prevents the NullPointerException. b/
This reverts commit 00b4fa8b138de801b0caf371a950fcda7b98bb83.

Bug: 74214574
Bug: 72290969
Test: Same tests run on original commit.
Test: successfully flash and boot from bild 4504078 to ToT master.
Change-Id: Ia1e900ebe0eb8f9d10fd0eddbf658f52e1ea79b4
(cherry picked from commit 32ef1c2eb0fe32d8fd02a44bc77b40ab7719c433)

core/java/android/content/pm/ApplicationInfo.java
services/core/java/com/android/server/pm/PackageManagerService.java
services/core/java/com/android/server/pm/SELinuxMMAC.java
services/core/java/com/android/server/pm/SharedUserSetting.java

index 4a8f61c..efa90d3 100644 (file)
@@ -763,15 +763,13 @@ public class ApplicationInfo extends PackageItemInfo implements Parcelable {
     public String[] resourceDirs;
 
     /**
-     * String retrieved from the seinfo tag found in selinux policy. This value
-     * can be overridden with a value set through the mac_permissions.xml policy
-     * construct. This value is useful in setting an SELinux security context on
-     * the process as well as its data directory. The String default is being used
-     * here to represent a catchall label when no policy matches.
+     * String retrieved from the seinfo tag found in selinux policy. This value can be set through
+     * the mac_permissions.xml policy construct. This value is used for setting an SELinux security
+     * context on the process as well as its data directory.
      *
      * {@hide}
      */
-    public String seInfo = "default";
+    public String seInfo;
 
     /**
      * The seinfo tag generated per-user. This value may change based upon the
index f12795b..fdba99e 100644 (file)
@@ -2980,6 +2980,9 @@ public class PackageManagerService extends IPackageManager.Stub
                         }
                     }
                 }
+                // Adjust seInfo to ensure apps which share a sharedUserId are placed in the same
+                // SELinux domain.
+                setting.fixSeInfoLocked();
             }
 
             // Now that we know all the packages we are keeping,
@@ -10376,20 +10379,24 @@ public class PackageManagerService extends IPackageManager.Stub
             pkg.applicationInfo.flags |= ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
         }
 
-        // SELinux sandboxes become more restrictive as targetSdkVersion increases.
-        // To ensure that apps with sharedUserId are placed in the same selinux domain
-        // without breaking any assumptions about access, put them into the least
-        // restrictive targetSdkVersion=25 domain.
-        // TODO(b/72290969): Base this on the actual targetSdkVersion(s) of the apps within the
-        // sharedUserSetting, instead of defaulting to the least restrictive domain.
-        final int targetSdk = (sharedUserSetting != null) ? 25
-                : pkg.applicationInfo.targetSdkVersion;
+        // Apps which share a sharedUserId must be placed in the same selinux domain. If this
+        // package is the first app installed as this shared user, set seInfoTargetSdkVersion to its
+        // targetSdkVersion. These are later adjusted in PackageManagerService's constructor to be
+        // the lowest targetSdkVersion of all apps within the shared user, which corresponds to the
+        // least restrictive selinux domain.
+        // NOTE: As new packages are installed / updated, the shared user's seinfoTargetSdkVersion
+        // will NOT be modified until next boot, even if a lower targetSdkVersion is used. This
+        // ensures that all packages continue to run in the same selinux domain.
+        final int targetSdkVersion =
+            ((sharedUserSetting != null) && (sharedUserSetting.packages.size() != 0)) ?
+            sharedUserSetting.seInfoTargetSdkVersion : pkg.applicationInfo.targetSdkVersion;
         // TODO(b/71593002): isPrivileged for sharedUser and appInfo should never be out of sync.
         // They currently can be if the sharedUser apps are signed with the platform key.
         final boolean isPrivileged = (sharedUserSetting != null) ?
             sharedUserSetting.isPrivileged() | pkg.isPrivileged() : pkg.isPrivileged();
 
-        SELinuxMMAC.assignSeInfoValue(pkg, isPrivileged, targetSdk);
+        pkg.applicationInfo.seInfo = SELinuxMMAC.getSeInfo(pkg, isPrivileged,
+                pkg.applicationInfo.targetSandboxVersion, targetSdkVersion);
 
         pkg.mExtras = pkgSetting;
         pkg.applicationInfo.processName = fixProcessName(
index a9f1528..b47d966 100644 (file)
@@ -64,6 +64,8 @@ public final class SELinuxMMAC {
     /** Required MAC permissions files */
     private static List<File> sMacPermissions = new ArrayList<>();
 
+    private static final String DEFAULT_SEINFO = "default";
+
     // Append privapp to existing seinfo label
     private static final String PRIVILEGED_APP_STR = ":privapp";
 
@@ -307,45 +309,56 @@ public final class SELinuxMMAC {
     }
 
     /**
-     * Applies a security label to a package based on an seinfo tag taken from a matched
-     * policy. All signature based policy stanzas are consulted and, if no match is
-     * found, the default seinfo label of 'default' (set in ApplicationInfo object) is
-     * used. The security label is attached to the ApplicationInfo instance of the package
-     * in the event that a matching policy was found.
+     * Selects a security label to a package based on input parameters and the seinfo tag taken
+     * from a matched policy. All signature based policy stanzas are consulted and, if no match
+     * is found, the default seinfo label of 'default' is used. The security label is attached to
+     * the ApplicationInfo instance of the package.
      *
      * @param pkg object representing the package to be labeled.
+     * @param isPrivileged boolean.
+     * @param targetSandboxVersion int.
+     * @param targetSdkVersion int. If this pkg runs as a sharedUser, targetSdkVersion is the
+     *        greater of: lowest targetSdk for all pkgs in the sharedUser, or
+     *        MINIMUM_TARGETSDKVERSION.
+     * @return String representing the resulting seinfo.
      */
-    public static void assignSeInfoValue(PackageParser.Package pkg, boolean isPrivileged,
-            int targetSdkVersion) {
+    public static String getSeInfo(PackageParser.Package pkg, boolean isPrivileged,
+            int targetSandboxVersion, int targetSdkVersion) {
+        String seInfo = null;
         synchronized (sPolicies) {
             if (!sPolicyRead) {
                 if (DEBUG_POLICY) {
                     Slog.d(TAG, "Policy not read");
                 }
-                return;
-            }
-            for (Policy policy : sPolicies) {
-                String seInfo = policy.getMatchedSeInfo(pkg);
-                if (seInfo != null) {
-                    pkg.applicationInfo.seInfo = seInfo;
-                    break;
+            } else {
+                for (Policy policy : sPolicies) {
+                    seInfo = policy.getMatchedSeInfo(pkg);
+                    if (seInfo != null) {
+                        break;
+                    }
                 }
             }
         }
 
-        if (pkg.applicationInfo.targetSandboxVersion == 2)
-            pkg.applicationInfo.seInfo += SANDBOX_V2_STR;
+        if (seInfo == null) {
+            seInfo = DEFAULT_SEINFO;
+        }
+
+        if (targetSandboxVersion == 2) {
+            seInfo += SANDBOX_V2_STR;
+        }
 
         if (isPrivileged) {
-            pkg.applicationInfo.seInfo += PRIVILEGED_APP_STR;
+            seInfo += PRIVILEGED_APP_STR;
         }
 
-        pkg.applicationInfo.seInfo += TARGETSDKVERSION_STR + targetSdkVersion;
+        seInfo += TARGETSDKVERSION_STR + targetSdkVersion;
 
         if (DEBUG_POLICY_INSTALL) {
             Slog.i(TAG, "package (" + pkg.packageName + ") labeled with " +
-                    "seinfo=" + pkg.applicationInfo.seInfo);
+                    "seinfo=" + seInfo);
         }
+        return seInfo;
     }
 }
 
index 2446131..1d9afd9 100644 (file)
@@ -39,6 +39,10 @@ public final class SharedUserSetting extends SettingBase {
     int uidFlags;
     int uidPrivateFlags;
 
+    // The lowest targetSdkVersion of all apps in the sharedUserSetting, used to assign seinfo so
+    // that all apps within the sharedUser run in the same selinux context.
+    int seInfoTargetSdkVersion;
+
     final ArraySet<PackageSetting> packages = new ArraySet<PackageSetting>();
 
     final PackageSignatures signatures = new PackageSignatures();
@@ -84,6 +88,11 @@ public final class SharedUserSetting extends SettingBase {
     }
 
     void addPackage(PackageSetting packageSetting) {
+        // If this is the first package added to this shared user, temporarily (until next boot) use
+        // its targetSdkVersion when assigning seInfo for the shared user.
+        if ((packages.size() == 0) && (packageSetting.pkg != null)) {
+            seInfoTargetSdkVersion = packageSetting.pkg.applicationInfo.targetSdkVersion;
+        }
         if (packages.add(packageSetting)) {
             setFlags(this.pkgFlags | packageSetting.pkgFlags);
             setPrivateFlags(this.pkgPrivateFlags | packageSetting.pkgPrivateFlags);
@@ -107,4 +116,26 @@ public final class SharedUserSetting extends SettingBase {
     public boolean isPrivileged() {
         return (this.pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
     }
+
+    /**
+     * Determine the targetSdkVersion for a sharedUser and update pkg.applicationInfo.seInfo
+     * to ensure that all apps within the sharedUser share an SELinux domain. Use the lowest
+     * targetSdkVersion of all apps within the shared user, which corresponds to the least
+     * restrictive selinux domain.
+     */
+    public void fixSeInfoLocked() {
+        final List<PackageParser.Package> pkgList = getPackages();
+
+        for (PackageParser.Package pkg : pkgList) {
+            if (pkg.applicationInfo.targetSdkVersion < seInfoTargetSdkVersion) {
+                seInfoTargetSdkVersion = pkg.applicationInfo.targetSdkVersion;
+            }
+        }
+        for (PackageParser.Package pkg : pkgList) {
+            final boolean isPrivileged = isPrivileged() | pkg.isPrivileged();
+            pkg.applicationInfo.seInfo = SELinuxMMAC.getSeInfo(pkg, isPrivileged,
+                pkg.applicationInfo.targetSandboxVersion, seInfoTargetSdkVersion);
+        }
+    }
+
 }