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
This commit is contained in:
Jeff Sharkey 2017-12-14 22:15:20 -07:00
parent 0667b7e7dd
commit 401b260351
5 changed files with 87 additions and 29 deletions

View file

@ -285,6 +285,13 @@ binder::Status VoldNativeService::onUserStopped(int32_t userId) {
return translate(VolumeManager::Instance()->onUserStopped(userId)); return translate(VolumeManager::Instance()->onUserStopped(userId));
} }
binder::Status VoldNativeService::onSecureKeyguardStateChanged(bool isShowing) {
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_LOCK;
return translate(VolumeManager::Instance()->onSecureKeyguardStateChanged(isShowing));
}
binder::Status VoldNativeService::partition(const std::string& diskId, int32_t partitionType, binder::Status VoldNativeService::partition(const std::string& diskId, int32_t partitionType,
int32_t ratio) { int32_t ratio) {
ENFORCE_UID(AID_SYSTEM); ENFORCE_UID(AID_SYSTEM);

View file

@ -43,6 +43,8 @@ public:
binder::Status onUserStarted(int32_t userId); binder::Status onUserStarted(int32_t userId);
binder::Status onUserStopped(int32_t userId); binder::Status onUserStopped(int32_t userId);
binder::Status onSecureKeyguardStateChanged(bool isShowing);
binder::Status partition(const std::string& diskId, int32_t partitionType, int32_t ratio); binder::Status partition(const std::string& diskId, int32_t partitionType, int32_t ratio);
binder::Status forgetPartition(const std::string& partGuid, const std::string& fsUuid); binder::Status forgetPartition(const std::string& partGuid, const std::string& fsUuid);

View file

@ -90,6 +90,9 @@ VolumeManager *VolumeManager::Instance() {
VolumeManager::VolumeManager() { VolumeManager::VolumeManager() {
mDebug = false; mDebug = false;
mNextObbId = 0; mNextObbId = 0;
// For security reasons, assume that a secure keyguard is
// showing until we hear otherwise
mSecureKeyguardShowing = true;
} }
VolumeManager::~VolumeManager() { VolumeManager::~VolumeManager() {
@ -116,23 +119,13 @@ int VolumeManager::updateVirtualDisk() {
auto disk = new android::vold::Disk("virtual", buf.st_rdev, "virtual", auto disk = new android::vold::Disk("virtual", buf.st_rdev, "virtual",
android::vold::Disk::Flags::kAdoptable | android::vold::Disk::Flags::kSd); android::vold::Disk::Flags::kAdoptable | android::vold::Disk::Flags::kSd);
disk->create();
mVirtualDisk = std::shared_ptr<android::vold::Disk>(disk); mVirtualDisk = std::shared_ptr<android::vold::Disk>(disk);
mDisks.push_back(mVirtualDisk); handleDiskAdded(mVirtualDisk);
} }
} else { } else {
if (mVirtualDisk != nullptr) { if (mVirtualDisk != nullptr) {
dev_t device = mVirtualDisk->getDevice(); dev_t device = mVirtualDisk->getDevice();
handleDiskRemoved(device);
auto i = mDisks.begin();
while (i != mDisks.end()) {
if ((*i)->getDevice() == device) {
(*i)->destroy();
i = mDisks.erase(i);
} else {
++i;
}
}
Loop::destroyByDevice(mVirtualDiskPath.c_str()); Loop::destroyByDevice(mVirtualDiskPath.c_str());
mVirtualDisk = nullptr; mVirtualDisk = nullptr;
@ -217,8 +210,7 @@ void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
auto disk = new android::vold::Disk(eventPath, device, auto disk = new android::vold::Disk(eventPath, device,
source->getNickname(), flags); source->getNickname(), flags);
disk->create(); handleDiskAdded(std::shared_ptr<android::vold::Disk>(disk));
mDisks.push_back(std::shared_ptr<android::vold::Disk>(disk));
break; break;
} }
} }
@ -226,15 +218,46 @@ void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
} }
case NetlinkEvent::Action::kChange: { case NetlinkEvent::Action::kChange: {
LOG(DEBUG) << "Disk at " << major << ":" << minor << " changed"; LOG(DEBUG) << "Disk at " << major << ":" << minor << " changed";
handleDiskChanged(device);
break;
}
case NetlinkEvent::Action::kRemove: {
handleDiskRemoved(device);
break;
}
default: {
LOG(WARNING) << "Unexpected block event action " << (int) evt->getAction();
break;
}
}
}
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) { for (const auto& disk : mDisks) {
if (disk->getDevice() == device) { if (disk->getDevice() == device) {
disk->readMetadata(); disk->readMetadata();
disk->readPartitions(); disk->readPartitions();
} }
} }
break;
} // For security reasons, we ignore all pending disks, since
case NetlinkEvent::Action::kRemove: { // we'll scan them once the device is unlocked
}
void VolumeManager::handleDiskRemoved(dev_t device) {
auto i = mDisks.begin(); auto i = mDisks.begin();
while (i != mDisks.end()) { while (i != mDisks.end()) {
if ((*i)->getDevice() == device) { if ((*i)->getDevice() == device) {
@ -244,11 +267,12 @@ void VolumeManager::handleBlockEvent(NetlinkEvent *evt) {
++i; ++i;
} }
} }
break; auto j = mPendingDisks.begin();
} while (j != mPendingDisks.end()) {
default: { if ((*j)->getDevice() == device) {
LOG(WARNING) << "Unexpected block event action " << (int) evt->getAction(); j = mPendingDisks.erase(j);
break; } else {
++j;
} }
} }
} }
@ -367,6 +391,20 @@ int VolumeManager::onUserStopped(userid_t userId) {
return 0; 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) { int VolumeManager::setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol) {
mPrimary = vol; mPrimary = vol;
for (userid_t userId : mStartedUsers) { for (userid_t userId : mStartedUsers) {
@ -554,6 +592,7 @@ int VolumeManager::shutdown() {
disk->destroy(); disk->destroy();
} }
mDisks.clear(); mDisks.clear();
mPendingDisks.clear();
android::vold::sSleepOnUnmount = true; android::vold::sSleepOnUnmount = true;
return 0; return 0;
} }

View file

@ -94,6 +94,8 @@ public:
int onUserStarted(userid_t userId); int onUserStarted(userid_t userId);
int onUserStopped(userid_t userId); int onUserStopped(userid_t userId);
int onSecureKeyguardStateChanged(bool isShowing);
int setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol); int setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol);
int remountUid(uid_t uid, const std::string& mode); int remountUid(uid_t uid, const std::string& mode);
@ -132,6 +134,10 @@ private:
int linkPrimary(userid_t userId); int linkPrimary(userid_t userId);
void handleDiskAdded(const std::shared_ptr<android::vold::Disk>& disk);
void handleDiskChanged(dev_t device);
void handleDiskRemoved(dev_t device);
std::mutex mLock; std::mutex mLock;
std::mutex mCryptLock; std::mutex mCryptLock;
@ -139,6 +145,7 @@ private:
std::list<std::shared_ptr<DiskSource>> mDiskSources; std::list<std::shared_ptr<DiskSource>> mDiskSources;
std::list<std::shared_ptr<android::vold::Disk>> mDisks; std::list<std::shared_ptr<android::vold::Disk>> mDisks;
std::list<std::shared_ptr<android::vold::Disk>> mPendingDisks;
std::list<std::shared_ptr<android::vold::VolumeBase>> mObbVolumes; std::list<std::shared_ptr<android::vold::VolumeBase>> mObbVolumes;
std::unordered_map<userid_t, int> mAddedUsers; std::unordered_map<userid_t, int> mAddedUsers;
@ -150,6 +157,7 @@ private:
std::shared_ptr<android::vold::VolumeBase> mPrimary; std::shared_ptr<android::vold::VolumeBase> mPrimary;
int mNextObbId; int mNextObbId;
bool mSecureKeyguardShowing;
}; };
#endif #endif

View file

@ -33,6 +33,8 @@ interface IVold {
void onUserStarted(int userId); void onUserStarted(int userId);
void onUserStopped(int userId); void onUserStopped(int userId);
void onSecureKeyguardStateChanged(boolean isShowing);
void partition(@utf8InCpp String diskId, int partitionType, int ratio); void partition(@utf8InCpp String diskId, int partitionType, int ratio);
void forgetPartition(@utf8InCpp String partGuid, @utf8InCpp String fsUuid); void forgetPartition(@utf8InCpp String partGuid, @utf8InCpp String fsUuid);