1cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root/*
2cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * Copyright (C) 2011 The Android Open Source Project
3cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root *
4cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * Licensed under the Apache License, Version 2.0 (the "License");
5cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * you may not use this file except in compliance with the License.
6cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * You may obtain a copy of the License at
7cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root *
8cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root *      http://www.apache.org/licenses/LICENSE-2.0
9cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root *
10cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * Unless required by applicable law or agreed to in writing, software
11cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * distributed under the License is distributed on an "AS IS" BASIS,
12cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * See the License for the specific language governing permissions and
14cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * limitations under the License.
15cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root */
16cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
17cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Rootpackage com.android.server.pm;
18cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
190eb9738d1708d9aa7846782046e6828ffc9fe901Todd Kennedyimport android.annotation.Nullable;
20d1cf49904ba79c70446f27b51e3d736bb1324009Jeff Vander Stoepimport android.content.pm.ApplicationInfo;
210eb9738d1708d9aa7846782046e6828ffc9fe901Todd Kennedyimport android.content.pm.PackageParser;
22d6759d46f96fe2c8955751b0fe8037d6c8a75464Yi Jinimport android.service.pm.PackageServiceDumpProto;
239f837a99d48c5bb8ad7fbc133943e5bf622ce065Jeff Sharkeyimport android.util.ArraySet;
24d6759d46f96fe2c8955751b0fe8037d6c8a75464Yi Jinimport android.util.proto.ProtoOutputStream;
25cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
260eb9738d1708d9aa7846782046e6828ffc9fe901Todd Kennedyimport java.util.ArrayList;
270eb9738d1708d9aa7846782046e6828ffc9fe901Todd Kennedyimport java.util.Collection;
280eb9738d1708d9aa7846782046e6828ffc9fe901Todd Kennedyimport java.util.List;
290eb9738d1708d9aa7846782046e6828ffc9fe901Todd Kennedy
30cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root/**
31cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root * Settings data for a particular shared user ID we know about.
32cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root */
330eb9738d1708d9aa7846782046e6828ffc9fe901Todd Kennedypublic final class SharedUserSetting extends SettingBase {
34cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    final String name;
35cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
36cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    int userId;
37cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
38dd72c9ed558158f889a8cdfed8a108553ba5a562Ben Gruver    // flags that are associated with this uid, regardless of any package flags
39dd72c9ed558158f889a8cdfed8a108553ba5a562Ben Gruver    int uidFlags;
40b9f8a5204a1b0b3919fa921e858d04124c582828Alex Klyubin    int uidPrivateFlags;
41dd72c9ed558158f889a8cdfed8a108553ba5a562Ben Gruver
42cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep    // The lowest targetSdkVersion of all apps in the sharedUserSetting, used to assign seinfo so
43cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep    // that all apps within the sharedUser run in the same selinux context.
44cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep    int seInfoTargetSdkVersion;
45cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep
469f837a99d48c5bb8ad7fbc133943e5bf622ce065Jeff Sharkey    final ArraySet<PackageSetting> packages = new ArraySet<PackageSetting>();
47cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
48cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    final PackageSignatures signatures = new PackageSignatures();
49ad8a0da6a7b92e244953460068aebd4b40a5614eBryan Henry    Boolean signaturesChanged;
50cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
51b9f8a5204a1b0b3919fa921e858d04124c582828Alex Klyubin    SharedUserSetting(String _name, int _pkgFlags, int _pkgPrivateFlags) {
52b9f8a5204a1b0b3919fa921e858d04124c582828Alex Klyubin        super(_pkgFlags, _pkgPrivateFlags);
53dd72c9ed558158f889a8cdfed8a108553ba5a562Ben Gruver        uidFlags =  _pkgFlags;
54b9f8a5204a1b0b3919fa921e858d04124c582828Alex Klyubin        uidPrivateFlags = _pkgPrivateFlags;
55cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        name = _name;
56dfd822be8fff9aeb6bd0c2098708a79380fc0729Joel Galenson        seInfoTargetSdkVersion = android.os.Build.VERSION_CODES.CUR_DEVELOPMENT;
57cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    }
58cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root
59cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    @Override
60cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    public String toString() {
61cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root        return "SharedUserSetting{" + Integer.toHexString(System.identityHashCode(this)) + " "
62cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root                + name + "/" + userId + "}";
63cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root    }
64dd72c9ed558158f889a8cdfed8a108553ba5a562Ben Gruver
65d6759d46f96fe2c8955751b0fe8037d6c8a75464Yi Jin    public void writeToProto(ProtoOutputStream proto, long fieldId) {
66d6759d46f96fe2c8955751b0fe8037d6c8a75464Yi Jin        long token = proto.start(fieldId);
67d6759d46f96fe2c8955751b0fe8037d6c8a75464Yi Jin        proto.write(PackageServiceDumpProto.SharedUserProto.USER_ID, userId);
68d6759d46f96fe2c8955751b0fe8037d6c8a75464Yi Jin        proto.write(PackageServiceDumpProto.SharedUserProto.NAME, name);
69d6759d46f96fe2c8955751b0fe8037d6c8a75464Yi Jin        proto.end(token);
70d6759d46f96fe2c8955751b0fe8037d6c8a75464Yi Jin    }
71d6759d46f96fe2c8955751b0fe8037d6c8a75464Yi Jin
72dd72c9ed558158f889a8cdfed8a108553ba5a562Ben Gruver    void removePackage(PackageSetting packageSetting) {
73dd72c9ed558158f889a8cdfed8a108553ba5a562Ben Gruver        if (packages.remove(packageSetting)) {
74dd72c9ed558158f889a8cdfed8a108553ba5a562Ben Gruver            // recalculate the pkgFlags for this shared user if needed
75dd72c9ed558158f889a8cdfed8a108553ba5a562Ben Gruver            if ((this.pkgFlags & packageSetting.pkgFlags) != 0) {
76dd72c9ed558158f889a8cdfed8a108553ba5a562Ben Gruver                int aggregatedFlags = uidFlags;
77dd72c9ed558158f889a8cdfed8a108553ba5a562Ben Gruver                for (PackageSetting ps : packages) {
78dd72c9ed558158f889a8cdfed8a108553ba5a562Ben Gruver                    aggregatedFlags |= ps.pkgFlags;
79dd72c9ed558158f889a8cdfed8a108553ba5a562Ben Gruver                }
80dd72c9ed558158f889a8cdfed8a108553ba5a562Ben Gruver                setFlags(aggregatedFlags);
81dd72c9ed558158f889a8cdfed8a108553ba5a562Ben Gruver            }
82b9f8a5204a1b0b3919fa921e858d04124c582828Alex Klyubin            if ((this.pkgPrivateFlags & packageSetting.pkgPrivateFlags) != 0) {
83b9f8a5204a1b0b3919fa921e858d04124c582828Alex Klyubin                int aggregatedPrivateFlags = uidPrivateFlags;
84b9f8a5204a1b0b3919fa921e858d04124c582828Alex Klyubin                for (PackageSetting ps : packages) {
85b9f8a5204a1b0b3919fa921e858d04124c582828Alex Klyubin                    aggregatedPrivateFlags |= ps.pkgPrivateFlags;
86b9f8a5204a1b0b3919fa921e858d04124c582828Alex Klyubin                }
87b9f8a5204a1b0b3919fa921e858d04124c582828Alex Klyubin                setPrivateFlags(aggregatedPrivateFlags);
88b9f8a5204a1b0b3919fa921e858d04124c582828Alex Klyubin            }
89dd72c9ed558158f889a8cdfed8a108553ba5a562Ben Gruver        }
90dd72c9ed558158f889a8cdfed8a108553ba5a562Ben Gruver    }
91dd72c9ed558158f889a8cdfed8a108553ba5a562Ben Gruver
92dd72c9ed558158f889a8cdfed8a108553ba5a562Ben Gruver    void addPackage(PackageSetting packageSetting) {
93cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep        // If this is the first package added to this shared user, temporarily (until next boot) use
94cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep        // its targetSdkVersion when assigning seInfo for the shared user.
95cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep        if ((packages.size() == 0) && (packageSetting.pkg != null)) {
96cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep            seInfoTargetSdkVersion = packageSetting.pkg.applicationInfo.targetSdkVersion;
97cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep        }
98dd72c9ed558158f889a8cdfed8a108553ba5a562Ben Gruver        if (packages.add(packageSetting)) {
99dd72c9ed558158f889a8cdfed8a108553ba5a562Ben Gruver            setFlags(this.pkgFlags | packageSetting.pkgFlags);
100b9f8a5204a1b0b3919fa921e858d04124c582828Alex Klyubin            setPrivateFlags(this.pkgPrivateFlags | packageSetting.pkgPrivateFlags);
101dd72c9ed558158f889a8cdfed8a108553ba5a562Ben Gruver        }
102dd72c9ed558158f889a8cdfed8a108553ba5a562Ben Gruver    }
1030eb9738d1708d9aa7846782046e6828ffc9fe901Todd Kennedy
1040eb9738d1708d9aa7846782046e6828ffc9fe901Todd Kennedy    public @Nullable List<PackageParser.Package> getPackages() {
1050eb9738d1708d9aa7846782046e6828ffc9fe901Todd Kennedy        if (packages == null || packages.size() == 0) {
1060eb9738d1708d9aa7846782046e6828ffc9fe901Todd Kennedy            return null;
1070eb9738d1708d9aa7846782046e6828ffc9fe901Todd Kennedy        }
1080eb9738d1708d9aa7846782046e6828ffc9fe901Todd Kennedy        final ArrayList<PackageParser.Package> pkgList = new ArrayList<>(packages.size());
1090eb9738d1708d9aa7846782046e6828ffc9fe901Todd Kennedy        for (PackageSetting ps : packages) {
1100a4c63f958d133f15398900a26668d1e2661f783Jeff Vander Stoep            if ((ps == null) || (ps.pkg == null)) {
1110eb9738d1708d9aa7846782046e6828ffc9fe901Todd Kennedy                continue;
1120eb9738d1708d9aa7846782046e6828ffc9fe901Todd Kennedy            }
1130eb9738d1708d9aa7846782046e6828ffc9fe901Todd Kennedy            pkgList.add(ps.pkg);
1140eb9738d1708d9aa7846782046e6828ffc9fe901Todd Kennedy        }
1150eb9738d1708d9aa7846782046e6828ffc9fe901Todd Kennedy        return pkgList;
1160eb9738d1708d9aa7846782046e6828ffc9fe901Todd Kennedy    }
117d1cf49904ba79c70446f27b51e3d736bb1324009Jeff Vander Stoep
118d1cf49904ba79c70446f27b51e3d736bb1324009Jeff Vander Stoep    public boolean isPrivileged() {
119d1cf49904ba79c70446f27b51e3d736bb1324009Jeff Vander Stoep        return (this.pkgPrivateFlags & ApplicationInfo.PRIVATE_FLAG_PRIVILEGED) != 0;
120d1cf49904ba79c70446f27b51e3d736bb1324009Jeff Vander Stoep    }
121cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep
122cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep    /**
123cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep     * Determine the targetSdkVersion for a sharedUser and update pkg.applicationInfo.seInfo
124cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep     * to ensure that all apps within the sharedUser share an SELinux domain. Use the lowest
125cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep     * targetSdkVersion of all apps within the shared user, which corresponds to the least
126cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep     * restrictive selinux domain.
127cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep     */
128cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep    public void fixSeInfoLocked() {
129cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep        final List<PackageParser.Package> pkgList = getPackages();
13054807bb15b1a853ce09bf2ffce4f84f36cc37245Jeff Vander Stoep        if (pkgList == null || pkgList.size() == 0) {
13154807bb15b1a853ce09bf2ffce4f84f36cc37245Jeff Vander Stoep            return;
13254807bb15b1a853ce09bf2ffce4f84f36cc37245Jeff Vander Stoep        }
133cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep
134cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep        for (PackageParser.Package pkg : pkgList) {
135cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep            if (pkg.applicationInfo.targetSdkVersion < seInfoTargetSdkVersion) {
136cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep                seInfoTargetSdkVersion = pkg.applicationInfo.targetSdkVersion;
137cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep            }
138cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep        }
139cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep        for (PackageParser.Package pkg : pkgList) {
140cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep            final boolean isPrivileged = isPrivileged() | pkg.isPrivileged();
141cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep            pkg.applicationInfo.seInfo = SELinuxMMAC.getSeInfo(pkg, isPrivileged,
142cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep                pkg.applicationInfo.targetSandboxVersion, seInfoTargetSdkVersion);
143cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep        }
144cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep    }
145cab3639dcb609b70012744029508f7b19e09c24dJeff Vander Stoep
146cf0b38ca6e5aa5efded7dbdbb623f6cd2746c96aKenny Root}
147