ART: Boot integrity checks for dalvik cache
Add a boot rc file that checks for boot classpath components
in the dalvik-cache and ensures they are fsverity-protected.
Bug: 125474642
Test: m
Test: manual
Change-Id: I3e7c2926e549c88934d86eb2d1d5264c5930b674
diff --git a/Android.mk b/Android.mk
index de3e2b3..65b904f 100644
--- a/Android.mk
+++ b/Android.mk
@@ -364,6 +364,7 @@
ifneq ($(HOST_OS),darwin)
LOCAL_REQUIRED_MODULES += $(APEX_TEST_MODULE)
endif
+LOCAL_REQUIRED_MODULES += art_apex_boot_integrity
# Clear locally used variable.
art_target_include_debug_build :=
diff --git a/build/apex/Android.bp b/build/apex/Android.bp
index 128a079..dcabfc6 100644
--- a/build/apex/Android.bp
+++ b/build/apex/Android.bp
@@ -188,6 +188,7 @@
prebuilts: art_runtime_data_file_prebuilts
+ ["com.android.runtime.ld.config.txt"],
key: "com.android.runtime.key",
+ required: ["art_apex_boot_integrity"],
}
// Release version of the Runtime APEX module (not containing debug
@@ -358,3 +359,9 @@
name: "art_postinstall_hook",
src: "art_postinstall_hook.sh",
}
+
+sh_binary {
+ name: "art_apex_boot_integrity",
+ src: "art_apex_boot_integrity.sh",
+ init_rc: ["art_apex_boot_integrity.rc"],
+}
diff --git a/build/apex/art_apex_boot_integrity.rc b/build/apex/art_apex_boot_integrity.rc
new file mode 100644
index 0000000..92f616b
--- /dev/null
+++ b/build/apex/art_apex_boot_integrity.rc
@@ -0,0 +1,21 @@
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# Check that boot classpath files in /data/dalvik-cache have fsverity
+# protection
+
+on post-fs-data
+ # TODO: Use apex path once feature is implemented.
+ exec - root -- /system/bin/art_apex_boot_integrity
diff --git a/build/apex/art_apex_boot_integrity.sh b/build/apex/art_apex_boot_integrity.sh
new file mode 100644
index 0000000..c21377b
--- /dev/null
+++ b/build/apex/art_apex_boot_integrity.sh
@@ -0,0 +1,55 @@
+#!/system/bin/sh
+
+# Copyright (C) 2019 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+alias log_info="log -t art_apex -p i"
+alias log_error="log -t art_apex -p f"
+
+log_info "=== ART pre-boot integrity checks ==="
+
+# Measure (and enable) fsverity to see if things are installed. Enable is not
+# idempotent, and we'd need to parse the error string to see whether it says
+# data was installed. Rather do a two-step.
+FILES=`find /data/dalvik-cache -type f -a -name 'system@framework@boot*'`
+
+if [ ! -f "/system/bin/fsverity" ] ; then
+ log_error "Device is not fsverity-enabled."
+ rm -f $FILES
+ exit 0
+fi
+
+for FILE in $FILES ; do
+ if [ ! -f "$FILE" ] ; then
+ continue # May have deleted already.
+ fi
+
+ # Check for fsverity protection.
+ fsverity measure $FILE || \
+ ENABLE_MSG=`fsverity enable $FILE 2>&1` || \
+ {
+ # No installed data, can't enable - clean up.
+ # Note: to avoid side effects, only delete the tested files. To avoid
+ # understanding arches here, delete all, even if that may delete
+ # too aggressively.
+ log_error "Enable failed: $ENABLE_MSG" ;
+ rm -f $FILES ;
+ exit 1 ;
+ }
+
+ # Check for integrity.
+ INTEGRITY_MSG=`dd if=$FILE of=/dev/null bs=4k 2>&1` || \
+ { log_error "Integrity failed: $INTEGRITY_MSG" ; rm -f $FILES ; exit 2 ; }
+done