Delay touching disks when secure keyguard showing.

We've tried our best to protect against malicious storage devices
with limited SELinux domains, but let's be even more paranoid and
refuse to look at disks inserted while a secure keyguard is
showing.  We'll gladly scan them right away once the user confirms
their credentials.

Test: builds, boots, manual testing
Bug: 68054513
Change-Id: I37fd6c25bbd6631fa4ba3f84e19384d746a22498
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index e078c0d..0936ed0 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -90,6 +90,9 @@
 VolumeManager::VolumeManager() {
     mDebug = false;
     mNextObbId = 0;
+    // For security reasons, assume that a secure keyguard is
+    // showing until we hear otherwise
+    mSecureKeyguardShowing = true;
 }
 
 VolumeManager::~VolumeManager() {
@@ -116,23 +119,13 @@
 
             auto disk = new android::vold::Disk("virtual", buf.st_rdev, "virtual",
                     android::vold::Disk::Flags::kAdoptable | android::vold::Disk::Flags::kSd);
-            disk->create();
             mVirtualDisk = std::shared_ptr<android::vold::Disk>(disk);
-            mDisks.push_back(mVirtualDisk);
+            handleDiskAdded(mVirtualDisk);
         }
     } else {
         if (mVirtualDisk != nullptr) {
             dev_t device = mVirtualDisk->getDevice();
-
-            auto i = mDisks.begin();
-            while (i != mDisks.end()) {
-                if ((*i)->getDevice() == device) {
-                    (*i)->destroy();
-                    i = mDisks.erase(i);
-                } else {
-                    ++i;
-                }
-            }
+            handleDiskRemoved(device);
 
             Loop::destroyByDevice(mVirtualDiskPath.c_str());
             mVirtualDisk = nullptr;
@@ -217,8 +210,7 @@
 
                 auto disk = new android::vold::Disk(eventPath, device,
                         source->getNickname(), flags);
-                disk->create();
-                mDisks.push_back(std::shared_ptr<android::vold::Disk>(disk));
+                handleDiskAdded(std::shared_ptr<android::vold::Disk>(disk));
                 break;
             }
         }
@@ -226,24 +218,11 @@
     }
     case NetlinkEvent::Action::kChange: {
         LOG(DEBUG) << "Disk at " << major << ":" << minor << " changed";
-        for (const auto& disk : mDisks) {
-            if (disk->getDevice() == device) {
-                disk->readMetadata();
-                disk->readPartitions();
-            }
-        }
+        handleDiskChanged(device);
         break;
     }
     case NetlinkEvent::Action::kRemove: {
-        auto i = mDisks.begin();
-        while (i != mDisks.end()) {
-            if ((*i)->getDevice() == device) {
-                (*i)->destroy();
-                i = mDisks.erase(i);
-            } else {
-                ++i;
-            }
-        }
+        handleDiskRemoved(device);
         break;
     }
     default: {
@@ -253,6 +232,51 @@
     }
 }
 
+void VolumeManager::handleDiskAdded(const std::shared_ptr<android::vold::Disk>& disk) {
+    // For security reasons, if secure keyguard is showing, wait
+    // until the user unlocks the device to actually touch it
+    if (mSecureKeyguardShowing) {
+        LOG(INFO) << "Found disk at " << disk->getEventPath()
+                << " but delaying scan due to secure keyguard";
+        mPendingDisks.push_back(disk);
+    } else {
+        disk->create();
+        mDisks.push_back(disk);
+    }
+}
+
+void VolumeManager::handleDiskChanged(dev_t device) {
+    for (const auto& disk : mDisks) {
+        if (disk->getDevice() == device) {
+            disk->readMetadata();
+            disk->readPartitions();
+        }
+    }
+
+    // For security reasons, we ignore all pending disks, since
+    // we'll scan them once the device is unlocked
+}
+
+void VolumeManager::handleDiskRemoved(dev_t device) {
+    auto i = mDisks.begin();
+    while (i != mDisks.end()) {
+        if ((*i)->getDevice() == device) {
+            (*i)->destroy();
+            i = mDisks.erase(i);
+        } else {
+            ++i;
+        }
+    }
+    auto j = mPendingDisks.begin();
+    while (j != mPendingDisks.end()) {
+        if ((*j)->getDevice() == device) {
+            j = mPendingDisks.erase(j);
+        } else {
+            ++j;
+        }
+    }
+}
+
 void VolumeManager::addDiskSource(const std::shared_ptr<DiskSource>& diskSource) {
     std::lock_guard<std::mutex> lock(mLock);
     mDiskSources.push_back(diskSource);
@@ -367,6 +391,20 @@
     return 0;
 }
 
+int VolumeManager::onSecureKeyguardStateChanged(bool isShowing) {
+    mSecureKeyguardShowing = isShowing;
+    if (!mSecureKeyguardShowing) {
+        // Now that secure keyguard has been dismissed, process
+        // any pending disks
+        for (const auto& disk : mPendingDisks) {
+            disk->create();
+            mDisks.push_back(disk);
+        }
+        mPendingDisks.clear();
+    }
+    return 0;
+}
+
 int VolumeManager::setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol) {
     mPrimary = vol;
     for (userid_t userId : mStartedUsers) {
@@ -554,6 +592,7 @@
         disk->destroy();
     }
     mDisks.clear();
+    mPendingDisks.clear();
     android::vold::sSleepOnUnmount = true;
     return 0;
 }