fskeyring & userspace reboot: support CE keys

During userspace reboot /data might be unmounted & remounted, meaning
that CE keys stored in fs-level keyring will be lost. In order to be
able to restore them, when installing new key to fs-level keyring, it's
also added to session-level keyring with type "fscrypt-provisioning".

Then when init_user0 is called during userspace reboot, vold will try to
load CE keys from the session-level keyring back into fs-level keyring
for all the users that were unlocked before the reboot.

If for any user vold fails to install the key, init_user0 will fail and
fallback to hard reboot will be triggered.

Test: set a pin pattern
Test: adb shell setprop sys.init.userdata_remount.force_umount 1
Test: adb shell svc power reboot userspace
Test: atest CtsUserspaceRebootHostSideTestCases
Bug: 143970043
Change-Id: I37603dc136c7ededc7b0381e4d730cb0ffd912b4
Merged-In: I37603dc136c7ededc7b0381e4d730cb0ffd912b4
(cherry picked from commit 1ee35cf002de9f6aaa6f33e67d882cdbbaa35cc2)
diff --git a/FsCrypt.cpp b/FsCrypt.cpp
index a84756f..aa66c01 100644
--- a/FsCrypt.cpp
+++ b/FsCrypt.cpp
@@ -374,6 +374,17 @@
     return true;
 }
 
+// Attempt to reinstall CE keys for users that we think are unlocked.
+static bool try_reload_ce_keys() {
+    for (const auto& it : s_ce_policies) {
+        if (!android::vold::reloadKeyFromSessionKeyring(DATA_MNT_POINT, it.second)) {
+            LOG(ERROR) << "Failed to load CE key from session keyring for user " << it.first;
+            return false;
+        }
+    }
+    return true;
+}
+
 bool fscrypt_initialize_systemwide_keys() {
     LOG(INFO) << "fscrypt_initialize_systemwide_keys";
 
@@ -440,6 +451,13 @@
         fscrypt_unlock_user_key(0, 0, "!", "!");
     }
 
+    // In some scenarios (e.g. userspace reboot) we might unmount userdata
+    // without doing a hard reboot. If CE keys were stored in fs keyring then
+    // they will be lost after unmount. Attempt to re-install them.
+    if (fscrypt_is_native() && android::vold::isFsKeyringSupported()) {
+        if (!try_reload_ce_keys()) return false;
+    }
+
     return true;
 }