Merge 8d920eed71f7722d2b1a477978e62843acac67f8 on remote branch

Change-Id: I5b382fdee11b0927aaeff0764d8fbca43ae98d0e
diff --git a/FsCrypt.cpp b/FsCrypt.cpp
index 98d535f..9794b0e 100644
--- a/FsCrypt.cpp
+++ b/FsCrypt.cpp
@@ -199,7 +199,7 @@
     auto const paths = get_ce_key_paths(directory_path);
     for (auto const ce_key_path : paths) {
         LOG(DEBUG) << "Trying user CE key " << ce_key_path;
-        if (retrieveKey(ce_key_path, auth, ce_key)) {
+        if (retrieveKey(ce_key_path, auth, ce_key, false)) {
             LOG(DEBUG) << "Successfully retrieved key";
             fixate_user_ce_key(directory_path, ce_key_path, paths);
             return true;
@@ -408,7 +408,7 @@
         userid_t user_id = std::stoi(entry->d_name);
         auto key_path = de_dir + "/" + entry->d_name;
         KeyBuffer de_key;
-        if (!retrieveKey(key_path, kEmptyAuthentication, &de_key)) return false;
+        if (!retrieveKey(key_path, kEmptyAuthentication, &de_key, false)) return false;
         EncryptionPolicy de_policy;
         if (!install_storage_key(DATA_MNT_POINT, options, de_key, &de_policy)) return false;
         auto ret = s_de_policies.insert({user_id, de_policy});
@@ -442,7 +442,7 @@
 
     KeyBuffer device_key;
     if (!retrieveOrGenerateKey(device_key_path, device_key_temp, kEmptyAuthentication,
-                               makeGen(options), &device_key))
+                               makeGen(options), &device_key, false))
         return false;
 
     EncryptionPolicy device_policy;
@@ -676,7 +676,7 @@
     EncryptionOptions options;
     if (!get_volume_file_encryption_options(&options)) return false;
     KeyBuffer key;
-    if (!retrieveOrGenerateKey(key_path, key_path + "_tmp", auth, makeGen(options), &key))
+    if (!retrieveOrGenerateKey(key_path, key_path + "_tmp", auth, makeGen(options), &key, false))
         return false;
     if (!install_storage_key(BuildDataPath(volume_uuid), options, key, policy)) return false;
     return true;
@@ -695,12 +695,12 @@
     auto const directory_path = get_ce_key_directory_path(user_id);
     KeyBuffer ce_key;
     std::string ce_key_current_path = get_ce_key_current_path(directory_path);
-    if (retrieveKey(ce_key_current_path, retrieve_auth, &ce_key)) {
+    if (retrieveKey(ce_key_current_path, retrieve_auth, &ce_key, false)) {
         LOG(DEBUG) << "Successfully retrieved key";
         // TODO(147732812): Remove this once Locksettingservice is fixed.
         // Currently it calls fscrypt_clear_user_key_auth with a secret when lockscreen is
         // changed from swipe to none or vice-versa
-    } else if (retrieveKey(ce_key_current_path, kEmptyAuthentication, &ce_key)) {
+    } else if (retrieveKey(ce_key_current_path, kEmptyAuthentication, &ce_key, false)) {
         LOG(DEBUG) << "Successfully retrieved key with empty auth";
     } else {
         LOG(ERROR) << "Failed to retrieve key for user " << user_id;
diff --git a/KeyStorage.h b/KeyStorage.h
index b4645b8..5c7c1db 100644
--- a/KeyStorage.h
+++ b/KeyStorage.h
@@ -68,8 +68,20 @@
                         const KeyAuthentication& auth, const KeyBuffer& key);
 
 // Retrieve the key from the named directory.
+//
+// If the key is wrapped by a Keymaster key that requires an upgrade, then that
+// Keymaster key is upgraded.  If |keepOld| is false, then the upgraded
+// Keymaster key replaces the original one.  As part of this, the original is
+// deleted from Keymaster; however, if a user data checkpoint is active, this
+// part is delayed until the checkpoint is committed.
+//
+// If instead |keepOld| is true, then the upgraded key doesn't actually replace
+// the original one.  This is needed *only* if |dir| isn't located in /data and
+// a user data checkpoint is active.  In this case the caller must handle
+// replacing the original key if the checkpoint is committed, and deleting the
+// upgraded key if the checkpoint is rolled back.
 bool retrieveKey(const std::string& dir, const KeyAuthentication& auth, KeyBuffer* key,
-                 bool keepOld = false);
+                 bool keepOld);
 
 // Securely destroy the key stored in the named directory and delete the directory.
 bool destroyKey(const std::string& dir);
diff --git a/KeyUtil.h b/KeyUtil.h
index 23278c1..0f5bc93 100644
--- a/KeyUtil.h
+++ b/KeyUtil.h
@@ -74,9 +74,11 @@
 // responsible for dropping caches.
 bool evictKey(const std::string& mountpoint, const EncryptionPolicy& policy);
 
+// Retrieves the key from the named directory, or generates it if it doesn't
+// exist.  In most cases |keepOld| must be false; see retrieveKey() for details.
 bool retrieveOrGenerateKey(const std::string& key_path, const std::string& tmp_path,
                            const KeyAuthentication& key_authentication, const KeyGeneration& gen,
-                           KeyBuffer* key, bool keepOld = true);
+                           KeyBuffer* key, bool keepOld);
 
 // Re-installs a file-based encryption key of fscrypt-provisioning type from the
 // global session keyring back into fs keyring of the mountpoint.
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index a543573..585d2d5 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -1066,8 +1066,42 @@
                              int32_t ownerGid, std::string* outVolId) {
     int id = mNextObbId++;
 
+    std::string lowerSourcePath;
+
+    // Convert to lower filesystem path
+    if (StartsWith(sourcePath, "/storage/")) {
+        auto filter_fn = [&](const VolumeBase& vol) {
+            if (vol.getState() != VolumeBase::State::kMounted) {
+                // The volume must be mounted
+                return false;
+            }
+            if ((vol.getMountFlags() & VolumeBase::MountFlags::kVisible) == 0) {
+                // and visible
+                return false;
+            }
+            if (vol.getInternalPath().empty()) {
+                return false;
+            }
+            if (!sourcePath.empty() && StartsWith(sourcePath, vol.getPath())) {
+                return true;
+            }
+
+            return false;
+        };
+        auto volume = findVolumeWithFilter(filter_fn);
+        if (volume == nullptr) {
+            LOG(ERROR) << "Failed to find mounted volume for " << sourcePath;
+            return -EINVAL;
+        } else {
+            lowerSourcePath =
+                    volume->getInternalPath() + sourcePath.substr(volume->getPath().length());
+        }
+    } else {
+        lowerSourcePath = sourcePath;
+    }
+
     auto vol = std::shared_ptr<android::vold::VolumeBase>(
-        new android::vold::ObbVolume(id, sourcePath, sourceKey, ownerGid));
+            new android::vold::ObbVolume(id, lowerSourcePath, sourceKey, ownerGid));
     vol->create();
 
     mObbVolumes.push_back(vol);