Progress towards FBE and adoptable storage.
Offer to adopt storage devices on FBE devices, but keep it guarded
behind a system property for now, since we still need to work out key
storage details.
When migrating shared storage, leave user-specific /data/media
directories in place, since they already have the needed crypto
policies defined.
Enable journaling, quotas, and encrypt options when formatting
newly adopted devices. installd already gracefully handles older
partitions without quota enabled.
Test: cts-tradefed run commandAndExit cts-dev --abi armeabi-v7a -m CtsAppSecurityHostTestCases -t android.appsecurity.cts.AdoptableHostTest
Bug: 62290006, 36757864, 29117062, 37395736
Bug: 29923055, 25861755, 30230655, 37436961
Change-Id: Ibbeb6ec9db2394a279bbac221a2b20711d65494e
diff --git a/Disk.cpp b/Disk.cpp
index b424aba..9c22400 100644
--- a/Disk.cpp
+++ b/Disk.cpp
@@ -24,6 +24,7 @@
#include "Ext4Crypt.h"
#include <android-base/file.h>
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <android-base/logging.h>
#include <diskconfig/diskconfig.h>
@@ -446,7 +447,8 @@
status_t Disk::partitionMixed(int8_t ratio) {
int res;
- if (e4crypt_is_native()) {
+ if (e4crypt_is_native()
+ && !android::base::GetBoolProperty("persist.sys.adoptable_fbe", false)) {
LOG(ERROR) << "Private volumes not yet supported on FBE devices";
return -EINVAL;
}
@@ -469,9 +471,14 @@
// We've had some success above, so generate both the private partition
// GUID and encryption key and persist them.
std::string partGuidRaw;
+ if (GenerateRandomUuid(partGuidRaw) != OK) {
+ LOG(ERROR) << "Failed to generate GUID";
+ return -EIO;
+ }
+
std::string keyRaw;
- if (ReadRandomBytes(16, partGuidRaw) || ReadRandomBytes(16, keyRaw)) {
- LOG(ERROR) << "Failed to generate GUID or key";
+ if (ReadRandomBytes(16, keyRaw) != OK) {
+ LOG(ERROR) << "Failed to generate key";
return -EIO;
}
diff --git a/MoveTask.cpp b/MoveTask.cpp
index ea64a1c..c565752 100644
--- a/MoveTask.cpp
+++ b/MoveTask.cpp
@@ -62,7 +62,8 @@
StringPrintf("%d", progress).c_str(), false);
}
-static status_t pushBackContents(const std::string& path, std::vector<std::string>& cmd) {
+static status_t pushBackContents(const std::string& path, std::vector<std::string>& cmd,
+ bool addWildcard) {
DIR* dir = opendir(path.c_str());
if (dir == NULL) {
return -1;
@@ -73,7 +74,11 @@
if ((!strcmp(ent->d_name, ".")) || (!strcmp(ent->d_name, ".."))) {
continue;
}
- cmd.push_back(StringPrintf("%s/%s", path.c_str(), ent->d_name));
+ if (addWildcard) {
+ cmd.push_back(StringPrintf("%s/%s/*", path.c_str(), ent->d_name));
+ } else {
+ cmd.push_back(StringPrintf("%s/%s", path.c_str(), ent->d_name));
+ }
found = true;
}
closedir(dir);
@@ -90,7 +95,7 @@
cmd.push_back(kRmPath);
cmd.push_back("-f"); /* force: remove without confirmation, no error if it doesn't exist */
cmd.push_back("-R"); /* recursive: remove directory contents */
- if (pushBackContents(path, cmd) != OK) {
+ if (pushBackContents(path, cmd, true) != OK) {
LOG(WARNING) << "No contents in " << path;
return OK;
}
@@ -140,7 +145,7 @@
cmd.push_back("-R"); /* recurse into subdirectories (DEST must be a directory) */
cmd.push_back("-P"); /* Do not follow symlinks [default] */
cmd.push_back("-d"); /* don't dereference symlinks */
- if (pushBackContents(fromPath, cmd) != OK) {
+ if (pushBackContents(fromPath, cmd, false) != OK) {
LOG(WARNING) << "No contents in " << fromPath;
return OK;
}
diff --git a/Utils.cpp b/Utils.cpp
index 529cfb2..9699777 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -372,6 +372,17 @@
}
}
+status_t GenerateRandomUuid(std::string& out) {
+ status_t res = ReadRandomBytes(16, out);
+ if (res == OK) {
+ out[6] &= 0x0f; /* clear version */
+ out[6] |= 0x40; /* set to version 4 */
+ out[8] &= 0x3f; /* clear variant */
+ out[8] |= 0x80; /* set to IETF variant */
+ }
+ return res;
+}
+
status_t HexToStr(const std::string& hex, std::string& str) {
str.clear();
bool even = true;
diff --git a/Utils.h b/Utils.h
index 813ffac..7272fe1 100644
--- a/Utils.h
+++ b/Utils.h
@@ -78,6 +78,7 @@
pid_t ForkExecvpAsync(const std::vector<std::string>& args);
status_t ReadRandomBytes(size_t bytes, std::string& out);
+status_t GenerateRandomUuid(std::string& out);
/* Converts hex string to raw bytes, ignoring [ :-] */
status_t HexToStr(const std::string& hex, std::string& str);
diff --git a/fs/Ext4.cpp b/fs/Ext4.cpp
index 0670bb5..041ce90 100644
--- a/fs/Ext4.cpp
+++ b/fs/Ext4.cpp
@@ -45,6 +45,7 @@
#include <selinux/selinux.h>
#include "Ext4.h"
+#include "Ext4Crypt.h"
#include "Utils.h"
#include "VoldUtil.h"
@@ -180,8 +181,13 @@
cmd.push_back("-M");
cmd.push_back(target);
+ std::string options("has_journal,quota");
+ if (e4crypt_is_native()) {
+ options += ",encrypt";
+ }
+
cmd.push_back("-O");
- cmd.push_back("^has_journal");
+ cmd.push_back(options);
cmd.push_back(source);