1d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig/*
2d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig * Copyright (C) 2012 The Android Open Source Project
3d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig *
4d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig * Licensed under the Apache License, Version 2.0 (the "License");
5d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig * you may not use this file except in compliance with the License.
6d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig * You may obtain a copy of the License at
7d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig *
8d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig *      http://www.apache.org/licenses/LICENSE-2.0
9d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig *
10d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig * Unless required by applicable law or agreed to in writing, software
11d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig * distributed under the License is distributed on an "AS IS" BASIS,
12d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig * See the License for the specific language governing permissions and
14d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig * limitations under the License.
15d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig */
16d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
17d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craigpackage com.android.server.pm;
18d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
19d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craigimport android.content.pm.ApplicationInfo;
20d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craigimport android.content.pm.PackageParser;
21d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craigimport android.content.pm.Signature;
22d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craigimport android.os.Environment;
23d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craigimport android.util.Slog;
24d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craigimport android.util.Xml;
25d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
26d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craigimport com.android.internal.util.XmlUtils;
27d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
284385343fd82058c397a46530458ae58999f75639Robert Craigimport libcore.io.IoUtils;
294385343fd82058c397a46530458ae58999f75639Robert Craig
30d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craigimport java.io.File;
31d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craigimport java.io.FileNotFoundException;
324385343fd82058c397a46530458ae58999f75639Robert Craigimport java.io.FileOutputStream;
33d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craigimport java.io.FileReader;
34d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craigimport java.io.IOException;
354385343fd82058c397a46530458ae58999f75639Robert Craigimport java.security.MessageDigest;
364385343fd82058c397a46530458ae58999f75639Robert Craigimport java.security.NoSuchAlgorithmException;
37d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
38d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craigimport java.util.HashMap;
39d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
40d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craigimport org.xmlpull.v1.XmlPullParser;
41d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craigimport org.xmlpull.v1.XmlPullParserException;
42d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
43d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig/**
44d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig * Centralized access to SELinux MMAC (middleware MAC) implementation.
45d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig * {@hide}
46d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig */
47d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craigpublic final class SELinuxMMAC {
48d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
49d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig    private static final String TAG = "SELinuxMMAC";
50d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
51d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig    private static final boolean DEBUG_POLICY = false;
52d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig    private static final boolean DEBUG_POLICY_INSTALL = DEBUG_POLICY || false;
53d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
54d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig    // Signature seinfo values read from policy.
55f877829d358e069a4abf413bcc356044c0232aaaRobert Craig    private static HashMap<Signature, Policy> sSigSeinfo = new HashMap<Signature, Policy>();
56d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
5799a626c2719e1965364fad543101799f527e28caRobert Craig    // Default seinfo read from policy.
5899a626c2719e1965364fad543101799f527e28caRobert Craig    private static String sDefaultSeinfo = null;
59d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
60f877829d358e069a4abf413bcc356044c0232aaaRobert Craig    // Data policy override version file.
61f877829d358e069a4abf413bcc356044c0232aaaRobert Craig    private static final String DATA_VERSION_FILE =
62f877829d358e069a4abf413bcc356044c0232aaaRobert Craig            Environment.getDataDirectory() + "/security/current/selinux_version";
63d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
64f877829d358e069a4abf413bcc356044c0232aaaRobert Craig    // Base policy version file.
65f877829d358e069a4abf413bcc356044c0232aaaRobert Craig    private static final String BASE_VERSION_FILE = "/selinux_version";
66f877829d358e069a4abf413bcc356044c0232aaaRobert Craig
67f877829d358e069a4abf413bcc356044c0232aaaRobert Craig    // Whether override security policies should be loaded.
68f877829d358e069a4abf413bcc356044c0232aaaRobert Craig    private static final boolean USE_OVERRIDE_POLICY = useOverridePolicy();
69f877829d358e069a4abf413bcc356044c0232aaaRobert Craig
70f877829d358e069a4abf413bcc356044c0232aaaRobert Craig    // Data override mac_permissions.xml policy file.
71f877829d358e069a4abf413bcc356044c0232aaaRobert Craig    private static final String DATA_MAC_PERMISSIONS =
72f877829d358e069a4abf413bcc356044c0232aaaRobert Craig            Environment.getDataDirectory() + "/security/current/mac_permissions.xml";
73f877829d358e069a4abf413bcc356044c0232aaaRobert Craig
74f877829d358e069a4abf413bcc356044c0232aaaRobert Craig    // Base mac_permissions.xml policy file.
75f877829d358e069a4abf413bcc356044c0232aaaRobert Craig    private static final String BASE_MAC_PERMISSIONS =
76f877829d358e069a4abf413bcc356044c0232aaaRobert Craig            Environment.getRootDirectory() + "/etc/security/mac_permissions.xml";
77f877829d358e069a4abf413bcc356044c0232aaaRobert Craig
78f877829d358e069a4abf413bcc356044c0232aaaRobert Craig    // Determine which mac_permissions.xml file to use.
79f877829d358e069a4abf413bcc356044c0232aaaRobert Craig    private static final String MAC_PERMISSIONS = USE_OVERRIDE_POLICY ?
80f877829d358e069a4abf413bcc356044c0232aaaRobert Craig            DATA_MAC_PERMISSIONS : BASE_MAC_PERMISSIONS;
81f877829d358e069a4abf413bcc356044c0232aaaRobert Craig
82f877829d358e069a4abf413bcc356044c0232aaaRobert Craig    // Data override seapp_contexts policy file.
83f877829d358e069a4abf413bcc356044c0232aaaRobert Craig    private static final String DATA_SEAPP_CONTEXTS =
84f877829d358e069a4abf413bcc356044c0232aaaRobert Craig            Environment.getDataDirectory() + "/security/current/seapp_contexts";
85f877829d358e069a4abf413bcc356044c0232aaaRobert Craig
86f877829d358e069a4abf413bcc356044c0232aaaRobert Craig    // Base seapp_contexts policy file.
87f877829d358e069a4abf413bcc356044c0232aaaRobert Craig    private static final String BASE_SEAPP_CONTEXTS = "/seapp_contexts";
88f877829d358e069a4abf413bcc356044c0232aaaRobert Craig
89f877829d358e069a4abf413bcc356044c0232aaaRobert Craig    // Determine which seapp_contexts file to use.
90f877829d358e069a4abf413bcc356044c0232aaaRobert Craig    private static final String SEAPP_CONTEXTS = USE_OVERRIDE_POLICY ?
91f877829d358e069a4abf413bcc356044c0232aaaRobert Craig            DATA_SEAPP_CONTEXTS : BASE_SEAPP_CONTEXTS;
924385343fd82058c397a46530458ae58999f75639Robert Craig
934385343fd82058c397a46530458ae58999f75639Robert Craig    // Stores the hash of the last used seapp_contexts file.
944385343fd82058c397a46530458ae58999f75639Robert Craig    private static final String SEAPP_HASH_FILE =
954385343fd82058c397a46530458ae58999f75639Robert Craig            Environment.getDataDirectory().toString() + "/system/seapp_hash";
964385343fd82058c397a46530458ae58999f75639Robert Craig
97f877829d358e069a4abf413bcc356044c0232aaaRobert Craig
9899a626c2719e1965364fad543101799f527e28caRobert Craig    // Signature policy stanzas
9999a626c2719e1965364fad543101799f527e28caRobert Craig    static class Policy {
10099a626c2719e1965364fad543101799f527e28caRobert Craig        private String seinfo;
10199a626c2719e1965364fad543101799f527e28caRobert Craig        private final HashMap<String, String> pkgMap;
10299a626c2719e1965364fad543101799f527e28caRobert Craig
10399a626c2719e1965364fad543101799f527e28caRobert Craig        Policy() {
10499a626c2719e1965364fad543101799f527e28caRobert Craig            seinfo = null;
10599a626c2719e1965364fad543101799f527e28caRobert Craig            pkgMap = new HashMap<String, String>();
10699a626c2719e1965364fad543101799f527e28caRobert Craig        }
10799a626c2719e1965364fad543101799f527e28caRobert Craig
10899a626c2719e1965364fad543101799f527e28caRobert Craig        void putSeinfo(String seinfoValue) {
10999a626c2719e1965364fad543101799f527e28caRobert Craig            seinfo = seinfoValue;
11099a626c2719e1965364fad543101799f527e28caRobert Craig        }
11199a626c2719e1965364fad543101799f527e28caRobert Craig
11299a626c2719e1965364fad543101799f527e28caRobert Craig        void putPkg(String pkg, String seinfoValue) {
11399a626c2719e1965364fad543101799f527e28caRobert Craig            pkgMap.put(pkg, seinfoValue);
11499a626c2719e1965364fad543101799f527e28caRobert Craig        }
11599a626c2719e1965364fad543101799f527e28caRobert Craig
11699a626c2719e1965364fad543101799f527e28caRobert Craig        // Valid policy stanza means there exists a global
11799a626c2719e1965364fad543101799f527e28caRobert Craig        // seinfo value or at least one package policy.
11899a626c2719e1965364fad543101799f527e28caRobert Craig        boolean isValid() {
11999a626c2719e1965364fad543101799f527e28caRobert Craig            return (seinfo != null) || (!pkgMap.isEmpty());
12099a626c2719e1965364fad543101799f527e28caRobert Craig        }
12199a626c2719e1965364fad543101799f527e28caRobert Craig
12299a626c2719e1965364fad543101799f527e28caRobert Craig        String checkPolicy(String pkgName) {
12399a626c2719e1965364fad543101799f527e28caRobert Craig            // Check for package name seinfo value first.
12499a626c2719e1965364fad543101799f527e28caRobert Craig            String seinfoValue = pkgMap.get(pkgName);
12599a626c2719e1965364fad543101799f527e28caRobert Craig            if (seinfoValue != null) {
12699a626c2719e1965364fad543101799f527e28caRobert Craig                return seinfoValue;
12799a626c2719e1965364fad543101799f527e28caRobert Craig            }
12899a626c2719e1965364fad543101799f527e28caRobert Craig
12999a626c2719e1965364fad543101799f527e28caRobert Craig            // Return the global seinfo value.
13099a626c2719e1965364fad543101799f527e28caRobert Craig            return seinfo;
13199a626c2719e1965364fad543101799f527e28caRobert Craig        }
13299a626c2719e1965364fad543101799f527e28caRobert Craig    }
13399a626c2719e1965364fad543101799f527e28caRobert Craig
134d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig    private static void flushInstallPolicy() {
135d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig        sSigSeinfo.clear();
13699a626c2719e1965364fad543101799f527e28caRobert Craig        sDefaultSeinfo = null;
137d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig    }
138d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
139d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig    public static boolean readInstallPolicy() {
14099a626c2719e1965364fad543101799f527e28caRobert Craig        // Temp structures to hold the rules while we parse the xml file.
14199a626c2719e1965364fad543101799f527e28caRobert Craig        // We add all the rules together once we know there's no structural problems.
14299a626c2719e1965364fad543101799f527e28caRobert Craig        HashMap<Signature, Policy> sigSeinfo = new HashMap<Signature, Policy>();
14399a626c2719e1965364fad543101799f527e28caRobert Craig        String defaultSeinfo = null;
144d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
145d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig        FileReader policyFile = null;
146d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig        try {
147f877829d358e069a4abf413bcc356044c0232aaaRobert Craig            policyFile = new FileReader(MAC_PERMISSIONS);
148f877829d358e069a4abf413bcc356044c0232aaaRobert Craig            Slog.d(TAG, "Using policy file " + MAC_PERMISSIONS);
149f877829d358e069a4abf413bcc356044c0232aaaRobert Craig
150d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig            XmlPullParser parser = Xml.newPullParser();
151d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig            parser.setInput(policyFile);
152d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
153d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig            XmlUtils.beginDocument(parser, "policy");
154d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig            while (true) {
155d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                XmlUtils.nextElement(parser);
156d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                if (parser.getEventType() == XmlPullParser.END_DOCUMENT) {
157d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                    break;
158d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                }
159d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
160d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                String tagName = parser.getName();
161d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                if ("signer".equals(tagName)) {
162d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                    String cert = parser.getAttributeValue(null, "signature");
163d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                    if (cert == null) {
164d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                        Slog.w(TAG, "<signer> without signature at "
165d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                               + parser.getPositionDescription());
166d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                        XmlUtils.skipCurrentTag(parser);
167d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                        continue;
168d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                    }
169d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                    Signature signature;
170d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                    try {
171d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                        signature = new Signature(cert);
172d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                    } catch (IllegalArgumentException e) {
173d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                        Slog.w(TAG, "<signer> with bad signature at "
174d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                               + parser.getPositionDescription(), e);
175d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                        XmlUtils.skipCurrentTag(parser);
176d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                        continue;
177d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                    }
17899a626c2719e1965364fad543101799f527e28caRobert Craig                    Policy policy = readPolicyTags(parser);
17999a626c2719e1965364fad543101799f527e28caRobert Craig                    if (policy.isValid()) {
18099a626c2719e1965364fad543101799f527e28caRobert Craig                        sigSeinfo.put(signature, policy);
181d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                    }
182d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                } else if ("default".equals(tagName)) {
18399a626c2719e1965364fad543101799f527e28caRobert Craig                    // Value is null if default tag is absent or seinfo tag is malformed.
18499a626c2719e1965364fad543101799f527e28caRobert Craig                    defaultSeinfo = readSeinfoTag(parser);
18599a626c2719e1965364fad543101799f527e28caRobert Craig                    if (DEBUG_POLICY_INSTALL)
18699a626c2719e1965364fad543101799f527e28caRobert Craig                        Slog.i(TAG, "<default> tag assigned seinfo=" + defaultSeinfo);
187d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
188d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                } else {
189d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                    XmlUtils.skipCurrentTag(parser);
190d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                }
191d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig            }
192f877829d358e069a4abf413bcc356044c0232aaaRobert Craig        } catch (XmlPullParserException xpe) {
193f877829d358e069a4abf413bcc356044c0232aaaRobert Craig            Slog.w(TAG, "Got exception parsing " + MAC_PERMISSIONS, xpe);
19499a626c2719e1965364fad543101799f527e28caRobert Craig            return false;
195f877829d358e069a4abf413bcc356044c0232aaaRobert Craig        } catch (IOException ioe) {
196f877829d358e069a4abf413bcc356044c0232aaaRobert Craig            Slog.w(TAG, "Got exception parsing " + MAC_PERMISSIONS, ioe);
19799a626c2719e1965364fad543101799f527e28caRobert Craig            return false;
19899a626c2719e1965364fad543101799f527e28caRobert Craig        } finally {
199f877829d358e069a4abf413bcc356044c0232aaaRobert Craig            IoUtils.closeQuietly(policyFile);
200d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig        }
20199a626c2719e1965364fad543101799f527e28caRobert Craig
20299a626c2719e1965364fad543101799f527e28caRobert Craig        flushInstallPolicy();
20399a626c2719e1965364fad543101799f527e28caRobert Craig        sSigSeinfo = sigSeinfo;
20499a626c2719e1965364fad543101799f527e28caRobert Craig        sDefaultSeinfo = defaultSeinfo;
20599a626c2719e1965364fad543101799f527e28caRobert Craig
206d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig        return true;
207d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig    }
208d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
20999a626c2719e1965364fad543101799f527e28caRobert Craig    private static Policy readPolicyTags(XmlPullParser parser) throws
210d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig            IOException, XmlPullParserException {
211d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
212d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig        int type;
213d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig        int outerDepth = parser.getDepth();
21499a626c2719e1965364fad543101799f527e28caRobert Craig        Policy policy = new Policy();
215d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
216d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig               && (type != XmlPullParser.END_TAG
217d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                   || parser.getDepth() > outerDepth)) {
218d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig            if (type == XmlPullParser.END_TAG
219d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                || type == XmlPullParser.TEXT) {
220d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                continue;
221d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig            }
222d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
223d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig            String tagName = parser.getName();
224d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig            if ("seinfo".equals(tagName)) {
22599a626c2719e1965364fad543101799f527e28caRobert Craig                String seinfo = parseSeinfo(parser);
22699a626c2719e1965364fad543101799f527e28caRobert Craig                if (seinfo != null) {
22799a626c2719e1965364fad543101799f527e28caRobert Craig                    policy.putSeinfo(seinfo);
22899a626c2719e1965364fad543101799f527e28caRobert Craig                }
22999a626c2719e1965364fad543101799f527e28caRobert Craig                XmlUtils.skipCurrentTag(parser);
23099a626c2719e1965364fad543101799f527e28caRobert Craig            } else if ("package".equals(tagName)) {
23199a626c2719e1965364fad543101799f527e28caRobert Craig                String pkg = parser.getAttributeValue(null, "name");
23299a626c2719e1965364fad543101799f527e28caRobert Craig                if (!validatePackageName(pkg)) {
23399a626c2719e1965364fad543101799f527e28caRobert Craig                    Slog.w(TAG, "<package> without valid name at "
234d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                           + parser.getPositionDescription());
23599a626c2719e1965364fad543101799f527e28caRobert Craig                    XmlUtils.skipCurrentTag(parser);
23699a626c2719e1965364fad543101799f527e28caRobert Craig                    continue;
23799a626c2719e1965364fad543101799f527e28caRobert Craig                }
23899a626c2719e1965364fad543101799f527e28caRobert Craig
23999a626c2719e1965364fad543101799f527e28caRobert Craig                String seinfo = readSeinfoTag(parser);
24099a626c2719e1965364fad543101799f527e28caRobert Craig                if (seinfo != null) {
24199a626c2719e1965364fad543101799f527e28caRobert Craig                    policy.putPkg(pkg, seinfo);
242d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                }
24399a626c2719e1965364fad543101799f527e28caRobert Craig            } else {
24499a626c2719e1965364fad543101799f527e28caRobert Craig                XmlUtils.skipCurrentTag(parser);
24599a626c2719e1965364fad543101799f527e28caRobert Craig            }
24699a626c2719e1965364fad543101799f527e28caRobert Craig        }
24799a626c2719e1965364fad543101799f527e28caRobert Craig        return policy;
24899a626c2719e1965364fad543101799f527e28caRobert Craig    }
24999a626c2719e1965364fad543101799f527e28caRobert Craig
25099a626c2719e1965364fad543101799f527e28caRobert Craig    private static String readSeinfoTag(XmlPullParser parser) throws
25199a626c2719e1965364fad543101799f527e28caRobert Craig            IOException, XmlPullParserException {
25299a626c2719e1965364fad543101799f527e28caRobert Craig
25399a626c2719e1965364fad543101799f527e28caRobert Craig        int type;
25499a626c2719e1965364fad543101799f527e28caRobert Craig        int outerDepth = parser.getDepth();
25599a626c2719e1965364fad543101799f527e28caRobert Craig        String seinfo = null;
25699a626c2719e1965364fad543101799f527e28caRobert Craig        while ((type=parser.next()) != XmlPullParser.END_DOCUMENT
25799a626c2719e1965364fad543101799f527e28caRobert Craig               && (type != XmlPullParser.END_TAG
25899a626c2719e1965364fad543101799f527e28caRobert Craig                   || parser.getDepth() > outerDepth)) {
25999a626c2719e1965364fad543101799f527e28caRobert Craig            if (type == XmlPullParser.END_TAG
26099a626c2719e1965364fad543101799f527e28caRobert Craig                || type == XmlPullParser.TEXT) {
26199a626c2719e1965364fad543101799f527e28caRobert Craig                continue;
26299a626c2719e1965364fad543101799f527e28caRobert Craig            }
26399a626c2719e1965364fad543101799f527e28caRobert Craig
26499a626c2719e1965364fad543101799f527e28caRobert Craig            String tagName = parser.getName();
26599a626c2719e1965364fad543101799f527e28caRobert Craig            if ("seinfo".equals(tagName)) {
26699a626c2719e1965364fad543101799f527e28caRobert Craig                seinfo = parseSeinfo(parser);
267d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig            }
268d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig            XmlUtils.skipCurrentTag(parser);
269d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig        }
270d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig        return seinfo;
271d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig    }
272d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
27399a626c2719e1965364fad543101799f527e28caRobert Craig    private static String parseSeinfo(XmlPullParser parser) {
27499a626c2719e1965364fad543101799f527e28caRobert Craig
27599a626c2719e1965364fad543101799f527e28caRobert Craig        String seinfoValue = parser.getAttributeValue(null, "value");
27699a626c2719e1965364fad543101799f527e28caRobert Craig        if (!validateValue(seinfoValue)) {
27799a626c2719e1965364fad543101799f527e28caRobert Craig            Slog.w(TAG, "<seinfo> without valid value at "
27899a626c2719e1965364fad543101799f527e28caRobert Craig                   + parser.getPositionDescription());
27999a626c2719e1965364fad543101799f527e28caRobert Craig            seinfoValue = null;
28099a626c2719e1965364fad543101799f527e28caRobert Craig        }
28199a626c2719e1965364fad543101799f527e28caRobert Craig        return seinfoValue;
28299a626c2719e1965364fad543101799f527e28caRobert Craig    }
28399a626c2719e1965364fad543101799f527e28caRobert Craig
28499a626c2719e1965364fad543101799f527e28caRobert Craig    /**
28599a626c2719e1965364fad543101799f527e28caRobert Craig     * General validation routine for package names.
28699a626c2719e1965364fad543101799f527e28caRobert Craig     * Returns a boolean indicating if the passed string
28799a626c2719e1965364fad543101799f527e28caRobert Craig     * is a valid android package name.
28899a626c2719e1965364fad543101799f527e28caRobert Craig     */
28999a626c2719e1965364fad543101799f527e28caRobert Craig    private static boolean validatePackageName(String name) {
29099a626c2719e1965364fad543101799f527e28caRobert Craig        if (name == null)
29199a626c2719e1965364fad543101799f527e28caRobert Craig            return false;
29299a626c2719e1965364fad543101799f527e28caRobert Craig
29399a626c2719e1965364fad543101799f527e28caRobert Craig        final int N = name.length();
29499a626c2719e1965364fad543101799f527e28caRobert Craig        boolean hasSep = false;
29599a626c2719e1965364fad543101799f527e28caRobert Craig        boolean front = true;
29699a626c2719e1965364fad543101799f527e28caRobert Craig        for (int i=0; i<N; i++) {
29799a626c2719e1965364fad543101799f527e28caRobert Craig            final char c = name.charAt(i);
29899a626c2719e1965364fad543101799f527e28caRobert Craig            if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
29999a626c2719e1965364fad543101799f527e28caRobert Craig                front = false;
30099a626c2719e1965364fad543101799f527e28caRobert Craig                continue;
30199a626c2719e1965364fad543101799f527e28caRobert Craig            }
30299a626c2719e1965364fad543101799f527e28caRobert Craig            if (!front) {
30399a626c2719e1965364fad543101799f527e28caRobert Craig                if ((c >= '0' && c <= '9') || c == '_') {
30499a626c2719e1965364fad543101799f527e28caRobert Craig                    continue;
30599a626c2719e1965364fad543101799f527e28caRobert Craig                }
30699a626c2719e1965364fad543101799f527e28caRobert Craig            }
30799a626c2719e1965364fad543101799f527e28caRobert Craig            if (c == '.') {
30899a626c2719e1965364fad543101799f527e28caRobert Craig                hasSep = true;
30999a626c2719e1965364fad543101799f527e28caRobert Craig                front = true;
31099a626c2719e1965364fad543101799f527e28caRobert Craig                continue;
31199a626c2719e1965364fad543101799f527e28caRobert Craig            }
31299a626c2719e1965364fad543101799f527e28caRobert Craig            return false;
31399a626c2719e1965364fad543101799f527e28caRobert Craig        }
31499a626c2719e1965364fad543101799f527e28caRobert Craig        return hasSep;
31599a626c2719e1965364fad543101799f527e28caRobert Craig    }
31699a626c2719e1965364fad543101799f527e28caRobert Craig
317d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig    /**
318d417ab0ea526cee036a71e67af4a8a898e35f564Robert Craig     * General validation routine for tag values.
319d417ab0ea526cee036a71e67af4a8a898e35f564Robert Craig     * Returns a boolean indicating if the passed string
320d417ab0ea526cee036a71e67af4a8a898e35f564Robert Craig     * contains only letters or underscores.
321d417ab0ea526cee036a71e67af4a8a898e35f564Robert Craig     */
322d417ab0ea526cee036a71e67af4a8a898e35f564Robert Craig    private static boolean validateValue(String name) {
323d417ab0ea526cee036a71e67af4a8a898e35f564Robert Craig        if (name == null)
324d417ab0ea526cee036a71e67af4a8a898e35f564Robert Craig            return false;
325d417ab0ea526cee036a71e67af4a8a898e35f564Robert Craig
326d417ab0ea526cee036a71e67af4a8a898e35f564Robert Craig        final int N = name.length();
327d417ab0ea526cee036a71e67af4a8a898e35f564Robert Craig        if (N == 0)
328d417ab0ea526cee036a71e67af4a8a898e35f564Robert Craig            return false;
329d417ab0ea526cee036a71e67af4a8a898e35f564Robert Craig
330d417ab0ea526cee036a71e67af4a8a898e35f564Robert Craig        for (int i = 0; i < N; i++) {
331d417ab0ea526cee036a71e67af4a8a898e35f564Robert Craig            final char c = name.charAt(i);
332d417ab0ea526cee036a71e67af4a8a898e35f564Robert Craig            if ((c < 'a' || c > 'z') && (c < 'A' || c > 'Z') && (c != '_')) {
333d417ab0ea526cee036a71e67af4a8a898e35f564Robert Craig                return false;
334d417ab0ea526cee036a71e67af4a8a898e35f564Robert Craig            }
335d417ab0ea526cee036a71e67af4a8a898e35f564Robert Craig        }
336d417ab0ea526cee036a71e67af4a8a898e35f564Robert Craig        return true;
337d417ab0ea526cee036a71e67af4a8a898e35f564Robert Craig    }
338d417ab0ea526cee036a71e67af4a8a898e35f564Robert Craig
339d417ab0ea526cee036a71e67af4a8a898e35f564Robert Craig    /**
340d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig     * Labels a package based on an seinfo tag from install policy.
341d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig     * The label is attached to the ApplicationInfo instance of the package.
3420aa5163c13caff1a3864548bf5e587b041895058Dianne Hackborn     * @param pkg object representing the package to be labeled.
34399a626c2719e1965364fad543101799f527e28caRobert Craig     * @return boolean which determines whether a non null seinfo label
34499a626c2719e1965364fad543101799f527e28caRobert Craig     *         was assigned to the package. A null value simply meaning that
34599a626c2719e1965364fad543101799f527e28caRobert Craig     *         no policy matched.
346d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig     */
34799a626c2719e1965364fad543101799f527e28caRobert Craig    public static boolean assignSeinfoValue(PackageParser.Package pkg) {
348d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
34983b54ecab73912a16d783f0d03c2aada378173a7Robert Craig        // We just want one of the signatures to match.
35083b54ecab73912a16d783f0d03c2aada378173a7Robert Craig        for (Signature s : pkg.mSignatures) {
35183b54ecab73912a16d783f0d03c2aada378173a7Robert Craig            if (s == null)
35283b54ecab73912a16d783f0d03c2aada378173a7Robert Craig                continue;
353d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
35483b54ecab73912a16d783f0d03c2aada378173a7Robert Craig            Policy policy = sSigSeinfo.get(s);
35583b54ecab73912a16d783f0d03c2aada378173a7Robert Craig            if (policy != null) {
35683b54ecab73912a16d783f0d03c2aada378173a7Robert Craig                String seinfo = policy.checkPolicy(pkg.packageName);
35783b54ecab73912a16d783f0d03c2aada378173a7Robert Craig                if (seinfo != null) {
35883b54ecab73912a16d783f0d03c2aada378173a7Robert Craig                    pkg.applicationInfo.seinfo = seinfo;
35983b54ecab73912a16d783f0d03c2aada378173a7Robert Craig                    if (DEBUG_POLICY_INSTALL)
36083b54ecab73912a16d783f0d03c2aada378173a7Robert Craig                        Slog.i(TAG, "package (" + pkg.packageName +
36183b54ecab73912a16d783f0d03c2aada378173a7Robert Craig                               ") labeled with seinfo=" + seinfo);
362d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
36383b54ecab73912a16d783f0d03c2aada378173a7Robert Craig                    return true;
364d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig                }
365d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig            }
366d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig        }
367d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig
368d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig        // If we have a default seinfo value then great, otherwise
369d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig        // we set a null object and that is what we started with.
37099a626c2719e1965364fad543101799f527e28caRobert Craig        pkg.applicationInfo.seinfo = sDefaultSeinfo;
371d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig        if (DEBUG_POLICY_INSTALL)
37299a626c2719e1965364fad543101799f527e28caRobert Craig            Slog.i(TAG, "package (" + pkg.packageName + ") labeled with seinfo="
37399a626c2719e1965364fad543101799f527e28caRobert Craig                   + (sDefaultSeinfo == null ? "null" : sDefaultSeinfo));
37499a626c2719e1965364fad543101799f527e28caRobert Craig
37599a626c2719e1965364fad543101799f527e28caRobert Craig        return (sDefaultSeinfo != null);
376d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig    }
3774385343fd82058c397a46530458ae58999f75639Robert Craig
3784385343fd82058c397a46530458ae58999f75639Robert Craig    /**
3794385343fd82058c397a46530458ae58999f75639Robert Craig     * Determines if a recursive restorecon on /data/data and /data/user is needed.
3804385343fd82058c397a46530458ae58999f75639Robert Craig     * It does this by comparing the SHA-1 of the seapp_contexts file against the
3814385343fd82058c397a46530458ae58999f75639Robert Craig     * stored hash at /data/system/seapp_hash.
3824385343fd82058c397a46530458ae58999f75639Robert Craig     *
3834385343fd82058c397a46530458ae58999f75639Robert Craig     * @return Returns true if the restorecon should occur or false otherwise.
3844385343fd82058c397a46530458ae58999f75639Robert Craig     */
3854385343fd82058c397a46530458ae58999f75639Robert Craig    public static boolean shouldRestorecon() {
3864385343fd82058c397a46530458ae58999f75639Robert Craig        // Any error with the seapp_contexts file should be fatal
3874385343fd82058c397a46530458ae58999f75639Robert Craig        byte[] currentHash = null;
3884385343fd82058c397a46530458ae58999f75639Robert Craig        try {
389f877829d358e069a4abf413bcc356044c0232aaaRobert Craig            currentHash = returnHash(SEAPP_CONTEXTS);
3904385343fd82058c397a46530458ae58999f75639Robert Craig        } catch (IOException ioe) {
3914385343fd82058c397a46530458ae58999f75639Robert Craig            Slog.e(TAG, "Error with hashing seapp_contexts.", ioe);
3924385343fd82058c397a46530458ae58999f75639Robert Craig            return false;
3934385343fd82058c397a46530458ae58999f75639Robert Craig        }
3944385343fd82058c397a46530458ae58999f75639Robert Craig
3954385343fd82058c397a46530458ae58999f75639Robert Craig        // Push past any error with the stored hash file
3964385343fd82058c397a46530458ae58999f75639Robert Craig        byte[] storedHash = null;
3974385343fd82058c397a46530458ae58999f75639Robert Craig        try {
3984385343fd82058c397a46530458ae58999f75639Robert Craig            storedHash = IoUtils.readFileAsByteArray(SEAPP_HASH_FILE);
3994385343fd82058c397a46530458ae58999f75639Robert Craig        } catch (IOException ioe) {
4000aa5163c13caff1a3864548bf5e587b041895058Dianne Hackborn            Slog.w(TAG, "Error opening " + SEAPP_HASH_FILE + ". Assuming first boot.");
4014385343fd82058c397a46530458ae58999f75639Robert Craig        }
4024385343fd82058c397a46530458ae58999f75639Robert Craig
4034385343fd82058c397a46530458ae58999f75639Robert Craig        return (storedHash == null || !MessageDigest.isEqual(storedHash, currentHash));
4044385343fd82058c397a46530458ae58999f75639Robert Craig    }
4054385343fd82058c397a46530458ae58999f75639Robert Craig
4064385343fd82058c397a46530458ae58999f75639Robert Craig    /**
4074385343fd82058c397a46530458ae58999f75639Robert Craig     * Stores the SHA-1 of the seapp_contexts to /data/system/seapp_hash.
4084385343fd82058c397a46530458ae58999f75639Robert Craig     */
4094385343fd82058c397a46530458ae58999f75639Robert Craig    public static void setRestoreconDone() {
4104385343fd82058c397a46530458ae58999f75639Robert Craig        try {
411f877829d358e069a4abf413bcc356044c0232aaaRobert Craig            final byte[] currentHash = returnHash(SEAPP_CONTEXTS);
4124385343fd82058c397a46530458ae58999f75639Robert Craig            dumpHash(new File(SEAPP_HASH_FILE), currentHash);
4134385343fd82058c397a46530458ae58999f75639Robert Craig        } catch (IOException ioe) {
4144385343fd82058c397a46530458ae58999f75639Robert Craig            Slog.e(TAG, "Error with saving hash to " + SEAPP_HASH_FILE, ioe);
4154385343fd82058c397a46530458ae58999f75639Robert Craig        }
4164385343fd82058c397a46530458ae58999f75639Robert Craig    }
4174385343fd82058c397a46530458ae58999f75639Robert Craig
4184385343fd82058c397a46530458ae58999f75639Robert Craig    /**
4194385343fd82058c397a46530458ae58999f75639Robert Craig     * Dump the contents of a byte array to a specified file.
4204385343fd82058c397a46530458ae58999f75639Robert Craig     *
4214385343fd82058c397a46530458ae58999f75639Robert Craig     * @param file The file that receives the byte array content.
4224385343fd82058c397a46530458ae58999f75639Robert Craig     * @param content A byte array that will be written to the specified file.
4234385343fd82058c397a46530458ae58999f75639Robert Craig     * @throws IOException if any failed I/O operation occured.
4244385343fd82058c397a46530458ae58999f75639Robert Craig     *         Included is the failure to atomically rename the tmp
4254385343fd82058c397a46530458ae58999f75639Robert Craig     *         file used in the process.
4264385343fd82058c397a46530458ae58999f75639Robert Craig     */
4274385343fd82058c397a46530458ae58999f75639Robert Craig    private static void dumpHash(File file, byte[] content) throws IOException {
4284385343fd82058c397a46530458ae58999f75639Robert Craig        FileOutputStream fos = null;
4294385343fd82058c397a46530458ae58999f75639Robert Craig        File tmp = null;
4304385343fd82058c397a46530458ae58999f75639Robert Craig        try {
4314385343fd82058c397a46530458ae58999f75639Robert Craig            tmp = File.createTempFile("seapp_hash", ".journal", file.getParentFile());
4324385343fd82058c397a46530458ae58999f75639Robert Craig            tmp.setReadable(true);
4334385343fd82058c397a46530458ae58999f75639Robert Craig            fos = new FileOutputStream(tmp);
4344385343fd82058c397a46530458ae58999f75639Robert Craig            fos.write(content);
4354385343fd82058c397a46530458ae58999f75639Robert Craig            fos.getFD().sync();
4364385343fd82058c397a46530458ae58999f75639Robert Craig            if (!tmp.renameTo(file)) {
4374385343fd82058c397a46530458ae58999f75639Robert Craig                throw new IOException("Failure renaming " + file.getCanonicalPath());
4384385343fd82058c397a46530458ae58999f75639Robert Craig            }
4394385343fd82058c397a46530458ae58999f75639Robert Craig        } finally {
4404385343fd82058c397a46530458ae58999f75639Robert Craig            if (tmp != null) {
4414385343fd82058c397a46530458ae58999f75639Robert Craig                tmp.delete();
4424385343fd82058c397a46530458ae58999f75639Robert Craig            }
4434385343fd82058c397a46530458ae58999f75639Robert Craig            IoUtils.closeQuietly(fos);
4444385343fd82058c397a46530458ae58999f75639Robert Craig        }
4454385343fd82058c397a46530458ae58999f75639Robert Craig    }
4464385343fd82058c397a46530458ae58999f75639Robert Craig
4474385343fd82058c397a46530458ae58999f75639Robert Craig    /**
4484385343fd82058c397a46530458ae58999f75639Robert Craig     * Return the SHA-1 of a file.
4494385343fd82058c397a46530458ae58999f75639Robert Craig     *
4504385343fd82058c397a46530458ae58999f75639Robert Craig     * @param file The path to the file given as a string.
4514385343fd82058c397a46530458ae58999f75639Robert Craig     * @return Returns the SHA-1 of the file as a byte array.
4524385343fd82058c397a46530458ae58999f75639Robert Craig     * @throws IOException if any failed I/O operations occured.
4534385343fd82058c397a46530458ae58999f75639Robert Craig     */
4544385343fd82058c397a46530458ae58999f75639Robert Craig    private static byte[] returnHash(String file) throws IOException {
4554385343fd82058c397a46530458ae58999f75639Robert Craig        try {
4564385343fd82058c397a46530458ae58999f75639Robert Craig            final byte[] contents = IoUtils.readFileAsByteArray(file);
4574385343fd82058c397a46530458ae58999f75639Robert Craig            return MessageDigest.getInstance("SHA-1").digest(contents);
4584385343fd82058c397a46530458ae58999f75639Robert Craig        } catch (NoSuchAlgorithmException nsae) {
4594385343fd82058c397a46530458ae58999f75639Robert Craig            throw new RuntimeException(nsae);  // impossible
4604385343fd82058c397a46530458ae58999f75639Robert Craig        }
4614385343fd82058c397a46530458ae58999f75639Robert Craig    }
462f877829d358e069a4abf413bcc356044c0232aaaRobert Craig
463f877829d358e069a4abf413bcc356044c0232aaaRobert Craig    private static boolean useOverridePolicy() {
464f877829d358e069a4abf413bcc356044c0232aaaRobert Craig        try {
465f877829d358e069a4abf413bcc356044c0232aaaRobert Craig            final String overrideVersion = IoUtils.readFileAsString(DATA_VERSION_FILE);
466f877829d358e069a4abf413bcc356044c0232aaaRobert Craig            final String baseVersion = IoUtils.readFileAsString(BASE_VERSION_FILE);
467f877829d358e069a4abf413bcc356044c0232aaaRobert Craig            if (overrideVersion.equals(baseVersion)) {
468f877829d358e069a4abf413bcc356044c0232aaaRobert Craig                return true;
469f877829d358e069a4abf413bcc356044c0232aaaRobert Craig            }
470f877829d358e069a4abf413bcc356044c0232aaaRobert Craig            Slog.e(TAG, "Override policy version '" + overrideVersion + "' doesn't match " +
471f877829d358e069a4abf413bcc356044c0232aaaRobert Craig                   "base version '" + baseVersion + "'. Skipping override policy files.");
472f877829d358e069a4abf413bcc356044c0232aaaRobert Craig        } catch (FileNotFoundException fnfe) {
473f877829d358e069a4abf413bcc356044c0232aaaRobert Craig            // Override version file doesn't have to exist so silently ignore.
474f877829d358e069a4abf413bcc356044c0232aaaRobert Craig        } catch (IOException ioe) {
475f877829d358e069a4abf413bcc356044c0232aaaRobert Craig            Slog.w(TAG, "Skipping override policy files.", ioe);
476f877829d358e069a4abf413bcc356044c0232aaaRobert Craig        }
477f877829d358e069a4abf413bcc356044c0232aaaRobert Craig        return false;
478f877829d358e069a4abf413bcc356044c0232aaaRobert Craig    }
479d3f8d0333cf4d9d2e47b5b082a6f70460adcf5ffRobert Craig}
480