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