SharedUserSetting.java revision 8196fd9380a8efe2d7fed0652b9e3b5285b02b61
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 17package com.android.server.pm; 18 19import android.annotation.Nullable; 20import android.content.pm.ApplicationInfo; 21import android.content.pm.PackageParser; 22import android.service.pm.PackageServiceDumpProto; 23import android.util.ArraySet; 24import android.util.proto.ProtoOutputStream; 25 26import java.util.ArrayList; 27import java.util.Collection; 28import java.util.List; 29 30/** 31 * Settings data for a particular shared user ID we know about. 32 */ 33public final class SharedUserSetting extends SettingBase { 34 final String name; 35 36 int userId; 37 38 // flags that are associated with this uid, regardless of any package flags 39 int uidFlags; 40 int uidPrivateFlags; 41 42 // The lowest targetSdkVersion of all apps in the sharedUserSetting, used to assign seinfo so 43 // that all apps within the sharedUser run in the same selinux context. 44 int seInfoTargetSdkVersion; 45 46 final ArraySet<PackageSetting> packages = new ArraySet<PackageSetting>(); 47 48 final PackageSignatures signatures = new PackageSignatures(); 49 50 SharedUserSetting(String _name, int _pkgFlags, int _pkgPrivateFlags) { 51 super(_pkgFlags, _pkgPrivateFlags); 52 uidFlags = _pkgFlags; 53 uidPrivateFlags = _pkgPrivateFlags; 54 name = _name; 55 } 56 57 @Override 58 public String toString() { 59 return "SharedUserSetting{" + Integer.toHexString(System.identityHashCode(this)) + " " 60 + name + "/" + userId + "}"; 61 } 62 63 public void writeToProto(ProtoOutputStream proto, long fieldId) { 64 long token = proto.start(fieldId); 65 proto.write(PackageServiceDumpProto.SharedUserProto.USER_ID, userId); 66 proto.write(PackageServiceDumpProto.SharedUserProto.NAME, name); 67 proto.end(token); 68 } 69 70 void removePackage(PackageSetting packageSetting) { 71 if (packages.remove(packageSetting)) { 72 // recalculate the pkgFlags for this shared user if needed 73 if ((this.pkgFlags & packageSetting.pkgFlags) != 0) { 74 int aggregatedFlags = uidFlags; 75 for (PackageSetting ps : packages) { 76 aggregatedFlags |= ps.pkgFlags; 77 } 78 setFlags(aggregatedFlags); 79 } 80 if ((this.pkgPrivateFlags & packageSetting.pkgPrivateFlags) != 0) { 81 int aggregatedPrivateFlags = uidPrivateFlags; 82 for (PackageSetting ps : packages) { 83 aggregatedPrivateFlags |= ps.pkgPrivateFlags; 84 } 85 setPrivateFlags(aggregatedPrivateFlags); 86 } 87 } 88 } 89 90 void addPackage(PackageSetting packageSetting) { 91 // If this is the first package added to this shared user, temporarily (until next boot) use 92 // its targetSdkVersion when assigning seInfo for the shared user. 93 if ((packages.size() == 0) && (packageSetting.pkg != null)) { 94 seInfoTargetSdkVersion = packageSetting.pkg.applicationInfo.targetSdkVersion; 95 } 96 if (packages.add(packageSetting)) { 97 setFlags(this.pkgFlags | packageSetting.pkgFlags); 98 setPrivateFlags(this.pkgPrivateFlags | packageSetting.pkgPrivateFlags); 99 } 100 } 101 102 public @Nullable List<PackageParser.Package> getPackages() { 103 if (packages == null || packages.size() == 0) { 104 return null; 105 } 106 final ArrayList<PackageParser.Package> pkgList = new ArrayList<>(packages.size()); 107 for (PackageSetting ps : packages) { 108 if (ps == null) { 109 continue; 110 } 111 pkgList.add(ps.pkg); 112 } 113 return pkgList; 114 } 115 116 public boolean isPrivileged() { 117 return (this.pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0; 118 } 119 120 /** 121 * Determine the targetSdkVersion for a sharedUser and update pkg.applicationInfo.seInfo 122 * to ensure that all apps within the sharedUser share an SELinux domain. Use the lowest 123 * targetSdkVersion of all apps within the shared user, which corresponds to the least 124 * restrictive selinux domain. 125 */ 126 public void fixSeInfoLocked() { 127 final List<PackageParser.Package> pkgList = getPackages(); 128 129 for (PackageParser.Package pkg : pkgList) { 130 if (pkg.applicationInfo.targetSdkVersion < seInfoTargetSdkVersion) { 131 seInfoTargetSdkVersion = pkg.applicationInfo.targetSdkVersion; 132 } 133 } 134 for (PackageParser.Package pkg : pkgList) { 135 final boolean isPrivileged = isPrivileged() | pkg.isPrivileged(); 136 pkg.applicationInfo.seInfo = SELinuxMMAC.getSeInfo(pkg, isPrivileged, 137 pkg.applicationInfo.targetSandboxVersion, seInfoTargetSdkVersion); 138 } 139 } 140 141} 142