diff options
author | Stephen Smalley <sds@tycho.nsa.gov> | 2015-02-27 14:35:53 -0500 |
---|---|---|
committer | Stephen Smalley <sds@tycho.nsa.gov> | 2015-02-27 16:07:55 -0500 |
commit | e9dc17233f25483298186b0521874bf962e3f10e (patch) | |
tree | fc9ae50cad1aad4e52384e7d49b926ebedcbee05 /services | |
parent | 8cba382f04e4ead4a6b8c4a74216ddb383e8db91 (diff) | |
download | frameworks_base-e9dc17233f25483298186b0521874bf962e3f10e.zip frameworks_base-e9dc17233f25483298186b0521874bf962e3f10e.tar.gz frameworks_base-e9dc17233f25483298186b0521874bf962e3f10e.tar.bz2 |
SELinuxPolicyInstallReceiver: Prevent partial or mixed policy updates.
The current SELinuxPolicyInstallReceiver logic can yield a partial
or mixed (old and new) set of policy files under /data/security/current
if there is an error or a crash at certain points before completing
the installation of the update.
Rewrite the logic to avoid the possibility of such partial or mixed
policy updates by using rename on the entire directory of policy
files rather than operating on a per-file basis. Also separate
the extraction of the policy files from the bundle into their own
temporary directory. Make sure we delete any previous temporary directory
or backup directory before using them for this update. Drop the
use of a symlink for /data/security/current altogether; it provides
no benefit.
Change-Id: I564af01c2c3ca1531c216013b8724c7511f32de8
Signed-off-by: Stephen Smalley <sds@tycho.nsa.gov>
Diffstat (limited to 'services')
-rw-r--r-- | services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java | 81 |
1 files changed, 29 insertions, 52 deletions
diff --git a/services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java b/services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java index 24318df..04774d4 100644 --- a/services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java +++ b/services/core/java/com/android/server/updates/SELinuxPolicyInstallReceiver.java @@ -48,39 +48,6 @@ public class SELinuxPolicyInstallReceiver extends ConfigUpdateInstallReceiver { super("/data/security/bundle", "sepolicy_bundle", "metadata/", "version"); } - private void backupContexts(File contexts) { - new File(contexts, versionPath).renameTo( - new File(contexts, versionPath + "_backup")); - - new File(contexts, macPermissionsPath).renameTo( - new File(contexts, macPermissionsPath + "_backup")); - - new File(contexts, seappContextsPath).renameTo( - new File(contexts, seappContextsPath + "_backup")); - - new File(contexts, propertyContextsPath).renameTo( - new File(contexts, propertyContextsPath + "_backup")); - - new File(contexts, fileContextsPath).renameTo( - new File(contexts, fileContextsPath + "_backup")); - - new File(contexts, sepolicyPath).renameTo( - new File(contexts, sepolicyPath + "_backup")); - - new File(contexts, serviceContextsPath).renameTo( - new File(contexts, serviceContextsPath + "_backup")); - } - - private void copyUpdate(File contexts) { - new File(updateDir, versionPath).renameTo(new File(contexts, versionPath)); - new File(updateDir, macPermissionsPath).renameTo(new File(contexts, macPermissionsPath)); - new File(updateDir, seappContextsPath).renameTo(new File(contexts, seappContextsPath)); - new File(updateDir, propertyContextsPath).renameTo(new File(contexts, propertyContextsPath)); - new File(updateDir, fileContextsPath).renameTo(new File(contexts, fileContextsPath)); - new File(updateDir, sepolicyPath).renameTo(new File(contexts, sepolicyPath)); - new File(updateDir, serviceContextsPath).renameTo(new File(contexts, serviceContextsPath)); - } - private int readInt(BufferedInputStream reader) throws IOException { int value = 0; for (int i=0; i < 4; i++) { @@ -108,17 +75,27 @@ public class SELinuxPolicyInstallReceiver extends ConfigUpdateInstallReceiver { writeUpdate(updateDir, destination, Base64.decode(chunk, Base64.DEFAULT)); } + private void deleteRecursive(File fileOrDirectory) { + if (fileOrDirectory.isDirectory()) + for (File child : fileOrDirectory.listFiles()) + deleteRecursive(child); + fileOrDirectory.delete(); + } + private void unpackBundle() throws IOException { BufferedInputStream stream = new BufferedInputStream(new FileInputStream(updateContent)); + File tmp = new File(updateDir.getParentFile(), "tmp"); try { int[] chunkLengths = readChunkLengths(stream); - installFile(new File(updateDir, versionPath), stream, chunkLengths[0]); - installFile(new File(updateDir, macPermissionsPath), stream, chunkLengths[1]); - installFile(new File(updateDir, seappContextsPath), stream, chunkLengths[2]); - installFile(new File(updateDir, propertyContextsPath), stream, chunkLengths[3]); - installFile(new File(updateDir, fileContextsPath), stream, chunkLengths[4]); - installFile(new File(updateDir, sepolicyPath), stream, chunkLengths[5]); - installFile(new File(updateDir, serviceContextsPath), stream, chunkLengths[6]); + deleteRecursive(tmp); + tmp.mkdirs(); + installFile(new File(tmp, versionPath), stream, chunkLengths[0]); + installFile(new File(tmp, macPermissionsPath), stream, chunkLengths[1]); + installFile(new File(tmp, seappContextsPath), stream, chunkLengths[2]); + installFile(new File(tmp, propertyContextsPath), stream, chunkLengths[3]); + installFile(new File(tmp, fileContextsPath), stream, chunkLengths[4]); + installFile(new File(tmp, sepolicyPath), stream, chunkLengths[5]); + installFile(new File(tmp, serviceContextsPath), stream, chunkLengths[6]); } finally { IoUtils.closeQuietly(stream); } @@ -126,22 +103,22 @@ public class SELinuxPolicyInstallReceiver extends ConfigUpdateInstallReceiver { private void applyUpdate() throws IOException, ErrnoException { Slog.i(TAG, "Applying SELinux policy"); - File contexts = new File(updateDir.getParentFile(), "contexts"); + File backup = new File(updateDir.getParentFile(), "backup"); File current = new File(updateDir.getParentFile(), "current"); - File update = new File(updateDir.getParentFile(), "update"); File tmp = new File(updateDir.getParentFile(), "tmp"); if (current.exists()) { - Os.symlink(updateDir.getPath(), update.getPath()); - Os.rename(update.getPath(), current.getPath()); - } else { - Os.symlink(updateDir.getPath(), current.getPath()); + deleteRecursive(backup); + Os.rename(current.getPath(), backup.getPath()); + } + try { + Os.rename(tmp.getPath(), current.getPath()); + SystemProperties.set("selinux.reload_policy", "1"); + } catch (ErrnoException e) { + Slog.e(TAG, "Could not update selinux policy: ", e); + if (backup.exists()) { + Os.rename(backup.getPath(), current.getPath()); + } } - contexts.mkdirs(); - backupContexts(contexts); - copyUpdate(contexts); - Os.symlink(contexts.getPath(), tmp.getPath()); - Os.rename(tmp.getPath(), current.getPath()); - SystemProperties.set("selinux.reload_policy", "1"); } @Override |