Kenny Root | cf0b38c | 2011-03-22 14:17:59 -0700 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2011 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | package com.android.server.pm; |
| 18 | |
Todd Kennedy | 0eb9738 | 2017-10-03 16:57:22 -0700 | [diff] [blame] | 19 | import android.annotation.Nullable; |
Jeff Vander Stoep | d1cf499 | 2018-01-11 16:09:58 -0800 | [diff] [blame] | 20 | import android.content.pm.ApplicationInfo; |
Todd Kennedy | 0eb9738 | 2017-10-03 16:57:22 -0700 | [diff] [blame] | 21 | import android.content.pm.PackageParser; |
Sudheer Shanka | d68bd60 | 2018-11-13 17:43:39 -0800 | [diff] [blame] | 22 | import android.os.storage.StorageManager; |
Yi Jin | d6759d4 | 2017-10-12 15:08:49 -0700 | [diff] [blame] | 23 | import android.service.pm.PackageServiceDumpProto; |
Jeff Sharkey | 9f837a9 | 2014-10-24 12:07:24 -0700 | [diff] [blame] | 24 | import android.util.ArraySet; |
Yi Jin | d6759d4 | 2017-10-12 15:08:49 -0700 | [diff] [blame] | 25 | import android.util.proto.ProtoOutputStream; |
Kenny Root | cf0b38c | 2011-03-22 14:17:59 -0700 | [diff] [blame] | 26 | |
Sudheer Shanka | 12783cb | 2018-10-18 08:53:02 -0700 | [diff] [blame] | 27 | import com.android.internal.util.ArrayUtils; |
| 28 | |
| 29 | import libcore.util.EmptyArray; |
| 30 | |
Todd Kennedy | 0eb9738 | 2017-10-03 16:57:22 -0700 | [diff] [blame] | 31 | import java.util.ArrayList; |
Todd Kennedy | 0eb9738 | 2017-10-03 16:57:22 -0700 | [diff] [blame] | 32 | import java.util.List; |
| 33 | |
Kenny Root | cf0b38c | 2011-03-22 14:17:59 -0700 | [diff] [blame] | 34 | /** |
| 35 | * Settings data for a particular shared user ID we know about. |
| 36 | */ |
Todd Kennedy | 0eb9738 | 2017-10-03 16:57:22 -0700 | [diff] [blame] | 37 | public final class SharedUserSetting extends SettingBase { |
Kenny Root | cf0b38c | 2011-03-22 14:17:59 -0700 | [diff] [blame] | 38 | final String name; |
| 39 | |
| 40 | int userId; |
| 41 | |
Ben Gruver | dd72c9e | 2013-08-06 12:34:17 -0700 | [diff] [blame] | 42 | // flags that are associated with this uid, regardless of any package flags |
| 43 | int uidFlags; |
Alex Klyubin | b9f8a52 | 2015-02-03 11:12:59 -0800 | [diff] [blame] | 44 | int uidPrivateFlags; |
Ben Gruver | dd72c9e | 2013-08-06 12:34:17 -0700 | [diff] [blame] | 45 | |
Jeff Vander Stoep | cab3639 | 2018-03-06 15:52:22 -0800 | [diff] [blame] | 46 | // The lowest targetSdkVersion of all apps in the sharedUserSetting, used to assign seinfo so |
| 47 | // that all apps within the sharedUser run in the same selinux context. |
| 48 | int seInfoTargetSdkVersion; |
| 49 | |
Jeff Sharkey | 9f837a9 | 2014-10-24 12:07:24 -0700 | [diff] [blame] | 50 | final ArraySet<PackageSetting> packages = new ArraySet<PackageSetting>(); |
Kenny Root | cf0b38c | 2011-03-22 14:17:59 -0700 | [diff] [blame] | 51 | |
| 52 | final PackageSignatures signatures = new PackageSignatures(); |
Bryan Henry | ad8a0da | 2018-05-06 13:36:17 -0700 | [diff] [blame] | 53 | Boolean signaturesChanged; |
Kenny Root | cf0b38c | 2011-03-22 14:17:59 -0700 | [diff] [blame] | 54 | |
Alex Klyubin | b9f8a52 | 2015-02-03 11:12:59 -0800 | [diff] [blame] | 55 | SharedUserSetting(String _name, int _pkgFlags, int _pkgPrivateFlags) { |
| 56 | super(_pkgFlags, _pkgPrivateFlags); |
Ben Gruver | dd72c9e | 2013-08-06 12:34:17 -0700 | [diff] [blame] | 57 | uidFlags = _pkgFlags; |
Alex Klyubin | b9f8a52 | 2015-02-03 11:12:59 -0800 | [diff] [blame] | 58 | uidPrivateFlags = _pkgPrivateFlags; |
Kenny Root | cf0b38c | 2011-03-22 14:17:59 -0700 | [diff] [blame] | 59 | name = _name; |
Joel Galenson | dfd822b | 2018-04-03 10:46:24 -0700 | [diff] [blame] | 60 | seInfoTargetSdkVersion = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT; |
Kenny Root | cf0b38c | 2011-03-22 14:17:59 -0700 | [diff] [blame] | 61 | } |
| 62 | |
| 63 | @Override |
| 64 | public String toString() { |
| 65 | return "SharedUserSetting{" + Integer.toHexString(System.identityHashCode(this)) + " " |
| 66 | + name + "/" + userId + "}"; |
| 67 | } |
Ben Gruver | dd72c9e | 2013-08-06 12:34:17 -0700 | [diff] [blame] | 68 | |
Yi Jin | d6759d4 | 2017-10-12 15:08:49 -0700 | [diff] [blame] | 69 | public void writeToProto(ProtoOutputStream proto, long fieldId) { |
| 70 | long token = proto.start(fieldId); |
Kweku Adams | 87c60a0 | 2018-06-13 12:13:52 -0700 | [diff] [blame] | 71 | proto.write(PackageServiceDumpProto.SharedUserProto.UID, userId); |
Yi Jin | d6759d4 | 2017-10-12 15:08:49 -0700 | [diff] [blame] | 72 | proto.write(PackageServiceDumpProto.SharedUserProto.NAME, name); |
| 73 | proto.end(token); |
| 74 | } |
| 75 | |
Patrick | 4ccae94 | 2018-07-17 09:15:55 -0700 | [diff] [blame] | 76 | boolean removePackage(PackageSetting packageSetting) { |
| 77 | if (!packages.remove(packageSetting)) { |
| 78 | return false; |
Ben Gruver | dd72c9e | 2013-08-06 12:34:17 -0700 | [diff] [blame] | 79 | } |
Patrick | 4ccae94 | 2018-07-17 09:15:55 -0700 | [diff] [blame] | 80 | // recalculate the pkgFlags for this shared user if needed |
| 81 | if ((this.pkgFlags & packageSetting.pkgFlags) != 0) { |
| 82 | int aggregatedFlags = uidFlags; |
| 83 | for (PackageSetting ps : packages) { |
| 84 | aggregatedFlags |= ps.pkgFlags; |
| 85 | } |
| 86 | setFlags(aggregatedFlags); |
| 87 | } |
| 88 | if ((this.pkgPrivateFlags & packageSetting.pkgPrivateFlags) != 0) { |
| 89 | int aggregatedPrivateFlags = uidPrivateFlags; |
| 90 | for (PackageSetting ps : packages) { |
| 91 | aggregatedPrivateFlags |= ps.pkgPrivateFlags; |
| 92 | } |
| 93 | setPrivateFlags(aggregatedPrivateFlags); |
| 94 | } |
| 95 | return true; |
Ben Gruver | dd72c9e | 2013-08-06 12:34:17 -0700 | [diff] [blame] | 96 | } |
| 97 | |
| 98 | void addPackage(PackageSetting packageSetting) { |
Jeff Vander Stoep | cab3639 | 2018-03-06 15:52:22 -0800 | [diff] [blame] | 99 | // If this is the first package added to this shared user, temporarily (until next boot) use |
| 100 | // its targetSdkVersion when assigning seInfo for the shared user. |
| 101 | if ((packages.size() == 0) && (packageSetting.pkg != null)) { |
| 102 | seInfoTargetSdkVersion = packageSetting.pkg.applicationInfo.targetSdkVersion; |
| 103 | } |
Ben Gruver | dd72c9e | 2013-08-06 12:34:17 -0700 | [diff] [blame] | 104 | if (packages.add(packageSetting)) { |
| 105 | setFlags(this.pkgFlags | packageSetting.pkgFlags); |
Alex Klyubin | b9f8a52 | 2015-02-03 11:12:59 -0800 | [diff] [blame] | 106 | setPrivateFlags(this.pkgPrivateFlags | packageSetting.pkgPrivateFlags); |
Ben Gruver | dd72c9e | 2013-08-06 12:34:17 -0700 | [diff] [blame] | 107 | } |
| 108 | } |
Todd Kennedy | 0eb9738 | 2017-10-03 16:57:22 -0700 | [diff] [blame] | 109 | |
| 110 | public @Nullable List<PackageParser.Package> getPackages() { |
| 111 | if (packages == null || packages.size() == 0) { |
| 112 | return null; |
| 113 | } |
| 114 | final ArrayList<PackageParser.Package> pkgList = new ArrayList<>(packages.size()); |
| 115 | for (PackageSetting ps : packages) { |
Jeff Vander Stoep | 0a4c63f | 2018-03-06 13:28:29 -0800 | [diff] [blame] | 116 | if ((ps == null) || (ps.pkg == null)) { |
Todd Kennedy | 0eb9738 | 2017-10-03 16:57:22 -0700 | [diff] [blame] | 117 | continue; |
| 118 | } |
| 119 | pkgList.add(ps.pkg); |
| 120 | } |
| 121 | return pkgList; |
| 122 | } |
Jeff Vander Stoep | d1cf499 | 2018-01-11 16:09:58 -0800 | [diff] [blame] | 123 | |
| 124 | public boolean isPrivileged() { |
| 125 | return (this.pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0; |
| 126 | } |
Jeff Vander Stoep | cab3639 | 2018-03-06 15:52:22 -0800 | [diff] [blame] | 127 | |
| 128 | /** |
| 129 | * Determine the targetSdkVersion for a sharedUser and update pkg.applicationInfo.seInfo |
| 130 | * to ensure that all apps within the sharedUser share an SELinux domain. Use the lowest |
| 131 | * targetSdkVersion of all apps within the shared user, which corresponds to the least |
| 132 | * restrictive selinux domain. |
| 133 | */ |
| 134 | public void fixSeInfoLocked() { |
| 135 | final List<PackageParser.Package> pkgList = getPackages(); |
Jeff Vander Stoep | 54807bb | 2018-03-08 09:49:33 -0800 | [diff] [blame] | 136 | if (pkgList == null || pkgList.size() == 0) { |
| 137 | return; |
| 138 | } |
Jeff Vander Stoep | cab3639 | 2018-03-06 15:52:22 -0800 | [diff] [blame] | 139 | |
| 140 | for (PackageParser.Package pkg : pkgList) { |
| 141 | if (pkg.applicationInfo.targetSdkVersion < seInfoTargetSdkVersion) { |
| 142 | seInfoTargetSdkVersion = pkg.applicationInfo.targetSdkVersion; |
| 143 | } |
| 144 | } |
| 145 | for (PackageParser.Package pkg : pkgList) { |
| 146 | final boolean isPrivileged = isPrivileged() | pkg.isPrivileged(); |
| 147 | pkg.applicationInfo.seInfo = SELinuxMMAC.getSeInfo(pkg, isPrivileged, |
| 148 | pkg.applicationInfo.targetSandboxVersion, seInfoTargetSdkVersion); |
| 149 | } |
| 150 | } |
| 151 | |
Sudheer Shanka | 12783cb | 2018-10-18 08:53:02 -0700 | [diff] [blame] | 152 | /** Returns userIds which doesn't have any packages with this sharedUserId */ |
| 153 | public int[] getNotInstalledUserIds() { |
| 154 | int[] excludedUserIds = null; |
| 155 | for (PackageSetting ps : packages) { |
| 156 | final int[] userIds = ps.getNotInstalledUserIds(); |
| 157 | if (excludedUserIds == null) { |
| 158 | excludedUserIds = userIds; |
| 159 | } else { |
| 160 | for (int userId : excludedUserIds) { |
| 161 | if (!ArrayUtils.contains(userIds, userId)) { |
| 162 | excludedUserIds = ArrayUtils.removeInt(excludedUserIds, userId); |
| 163 | } |
| 164 | } |
| 165 | } |
| 166 | } |
| 167 | return excludedUserIds == null ? EmptyArray.INT : excludedUserIds; |
| 168 | } |
| 169 | |
Sudheer Shanka | d68bd60 | 2018-11-13 17:43:39 -0800 | [diff] [blame] | 170 | public String getStorageSandboxName() { |
| 171 | return StorageManager.SHARED_SANDBOX_PREFIX + name; |
Sudheer Shanka | 12783cb | 2018-10-18 08:53:02 -0700 | [diff] [blame] | 172 | } |
| 173 | |
Patrick | 4ccae94 | 2018-07-17 09:15:55 -0700 | [diff] [blame] | 174 | /** Updates all fields in this shared user setting from another. */ |
| 175 | public SharedUserSetting updateFrom(SharedUserSetting sharedUser) { |
| 176 | copyFrom(sharedUser); |
| 177 | this.userId = sharedUser.userId; |
| 178 | this.uidFlags = sharedUser.uidFlags; |
| 179 | this.uidPrivateFlags = sharedUser.uidPrivateFlags; |
| 180 | this.seInfoTargetSdkVersion = sharedUser.seInfoTargetSdkVersion; |
| 181 | this.packages.clear(); |
| 182 | this.packages.addAll(sharedUser.packages); |
| 183 | this.signaturesChanged = sharedUser.signaturesChanged; |
| 184 | return this; |
| 185 | } |
Kenny Root | cf0b38c | 2011-03-22 14:17:59 -0700 | [diff] [blame] | 186 | } |