From 27f19427f631548a06beccf171c89b4794be4d40 Mon Sep 17 00:00:00 2001
From: Alex Deymo <deymo@google.com>
Date: Wed, 3 Aug 2016 20:31:37 -0700
Subject: [PATCH] Allow executing update_engine_sideload from recovery.

The recovery flow for A/B devices allows to sideload an OTA downloaded
to a desktop and apply from recovery. This patch allows the "recovery"
context to perform all the operations required to apply an update as
update_engine would do in the background. These rules are now extracted
into a new attributte called update_engine_common shared between
recovery and update_engine.

Bug: 27178350

(cherry picked from commit d63084d32a45ea443c19c871f9de7d44102034a0)

Change-Id: I1f3e1e83a21e37e09b69cd9c497f87b42b9cbeb1
---
 attributes              |  5 +++++
 postinstall.te          | 13 +++++++------
 recovery.te             |  3 +++
 update_engine.te        | 36 +-----------------------------------
 update_engine_common.te | 37 +++++++++++++++++++++++++++++++++++++
 5 files changed, 53 insertions(+), 41 deletions(-)
 create mode 100644 update_engine_common.te

diff --git a/attributes b/attributes
index 1160a95b6..a846c3472 100644
--- a/attributes
+++ b/attributes
@@ -108,3 +108,8 @@ attribute binderservicedomain;
 # requires are specific to the implementation provided in each device, but
 # common daemons need to be aware of those when calling into the HAL.
 attribute boot_control_hal;
+
+# update_engine related domains that need to apply an update and run
+# postinstall. This includes the background daemon and the sideload tool from
+# recovery for A/B devices.
+attribute update_engine_common;
diff --git a/postinstall.te b/postinstall.te
index 0560606c7..0f6bb749b 100644
--- a/postinstall.te
+++ b/postinstall.te
@@ -5,8 +5,8 @@ type postinstall, domain;
 
 # Allow postinstall to write to its stdout/stderr when redirected via pipes to
 # update_engine.
-allow postinstall update_engine:fd use;
-allow postinstall update_engine:fifo_file rw_file_perms;
+allow postinstall update_engine_common:fd use;
+allow postinstall update_engine_common:fifo_file rw_file_perms;
 
 # Allow postinstall to read and execute directories and files in the same
 # mounted location.
@@ -19,10 +19,6 @@ allow postinstall shell_exec:file rx_file_perms;
 allow postinstall system_file:file rx_file_perms;
 allow postinstall toolbox_exec:file rx_file_perms;
 
-# No domain other than update_engine should transition to postinstall, as it is
-# only meant to run during the update.
-neverallow { domain -update_engine } postinstall:process { transition dyntransition };
-
 #
 # For OTA dexopt.
 #
@@ -35,3 +31,8 @@ binder_call(postinstall, system_server)
 allow postinstall otadexopt_service:service_manager find;
 
 domain_auto_trans(postinstall, otapreopt_chroot_exec, otapreopt_chroot)
+
+# No domain other than update_engine and recovery (via update_engine_sideload)
+# should transition to postinstall, as it is only meant to run during the
+# update.
+neverallow { domain -update_engine -recovery } postinstall:process { transition dyntransition };
diff --git a/recovery.te b/recovery.te
index d5767ed00..209a276ea 100644
--- a/recovery.te
+++ b/recovery.te
@@ -7,6 +7,9 @@ type recovery, domain, domain_deprecated;
 # But the allow rules are only included in the recovery policy.
 # Otherwise recovery is only allowed the domain rules.
 recovery_only(`
+  # Allow recovery to perform an update as update_engine would do.
+  typeattribute recovery update_engine_common, boot_control_hal;
+
   allow recovery self:capability { chown dac_override fowner fsetid setfcap setuid setgid sys_admin sys_tty_config };
 
   # Set security contexts on files that are not known to the loaded policy.
diff --git a/update_engine.te b/update_engine.te
index 9f942430b..fa3f05ccb 100644
--- a/update_engine.te
+++ b/update_engine.te
@@ -1,6 +1,6 @@
 # Domain for update_engine daemon.
 # update_engine uses the boot_control_hal.
-type update_engine, domain, domain_deprecated, boot_control_hal;
+type update_engine, domain, domain_deprecated, update_engine_common, boot_control_hal;
 type update_engine_exec, exec_type, file_type;
 type update_engine_data_file, file_type, data_file_type;
 
@@ -21,43 +21,9 @@ dontaudit update_engine kernel:process setsched;
 allow update_engine update_engine_data_file:dir { create_dir_perms };
 allow update_engine update_engine_data_file:file { create_file_perms };
 
-# Allow update_engine to reach block devices in /dev/block.
-allow update_engine block_device:dir search;
-
-# Allow read/write on system and boot partitions.
-allow update_engine boot_block_device:blk_file rw_file_perms;
-allow update_engine system_block_device:blk_file rw_file_perms;
-
-# Allow to set recovery options in the BCB. Used to trigger factory reset when
-# the update to an older version (channel change) or incompatible version
-# requires it.
-allow update_engine misc_block_device:blk_file rw_file_perms;
-
 # Don't allow kernel module loading, just silence the logs.
 dontaudit update_engine kernel:system module_request;
 
-# Allow update_engine to mount on the /postinstall directory and reset the
-# labels on the mounted filesystem to postinstall_file.
-allow update_engine postinstall_mnt_dir:dir mounton;
-allow update_engine postinstall_file:filesystem { mount unmount relabelfrom relabelto };
-allow update_engine labeledfs:filesystem relabelfrom;
-
-# Allow update_engine to read and execute postinstall_file.
-allow update_engine postinstall_file:file rx_file_perms;
-allow update_engine postinstall_file:lnk_file r_file_perms;
-allow update_engine postinstall_file:dir r_dir_perms;
-
-# The postinstall program is run by update_engine and will always be tagged as a
-# postinstall_file regardless of its attributes in the new system.
-domain_auto_trans(update_engine, postinstall_file, postinstall)
-
-# A postinstall program is typically a shell script (with a #!), so we allow
-# to execute those.
-allow update_engine shell_exec:file rx_file_perms;
-
-# Allow update_engine to suspend, resume and kill the postinstall program.
-allow update_engine postinstall:process { signal sigstop };
-
 # Register the service to perform Binder IPC.
 binder_use(update_engine)
 allow update_engine update_engine_service:service_manager { add };
diff --git a/update_engine_common.te b/update_engine_common.te
new file mode 100644
index 000000000..e70e44db1
--- /dev/null
+++ b/update_engine_common.te
@@ -0,0 +1,37 @@
+# update_engine payload application permissions. These are shared between the
+# background daemon and the recovery tool to sideload an update.
+
+# Allow update_engine to reach block devices in /dev/block.
+allow update_engine_common block_device:dir search;
+
+# Allow read/write on system and boot partitions.
+allow update_engine_common boot_block_device:blk_file rw_file_perms;
+allow update_engine_common system_block_device:blk_file rw_file_perms;
+
+# Allow to set recovery options in the BCB. Used to trigger factory reset when
+# the update to an older version (channel change) or incompatible version
+# requires it.
+allow update_engine_common misc_block_device:blk_file rw_file_perms;
+
+# Allow update_engine_common to mount on the /postinstall directory and reset the
+# labels on the mounted filesystem to postinstall_file.
+allow update_engine_common postinstall_mnt_dir:dir mounton;
+allow update_engine_common postinstall_file:filesystem { mount unmount relabelfrom relabelto };
+allow update_engine_common labeledfs:filesystem relabelfrom;
+
+# Allow update_engine_common to read and execute postinstall_file.
+allow update_engine_common postinstall_file:file rx_file_perms;
+allow update_engine_common postinstall_file:lnk_file r_file_perms;
+allow update_engine_common postinstall_file:dir r_dir_perms;
+
+# The postinstall program is run by update_engine_common and will always be tagged as a
+# postinstall_file regardless of its attributes in the new system.
+domain_auto_trans(update_engine_common, postinstall_file, postinstall)
+
+# A postinstall program is typically a shell script (with a #!), so we allow
+# to execute those.
+allow update_engine_common shell_exec:file rx_file_perms;
+
+# Allow update_engine_common to suspend, resume and kill the postinstall program.
+allow update_engine_common postinstall:process { signal sigstop };
+
-- 
GitLab