Merge QP1A.190107.001
Change-Id: If019c75ac81f35d72fc2aab573557e325e2dfcb0
diff --git a/Android.bp b/Android.bp
index f8f8d5a..f2012ef 100644
--- a/Android.bp
+++ b/Android.bp
@@ -144,7 +144,6 @@
"arc_services_aidl",
"libarcappfuse",
"libarcobbvolume",
- "libparcelfiledescriptor",
],
},
debuggable: {
@@ -179,7 +178,6 @@
"arc_services_aidl",
"libarcappfuse",
"libarcobbvolume",
- "libparcelfiledescriptor",
],
},
device_support_hwfde: {
diff --git a/Checkpoint.cpp b/Checkpoint.cpp
index e238acf..28855e6 100644
--- a/Checkpoint.cpp
+++ b/Checkpoint.cpp
@@ -26,6 +26,7 @@
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/parseint.h>
+#include <android-base/properties.h>
#include <android-base/unique_fd.h>
#include <android/hardware/boot/1.0/IBootControl.h>
#include <cutils/android_reboot.h>
@@ -36,6 +37,7 @@
#include <sys/mount.h>
#include <sys/stat.h>
+using android::base::SetProperty;
using android::binder::Status;
using android::hardware::hidl_string;
using android::hardware::boot::V1_0::BoolResult;
@@ -81,8 +83,15 @@
return Status::ok();
}
+namespace {
+
+bool isCheckpointing = false;
+}
+
Status cp_commitChanges() {
- if (!cp_needsCheckpoint()) return Status::ok();
+ if (!isCheckpointing) {
+ return Status::ok();
+ }
// Must take action for list of mounted checkpointed things here
// To do this, we walk the list of mounted file systems.
// But we also need to get the matching fstab entries to see
@@ -115,6 +124,8 @@
return Status::fromExceptionCode(EINVAL, "Failed to set bow state");
}
}
+ SetProperty("vold.checkpoint_committed", "1");
+ isCheckpointing = false;
if (!android::base::RemoveFileIfExists(kMetadataCPFile, &err_str))
return Status::fromExceptionCode(errno, err_str.c_str());
return Status::ok();
@@ -152,10 +163,16 @@
std::string content;
sp<IBootControl> module = IBootControl::getService();
- if (module && module->isSlotMarkedSuccessful(module->getCurrentSlot()) == BoolResult::FALSE)
+ if (module && module->isSlotMarkedSuccessful(module->getCurrentSlot()) == BoolResult::FALSE) {
+ isCheckpointing = true;
return true;
+ }
ret = android::base::ReadFileToString(kMetadataCPFile, &content);
- if (ret) return content != "0";
+ if (ret) {
+ ret = content != "0";
+ isCheckpointing = ret;
+ return ret;
+ }
return false;
}
@@ -279,9 +296,9 @@
PLOG(ERROR) << "Cannot open " << blockDevice;
return Status::fromExceptionCode(errno, ("Cannot open " + blockDevice).c_str());
}
- char buffer[kBlockSize];
- device.read(buffer, kBlockSize);
- log_sector& ls = *(log_sector*)buffer;
+ alignas(alignof(log_sector)) char ls_buffer[kBlockSize];
+ device.read(ls_buffer, kBlockSize);
+ log_sector& ls = *reinterpret_cast<log_sector*>(ls_buffer);
if (ls.magic != kMagic) {
LOG(ERROR) << "No magic";
return Status::fromExceptionCode(EINVAL, "No magic");
@@ -290,10 +307,9 @@
LOG(INFO) << "Restoring " << ls.sequence << " log sectors";
for (int sequence = ls.sequence; sequence >= 0; sequence--) {
- char buffer[kBlockSize];
device.seekg(0);
- device.read(buffer, kBlockSize);
- log_sector& ls = *(log_sector*)buffer;
+ device.read(ls_buffer, kBlockSize);
+ ls = *reinterpret_cast<log_sector*>(ls_buffer);
if (ls.magic != kMagic) {
LOG(ERROR) << "No magic!";
return Status::fromExceptionCode(EINVAL, "No magic");
diff --git a/EncryptInplace.cpp b/EncryptInplace.cpp
index 63a8e15..cfad84e 100644
--- a/EncryptInplace.cpp
+++ b/EncryptInplace.cpp
@@ -596,11 +596,11 @@
for (i /= CRYPT_SECTORS_PER_BUFSIZE; i < numblocks; i++) {
new_pct = (i + blocks_already_done) / one_pct;
if (set_progress_properties && new_pct > cur_pct) {
- char buf[8];
+ char property_buf[8];
cur_pct = new_pct;
- snprintf(buf, sizeof(buf), "%" PRId64, cur_pct);
- android::base::SetProperty("vold.encrypt_progress", buf);
+ snprintf(property_buf, sizeof(property_buf), "%" PRId64, cur_pct);
+ android::base::SetProperty("vold.encrypt_progress", property_buf);
}
if (unix_read(realfd, buf, CRYPT_INPLACE_BUFSIZE) <= 0) {
PLOG(ERROR) << "Error reading real_blkdev " << real_blkdev << " for inplace encrypt";
diff --git a/KeyStorage.cpp b/KeyStorage.cpp
index f1a1167..97ee468 100644
--- a/KeyStorage.cpp
+++ b/KeyStorage.cpp
@@ -244,7 +244,7 @@
km::KeyPurpose purpose, const km::AuthorizationSet& keyParams,
const km::AuthorizationSet& opParams,
const km::HardwareAuthToken& authToken,
- km::AuthorizationSet* outParams) {
+ km::AuthorizationSet* outParams, bool keepOld) {
auto kmKeyPath = dir + "/" + kFn_keymaster_key_blob;
std::string kmKey;
if (!readFileToString(kmKeyPath, &kmKey)) return KeymasterOperation();
@@ -261,12 +261,14 @@
if (!keymaster.upgradeKey(kmKey, keyParams, &newKey)) return KeymasterOperation();
auto newKeyPath = dir + "/" + kFn_keymaster_key_blob_upgraded;
if (!writeStringToFile(newKey, newKeyPath)) return KeymasterOperation();
- if (rename(newKeyPath.c_str(), kmKeyPath.c_str()) != 0) {
- PLOG(ERROR) << "Unable to move upgraded key to location: " << kmKeyPath;
- return KeymasterOperation();
- }
- if (!keymaster.deleteKey(kmKey)) {
- LOG(ERROR) << "Key deletion failed during upgrade, continuing anyway: " << dir;
+ if (!keepOld) {
+ if (rename(newKeyPath.c_str(), kmKeyPath.c_str()) != 0) {
+ PLOG(ERROR) << "Unable to move upgraded key to location: " << kmKeyPath;
+ return KeymasterOperation();
+ }
+ if (!keymaster.deleteKey(kmKey)) {
+ LOG(ERROR) << "Key deletion failed during upgrade, continuing anyway: " << dir;
+ }
}
kmKey = newKey;
LOG(INFO) << "Key upgraded: " << dir;
@@ -275,12 +277,12 @@
static bool encryptWithKeymasterKey(Keymaster& keymaster, const std::string& dir,
const km::AuthorizationSet& keyParams,
- const km::HardwareAuthToken& authToken,
- const KeyBuffer& message, std::string* ciphertext) {
+ const km::HardwareAuthToken& authToken, const KeyBuffer& message,
+ std::string* ciphertext, bool keepOld) {
km::AuthorizationSet opParams;
km::AuthorizationSet outParams;
- auto opHandle =
- begin(keymaster, dir, km::KeyPurpose::ENCRYPT, keyParams, opParams, authToken, &outParams);
+ auto opHandle = begin(keymaster, dir, km::KeyPurpose::ENCRYPT, keyParams, opParams, authToken,
+ &outParams, keepOld);
if (!opHandle) return false;
auto nonceBlob = outParams.GetTagValue(km::TAG_NONCE);
if (!nonceBlob.isOk()) {
@@ -304,13 +306,14 @@
static bool decryptWithKeymasterKey(Keymaster& keymaster, const std::string& dir,
const km::AuthorizationSet& keyParams,
const km::HardwareAuthToken& authToken,
- const std::string& ciphertext, KeyBuffer* message) {
+ const std::string& ciphertext, KeyBuffer* message,
+ bool keepOld) {
auto nonce = ciphertext.substr(0, GCM_NONCE_BYTES);
auto bodyAndMac = ciphertext.substr(GCM_NONCE_BYTES);
auto opParams = km::AuthorizationSetBuilder().Authorization(km::TAG_NONCE,
km::support::blob2hidlVec(nonce));
- auto opHandle =
- begin(keymaster, dir, km::KeyPurpose::DECRYPT, keyParams, opParams, authToken, nullptr);
+ auto opHandle = begin(keymaster, dir, km::KeyPurpose::DECRYPT, keyParams, opParams, authToken,
+ nullptr, keepOld);
if (!opHandle) return false;
if (!opHandle.updateCompletely(bodyAndMac, message)) return false;
if (!opHandle.finish(nullptr)) return false;
@@ -516,7 +519,8 @@
km::AuthorizationSet keyParams;
km::HardwareAuthToken authToken;
std::tie(keyParams, authToken) = beginParams(auth, appId);
- if (!encryptWithKeymasterKey(keymaster, dir, keyParams, authToken, key, &encryptedKey))
+ if (!encryptWithKeymasterKey(keymaster, dir, keyParams, authToken, key, &encryptedKey,
+ false))
return false;
} else {
if (!encryptWithoutKeymaster(appId, key, &encryptedKey)) return false;
@@ -544,7 +548,8 @@
return true;
}
-bool retrieveKey(const std::string& dir, const KeyAuthentication& auth, KeyBuffer* key) {
+bool retrieveKey(const std::string& dir, const KeyAuthentication& auth, KeyBuffer* key,
+ bool keepOld) {
std::string version;
if (!readFileToString(dir + "/" + kFn_version, &version)) return false;
if (version != kCurrentVersion) {
@@ -569,7 +574,8 @@
km::AuthorizationSet keyParams;
km::HardwareAuthToken authToken;
std::tie(keyParams, authToken) = beginParams(auth, appId);
- if (!decryptWithKeymasterKey(keymaster, dir, keyParams, authToken, encryptedMessage, key))
+ if (!decryptWithKeymasterKey(keymaster, dir, keyParams, authToken, encryptedMessage, key,
+ keepOld))
return false;
} else {
if (!decryptWithoutKeymaster(appId, encryptedMessage, key)) return false;
diff --git a/KeyStorage.h b/KeyStorage.h
index d452589..72ddfc4 100644
--- a/KeyStorage.h
+++ b/KeyStorage.h
@@ -32,7 +32,7 @@
// If only "secret" is nonempty, it is used to decrypt in a non-Keymaster process.
class KeyAuthentication {
public:
- KeyAuthentication(std::string t, std::string s) : token{t}, secret{s} {};
+ KeyAuthentication(const std::string& t, const std::string& s) : token{t}, secret{s} {};
bool usesKeymaster() const { return !token.empty() || secret.empty(); };
@@ -68,7 +68,8 @@
const KeyAuthentication& auth, const KeyBuffer& key);
// Retrieve the key from the named directory.
-bool retrieveKey(const std::string& dir, const KeyAuthentication& auth, KeyBuffer* key);
+bool retrieveKey(const std::string& dir, const KeyAuthentication& auth, KeyBuffer* key,
+ bool keepOld = false);
// Securely destroy the key stored in the named directory and delete the directory.
bool destroyKey(const std::string& dir);
diff --git a/KeyUtil.cpp b/KeyUtil.cpp
index 1f35f3a..b1f4c3d 100644
--- a/KeyUtil.cpp
+++ b/KeyUtil.cpp
@@ -194,10 +194,10 @@
}
bool retrieveKey(bool create_if_absent, const std::string& key_path, const std::string& tmp_path,
- KeyBuffer* key) {
+ KeyBuffer* key, bool keepOld) {
if (pathExists(key_path)) {
LOG(DEBUG) << "Key exists, using: " << key_path;
- if (!retrieveKey(key_path, kEmptyAuthentication, key)) return false;
+ if (!retrieveKey(key_path, kEmptyAuthentication, key, keepOld)) return false;
} else {
if (!create_if_absent) {
LOG(ERROR) << "No key found in " << key_path;
diff --git a/KeyUtil.h b/KeyUtil.h
index f0b2856..2839b4a 100644
--- a/KeyUtil.h
+++ b/KeyUtil.h
@@ -34,7 +34,7 @@
const std::string& key_path, const std::string& tmp_path,
std::string* key_ref, bool wrapped_key_supported);
bool retrieveKey(bool create_if_absent, const std::string& key_path, const std::string& tmp_path,
- KeyBuffer* key);
+ KeyBuffer* key, bool keepOld = true);
} // namespace vold
} // namespace android
diff --git a/Keymaster.h b/Keymaster.h
index c0ec4d3..a75fd56 100644
--- a/Keymaster.h
+++ b/Keymaster.h
@@ -46,8 +46,8 @@
~KeymasterOperation();
// Is this instance valid? This is false if creation fails, and becomes
// false on finish or if an update fails.
- explicit operator bool() { return mError == km::ErrorCode::OK; }
- km::ErrorCode errorCode() { return mError; }
+ explicit operator bool() const { return mError == km::ErrorCode::OK; }
+ km::ErrorCode errorCode() const { return mError; }
// Call "update" repeatedly until all of the input is consumed, and
// concatenate the output. Return true on success.
template <class TI, class TO>
diff --git a/MetadataCrypt.cpp b/MetadataCrypt.cpp
index e156424..5c8a075 100644
--- a/MetadataCrypt.cpp
+++ b/MetadataCrypt.cpp
@@ -30,6 +30,7 @@
#include <linux/dm-ioctl.h>
+#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/properties.h>
#include <android-base/unique_fd.h>
@@ -40,6 +41,7 @@
#include "EncryptInplace.h"
#include "KeyStorage.h"
#include "KeyUtil.h"
+#include "Keymaster.h"
#include "Utils.h"
#include "VoldUtil.h"
#include "secontext.h"
@@ -52,6 +54,9 @@
static const std::string kDmNameUserdata = "userdata";
+static const char* kFn_keymaster_key_blob = "keymaster_key_blob";
+static const char* kFn_keymaster_key_blob_upgraded = "keymaster_key_blob_upgraded";
+
static bool mount_via_fs_mgr(const char* mount_point, const char* blk_device) {
// fs_mgr_do_mount runs fsck. Use setexeccon to run trusted
// partitions in the fsck domain.
@@ -74,12 +79,41 @@
return true;
}
+namespace android {
+namespace vold {
+
+// Note: It is possible to orphan a key if it is removed before deleting
+// Update this once keymaster APIs change, and we have a proper commit.
+static void commit_key(const std::string& dir) {
+ while (!android::base::WaitForProperty("vold.checkpoint_committed", "1")) {
+ LOG(ERROR) << "Wait for boot timed out";
+ }
+ Keymaster keymaster;
+ auto keyPath = dir + "/" + kFn_keymaster_key_blob;
+ auto newKeyPath = dir + "/" + kFn_keymaster_key_blob_upgraded;
+ std::string key;
+
+ if (!android::base::ReadFileToString(keyPath, &key)) {
+ LOG(ERROR) << "Failed to read old key: " << dir;
+ return;
+ }
+ if (rename(newKeyPath.c_str(), keyPath.c_str()) != 0) {
+ PLOG(ERROR) << "Unable to move upgraded key to location: " << keyPath;
+ return;
+ }
+ if (!keymaster.deleteKey(key)) {
+ LOG(ERROR) << "Key deletion failed during upgrade, continuing anyway: " << dir;
+ }
+ LOG(INFO) << "Old Key deleted: " << dir;
+}
+
static bool read_key(struct fstab_rec const* data_rec, bool create_if_absent, KeyBuffer* key) {
if (!data_rec->key_dir) {
LOG(ERROR) << "Failed to get key_dir";
return false;
}
std::string key_dir = data_rec->key_dir;
+ std::string sKey;
auto dir = key_dir + "/key";
LOG(DEBUG) << "key_dir/key: " << dir;
if (fs_mkdirs(dir.c_str(), 0700)) {
@@ -87,10 +121,30 @@
return false;
}
auto temp = key_dir + "/tmp";
- if (!android::vold::retrieveKey(create_if_absent, dir, temp, key)) return false;
+ auto newKeyPath = dir + "/" + kFn_keymaster_key_blob_upgraded;
+ /* If we have a leftover upgraded key, delete it.
+ * We either failed an update and must return to the old key,
+ * or we rebooted before commiting the keys in a freak accident.
+ * Either way, we can re-upgrade the key if we need to.
+ */
+ Keymaster keymaster;
+ if (pathExists(newKeyPath)) {
+ if (!android::base::ReadFileToString(newKeyPath, &sKey))
+ LOG(ERROR) << "Failed to read old key: " << dir;
+ else if (!keymaster.deleteKey(sKey))
+ LOG(ERROR) << "Old key deletion failed, continuing anyway: " << dir;
+ else
+ unlink(newKeyPath.c_str());
+ }
+ bool needs_cp = cp_needsCheckpoint();
+ if (!android::vold::retrieveKey(create_if_absent, dir, temp, key, needs_cp)) return false;
+ if (needs_cp && pathExists(newKeyPath)) std::thread(commit_key, dir).detach();
return true;
}
+} // namespace vold
+} // namespace android
+
static KeyBuffer default_key_params(const std::string& real_blkdev, const KeyBuffer& key) {
KeyBuffer hex_key;
if (android::vold::StrToHex(key, hex_key) != android::OK) {
diff --git a/Utils.cpp b/Utils.cpp
index 57417d6..4ec2679 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -236,7 +236,7 @@
cmd.push_back(path);
std::vector<std::string> output;
- status_t res = ForkExecvp(cmd, output, untrusted ? sBlkidUntrustedContext : sBlkidContext);
+ status_t res = ForkExecvp(cmd, &output, untrusted ? sBlkidUntrustedContext : sBlkidContext);
if (res != OK) {
LOG(WARNING) << "blkid failed to identify " << path;
return res;
@@ -262,101 +262,92 @@
return readMetadata(path, fsType, fsUuid, fsLabel, true);
}
-status_t ForkExecvp(const std::vector<std::string>& args) {
- return ForkExecvp(args, nullptr);
-}
-
-status_t ForkExecvp(const std::vector<std::string>& args, security_context_t context) {
- std::lock_guard<std::mutex> lock(kSecurityLock);
- size_t argc = args.size();
- char** argv = (char**)calloc(argc, sizeof(char*));
- for (size_t i = 0; i < argc; i++) {
- argv[i] = (char*)args[i].c_str();
- if (i == 0) {
- LOG(DEBUG) << args[i];
+static std::vector<const char*> ConvertToArgv(const std::vector<std::string>& args) {
+ std::vector<const char*> argv;
+ argv.reserve(args.size() + 1);
+ for (const auto& arg : args) {
+ if (argv.empty()) {
+ LOG(DEBUG) << arg;
} else {
- LOG(DEBUG) << " " << args[i];
+ LOG(DEBUG) << " " << arg;
}
+ argv.emplace_back(arg.data());
}
-
- if (context) {
- if (setexeccon(context)) {
- LOG(ERROR) << "Failed to setexeccon";
- abort();
- }
- }
- status_t res = android_fork_execvp(argc, argv, NULL, false, true);
- if (context) {
- if (setexeccon(nullptr)) {
- LOG(ERROR) << "Failed to setexeccon";
- abort();
- }
- }
-
- free(argv);
- return res;
+ argv.emplace_back(nullptr);
+ return argv;
}
-status_t ForkExecvp(const std::vector<std::string>& args, std::vector<std::string>& output) {
- return ForkExecvp(args, output, nullptr);
-}
-
-status_t ForkExecvp(const std::vector<std::string>& args, std::vector<std::string>& output,
- security_context_t context) {
- std::lock_guard<std::mutex> lock(kSecurityLock);
- std::string cmd;
- for (size_t i = 0; i < args.size(); i++) {
- cmd += args[i] + " ";
- if (i == 0) {
- LOG(DEBUG) << args[i];
- } else {
- LOG(DEBUG) << " " << args[i];
- }
- }
- output.clear();
-
- if (context) {
- if (setexeccon(context)) {
- LOG(ERROR) << "Failed to setexeccon";
- abort();
- }
- }
- FILE* fp = popen(cmd.c_str(), "r"); // NOLINT
- if (context) {
- if (setexeccon(nullptr)) {
- LOG(ERROR) << "Failed to setexeccon";
- abort();
- }
- }
-
+static status_t ReadLinesFromFdAndLog(std::vector<std::string>* output,
+ android::base::unique_fd ufd) {
+ std::unique_ptr<FILE, int (*)(FILE*)> fp(android::base::Fdopen(std::move(ufd), "r"), fclose);
if (!fp) {
- PLOG(ERROR) << "Failed to popen " << cmd;
+ PLOG(ERROR) << "fdopen in ReadLinesFromFdAndLog";
return -errno;
}
+ if (output) output->clear();
char line[1024];
- while (fgets(line, sizeof(line), fp) != nullptr) {
+ while (fgets(line, sizeof(line), fp.get()) != nullptr) {
LOG(DEBUG) << line;
- output.push_back(std::string(line));
+ if (output) output->emplace_back(line);
}
- if (pclose(fp) != 0) {
- PLOG(ERROR) << "Failed to pclose " << cmd;
+ return OK;
+}
+
+status_t ForkExecvp(const std::vector<std::string>& args, std::vector<std::string>* output,
+ security_context_t context) {
+ auto argv = ConvertToArgv(args);
+
+ android::base::unique_fd pipe_read, pipe_write;
+ if (!android::base::Pipe(&pipe_read, &pipe_write)) {
+ PLOG(ERROR) << "Pipe in ForkExecvp";
return -errno;
}
+ pid_t pid = fork();
+ if (pid == 0) {
+ if (context) {
+ if (setexeccon(context)) {
+ LOG(ERROR) << "Failed to setexeccon in ForkExecvp";
+ abort();
+ }
+ }
+ pipe_read.reset();
+ if (dup2(pipe_write.get(), STDOUT_FILENO) == -1) {
+ PLOG(ERROR) << "dup2 in ForkExecvp";
+ _exit(EXIT_FAILURE);
+ }
+ pipe_write.reset();
+ execvp(argv[0], const_cast<char**>(argv.data()));
+ PLOG(ERROR) << "exec in ForkExecvp";
+ _exit(EXIT_FAILURE);
+ }
+ if (pid == -1) {
+ PLOG(ERROR) << "fork in ForkExecvp";
+ return -errno;
+ }
+
+ pipe_write.reset();
+ auto st = ReadLinesFromFdAndLog(output, std::move(pipe_read));
+ if (st != 0) return st;
+
+ int status;
+ if (waitpid(pid, &status, 0) == -1) {
+ PLOG(ERROR) << "waitpid in ForkExecvp";
+ return -errno;
+ }
+ if (!WIFEXITED(status)) {
+ LOG(ERROR) << "Process did not exit normally, status: " << status;
+ return -ECHILD;
+ }
+ if (WEXITSTATUS(status)) {
+ LOG(ERROR) << "Process exited with code: " << WEXITSTATUS(status);
+ return WEXITSTATUS(status);
+ }
return OK;
}
pid_t ForkExecvpAsync(const std::vector<std::string>& args) {
- size_t argc = args.size();
- char** argv = (char**)calloc(argc + 1, sizeof(char*));
- for (size_t i = 0; i < argc; i++) {
- argv[i] = (char*)args[i].c_str();
- if (i == 0) {
- LOG(DEBUG) << args[i];
- } else {
- LOG(DEBUG) << " " << args[i];
- }
- }
+ auto argv = ConvertToArgv(args);
pid_t pid = fork();
if (pid == 0) {
@@ -364,18 +355,14 @@
close(STDOUT_FILENO);
close(STDERR_FILENO);
- if (execvp(argv[0], argv)) {
- PLOG(ERROR) << "Failed to exec";
- }
-
- _exit(1);
+ execvp(argv[0], const_cast<char**>(argv.data()));
+ PLOG(ERROR) << "exec in ForkExecvpAsync";
+ _exit(EXIT_FAILURE);
}
-
if (pid == -1) {
- PLOG(ERROR) << "Failed to exec";
+ PLOG(ERROR) << "fork in ForkExecvpAsync";
+ return -1;
}
-
- free(argv);
return pid;
}
@@ -767,29 +754,10 @@
}
status_t UnmountTree(const std::string& prefix) {
- FILE* fp = setmntent("/proc/mounts", "re");
- if (fp == NULL) {
- PLOG(ERROR) << "Failed to open /proc/mounts";
+ if (umount2(prefix.c_str(), MNT_DETACH)) {
+ PLOG(ERROR) << "Failed to unmount " << prefix;
return -errno;
}
-
- // Some volumes can be stacked on each other, so force unmount in
- // reverse order to give us the best chance of success.
- std::list<std::string> toUnmount;
- mntent* mentry;
- while ((mentry = getmntent(fp)) != NULL) {
- auto test = std::string(mentry->mnt_dir) + "/";
- if (android::base::StartsWith(test, prefix)) {
- toUnmount.push_front(test);
- }
- }
- endmntent(fp);
-
- for (const auto& path : toUnmount) {
- if (umount2(path.c_str(), MNT_DETACH)) {
- PLOG(ERROR) << "Failed to unmount " << path;
- }
- }
return OK;
}
diff --git a/Utils.h b/Utils.h
index e6f4792..68c82eb 100644
--- a/Utils.h
+++ b/Utils.h
@@ -68,12 +68,8 @@
std::string* fsLabel);
/* Returns either WEXITSTATUS() status, or a negative errno */
-status_t ForkExecvp(const std::vector<std::string>& args);
-status_t ForkExecvp(const std::vector<std::string>& args, security_context_t context);
-
-status_t ForkExecvp(const std::vector<std::string>& args, std::vector<std::string>& output);
-status_t ForkExecvp(const std::vector<std::string>& args, std::vector<std::string>& output,
- security_context_t context);
+status_t ForkExecvp(const std::vector<std::string>& args, std::vector<std::string>* output = nullptr,
+ security_context_t context = nullptr);
pid_t ForkExecvpAsync(const std::vector<std::string>& args);
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index e9ab8a5..58fdc74 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -556,24 +556,7 @@
ENFORCE_UID(AID_SYSTEM);
ACQUIRE_LOCK;
- std::string tmp;
- switch (remountMode) {
- case REMOUNT_MODE_NONE:
- tmp = "none";
- break;
- case REMOUNT_MODE_DEFAULT:
- tmp = "default";
- break;
- case REMOUNT_MODE_READ:
- tmp = "read";
- break;
- case REMOUNT_MODE_WRITE:
- tmp = "write";
- break;
- default:
- return error("Unknown mode " + std::to_string(remountMode));
- }
- return translate(VolumeManager::Instance()->remountUid(uid, tmp));
+ return translate(VolumeManager::Instance()->remountUid(uid, remountMode));
}
binder::Status VoldNativeService::mkdirs(const std::string& path) {
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 0b2f1bf..d113cf9 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -73,6 +73,7 @@
using android::base::StringAppendF;
using android::base::StringPrintf;
using android::base::unique_fd;
+using android::vold::VoldNativeService;
static const char* kPathUserMount = "/mnt/user";
static const char* kPathVirtualDisk = "/data/misc/vold/virtual_disk";
@@ -326,7 +327,8 @@
return nullptr;
}
-void VolumeManager::listVolumes(android::vold::VolumeBase::Type type, std::list<std::string>& list) {
+void VolumeManager::listVolumes(android::vold::VolumeBase::Type type,
+ std::list<std::string>& list) const {
list.clear();
for (const auto& disk : mDisks) {
disk->listVolumes(type, list);
@@ -401,7 +403,7 @@
int VolumeManager::mountPkgSpecificDirsForRunningProcs(
userid_t userId, const std::vector<std::string>& packageNames,
- const std::vector<std::string>& visibleVolLabels) {
+ const std::vector<std::string>& visibleVolLabels, int remountMode) {
// TODO: New processes could be started while traversing over the existing
// processes which would end up not having the necessary bind mounts. This
// issue needs to be fixed, may be by doing multiple passes here?
@@ -496,38 +498,32 @@
_exit(1);
}
- struct stat storageSb;
- if (TEMP_FAILURE_RETRY(stat("/storage", &storageSb)) == -1) {
- PLOG(ERROR) << "Failed to stat /storage";
- _exit(1);
- }
-
- // Some packages have access to full external storage, identify processes belonging
- // to those packages by comparing inode no.s of /mnt/runtime/write and /storage
- if (storageSb.st_dev == fullWriteSb.st_dev && storageSb.st_ino == fullWriteSb.st_ino) {
- _exit(0);
+ int mountMode;
+ if (remountMode == -1) {
+ mountMode = getMountModeForRunningProc(packagesForUid, userId, fullWriteSb);
+ if (mountMode == -1) {
+ _exit(1);
+ }
} else {
- // Some packages don't have access to external storage and processes belonging to
- // those packages don't have anything mounted at /storage. So, identify those
- // processes by comparing inode no.s of /mnt/user/%d/package/%s
- // and /storage
- std::string pkgStorageSource;
- for (auto& package : packagesForUid) {
- std::string sandbox =
- StringPrintf("/mnt/user/%d/package/%s", userId, package.c_str());
- struct stat s;
- if (TEMP_FAILURE_RETRY(stat(sandbox.c_str(), &s)) == -1) {
- PLOG(ERROR) << "Failed to stat " << sandbox;
- _exit(1);
+ mountMode = remountMode;
+ std::string obbMountFile = StringPrintf("/mnt/user/%d/package/%s/obb_mount", userId,
+ packagesForUid[0].c_str());
+ if (mountMode == VoldNativeService::REMOUNT_MODE_INSTALLER) {
+ if (access(obbMountFile.c_str(), F_OK) != 0) {
+ const unique_fd fd(
+ TEMP_FAILURE_RETRY(open(obbMountFile.c_str(), O_RDWR | O_CREAT, 0660)));
}
- if (storageSb.st_dev == s.st_dev && storageSb.st_ino == s.st_ino) {
- pkgStorageSource = sandbox;
- break;
+ } else {
+ if (access(obbMountFile.c_str(), F_OK) == 0) {
+ remove(obbMountFile.c_str());
}
}
- if (pkgStorageSource.empty()) {
- _exit(0);
- }
+ }
+ if (mountMode == VoldNativeService::REMOUNT_MODE_FULL ||
+ mountMode == VoldNativeService::REMOUNT_MODE_NONE) {
+ // These mount modes are not going to change dynamically, so don't bother
+ // unmounting/remounting dirs.
+ _exit(0);
}
for (auto& volumeLabel : visibleVolLabels) {
@@ -537,10 +533,31 @@
StringAppendF(&mntSource, "/%d", userId);
StringAppendF(&mntTarget, "/%d", userId);
}
+ std::string obbSourceDir = StringPrintf("%s/Android/obb", mntSource.c_str());
+ std::string obbTargetDir = StringPrintf("%s/Android/obb", mntTarget.c_str());
+ if (umount2(obbTargetDir.c_str(), MNT_DETACH) == -1 && errno != EINVAL &&
+ errno != ENOENT) {
+ PLOG(ERROR) << "Failed to unmount " << obbTargetDir;
+ continue;
+ }
for (auto& package : packagesForUid) {
mountPkgSpecificDir(mntSource, mntTarget, package, "data");
mountPkgSpecificDir(mntSource, mntTarget, package, "media");
- mountPkgSpecificDir(mntSource, mntTarget, package, "obb");
+ if (mountMode != VoldNativeService::REMOUNT_MODE_INSTALLER) {
+ mountPkgSpecificDir(mntSource, mntTarget, package, "obb");
+ }
+ }
+ if (mountMode == VoldNativeService::REMOUNT_MODE_INSTALLER) {
+ if (TEMP_FAILURE_RETRY(mount(obbSourceDir.c_str(), obbTargetDir.c_str(),
+ nullptr, MS_BIND | MS_REC, nullptr)) == -1) {
+ PLOG(ERROR) << "Failed to mount " << obbSourceDir << " to " << obbTargetDir;
+ continue;
+ }
+ if (TEMP_FAILURE_RETRY(mount(nullptr, obbTargetDir.c_str(), nullptr,
+ MS_REC | MS_SLAVE, nullptr)) == -1) {
+ PLOG(ERROR) << "Failed to set MS_SLAVE at " << obbTargetDir.c_str();
+ continue;
+ }
}
}
_exit(0);
@@ -555,6 +572,44 @@
return 0;
}
+int VolumeManager::getMountModeForRunningProc(const std::vector<std::string>& packagesForUid,
+ userid_t userId, struct stat& mntWriteStat) {
+ struct stat storageSb;
+ if (TEMP_FAILURE_RETRY(stat("/storage", &storageSb)) == -1) {
+ PLOG(ERROR) << "Failed to stat /storage";
+ return -1;
+ }
+
+ // Some packages have access to full external storage, identify processes belonging
+ // to those packages by comparing inode no.s of /mnt/runtime/write and /storage
+ if (storageSb.st_dev == mntWriteStat.st_dev && storageSb.st_ino == mntWriteStat.st_ino) {
+ return VoldNativeService::REMOUNT_MODE_FULL;
+ }
+
+ std::string obbMountFile =
+ StringPrintf("/mnt/user/%d/package/%s/obb_mount", userId, packagesForUid[0].c_str());
+ if (access(obbMountFile.c_str(), F_OK) == 0) {
+ return VoldNativeService::REMOUNT_MODE_INSTALLER;
+ }
+
+ // Some packages don't have access to external storage and processes belonging to
+ // those packages don't have anything mounted at /storage. So, identify those
+ // processes by comparing inode no.s of /mnt/user/%d/package/%s
+ // and /storage
+ for (auto& package : packagesForUid) {
+ std::string sandbox = StringPrintf("/mnt/user/%d/package/%s", userId, package.c_str());
+ struct stat sandboxStat;
+ if (TEMP_FAILURE_RETRY(stat(sandbox.c_str(), &sandboxStat)) == -1) {
+ PLOG(ERROR) << "Failed to stat " << sandbox;
+ return -1;
+ }
+ if (storageSb.st_dev == sandboxStat.st_dev && storageSb.st_ino == sandboxStat.st_ino) {
+ return VoldNativeService::REMOUNT_MODE_WRITE;
+ }
+ }
+ return VoldNativeService::REMOUNT_MODE_NONE;
+}
+
int VolumeManager::prepareSandboxes(userid_t userId, const std::vector<std::string>& packageNames,
const std::vector<std::string>& visibleVolLabels) {
if (visibleVolLabels.empty()) {
@@ -667,7 +722,7 @@
}
}
}
- mountPkgSpecificDirsForRunningProcs(userId, packageNames, visibleVolLabels);
+ mountPkgSpecificDirsForRunningProcs(userId, packageNames, visibleVolLabels, -1);
return 0;
}
@@ -874,7 +929,8 @@
LOG(VERBOSE) << "destroySandboxForApp: " << packageName << ", sandboxId=" << sandboxId
<< ", userId=" << userId;
auto& userPackages = mUserPackages[userId];
- std::remove(userPackages.begin(), userPackages.end(), packageName);
+ userPackages.erase(std::remove(userPackages.begin(), userPackages.end(), packageName),
+ userPackages.end());
// If the package is not uninstalled in any other users, remove appId and sandboxId
// corresponding to it from the internal state.
bool installedInAnyUser = false;
@@ -1038,12 +1094,56 @@
return 0;
}
-int VolumeManager::remountUid(uid_t uid, const std::string& mode) {
- // If the isolated storage is enabled, return -1 since in the isolated storage world, there
- // are no longer any runtime storage permissions, so this shouldn't be called anymore.
- if (GetBoolProperty(kIsolatedStorage, false)) {
+int VolumeManager::remountUid(uid_t uid, int32_t mountMode) {
+ if (!GetBoolProperty(kIsolatedStorage, false)) {
+ return remountUidLegacy(uid, mountMode);
+ }
+
+ appid_t appId = multiuser_get_app_id(uid);
+ userid_t userId = multiuser_get_user_id(uid);
+ std::vector<std::string> visibleVolLabels;
+ for (auto& volId : mVisibleVolumeIds) {
+ auto vol = findVolume(volId);
+ userid_t mountUserId = vol->getMountUserId();
+ if (mountUserId == userId || vol->isEmulated()) {
+ visibleVolLabels.push_back(vol->getLabel());
+ }
+ }
+
+ // Finding one package with appId is enough
+ std::vector<std::string> packageNames;
+ for (auto it = mAppIds.begin(); it != mAppIds.end(); ++it) {
+ if (it->second == appId) {
+ packageNames.push_back(it->first);
+ break;
+ }
+ }
+ if (packageNames.empty()) {
+ PLOG(ERROR) << "Failed to find packageName for " << uid;
return -1;
}
+ return mountPkgSpecificDirsForRunningProcs(userId, packageNames, visibleVolLabels, mountMode);
+}
+
+int VolumeManager::remountUidLegacy(uid_t uid, int32_t mountMode) {
+ std::string mode;
+ switch (mountMode) {
+ case VoldNativeService::REMOUNT_MODE_NONE:
+ mode = "none";
+ break;
+ case VoldNativeService::REMOUNT_MODE_DEFAULT:
+ mode = "default";
+ break;
+ case VoldNativeService::REMOUNT_MODE_READ:
+ mode = "read";
+ break;
+ case VoldNativeService::REMOUNT_MODE_WRITE:
+ mode = "write";
+ break;
+ default:
+ PLOG(ERROR) << "Unknown mode " << std::to_string(mountMode);
+ return -1;
+ }
LOG(DEBUG) << "Remounting " << uid << " as mode " << mode;
DIR* dir;
diff --git a/VolumeManager.h b/VolumeManager.h
index 9e990d0..3a7bae4 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -52,7 +52,7 @@
std::mutex& getCryptLock() { return mCryptLock; }
void setListener(android::sp<android::os::IVoldListener> listener) { mListener = listener; }
- android::sp<android::os::IVoldListener> getListener() { return mListener; }
+ android::sp<android::os::IVoldListener> getListener() const { return mListener; }
int start();
int stop();
@@ -68,8 +68,8 @@
return !fnmatch(mSysPattern.c_str(), sysPath.c_str(), 0);
}
- const std::string& getNickname() { return mNickname; }
- int getFlags() { return mFlags; }
+ const std::string& getNickname() const { return mNickname; }
+ int getFlags() const { return mFlags; }
private:
std::string mSysPattern;
@@ -82,7 +82,7 @@
std::shared_ptr<android::vold::Disk> findDisk(const std::string& id);
std::shared_ptr<android::vold::VolumeBase> findVolume(const std::string& id);
- void listVolumes(android::vold::VolumeBase::Type type, std::list<std::string>& list);
+ void listVolumes(android::vold::VolumeBase::Type type, std::list<std::string>& list) const;
int forgetPartition(const std::string& partGuid, const std::string& fsUuid);
@@ -107,7 +107,8 @@
int setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol);
- int remountUid(uid_t uid, const std::string& mode);
+ int remountUid(uid_t uid, int32_t remountMode);
+ int remountUidLegacy(uid_t uid, int32_t remountMode);
/* Reset all internal state, typically during framework boot */
int reset();
@@ -153,7 +154,8 @@
const std::vector<std::string>& visibleVolLabels);
int mountPkgSpecificDirsForRunningProcs(userid_t userId,
const std::vector<std::string>& packageNames,
- const std::vector<std::string>& visibleVolLabels);
+ const std::vector<std::string>& visibleVolLabels,
+ int remountMode);
int destroySandboxesForVol(android::vold::VolumeBase* vol, userid_t userId);
std::string prepareSandboxSource(uid_t uid, const std::string& sandboxId,
const std::string& sandboxRootDir);
@@ -171,6 +173,8 @@
const std::string& packageName, const char* dirName);
int destroySandboxForAppOnVol(const std::string& packageName, const std::string& sandboxId,
userid_t userId, const std::string& volLabel);
+ int getMountModeForRunningProc(const std::vector<std::string>& packagesForUid, userid_t userId,
+ struct stat& mntWriteStat);
void handleDiskAdded(const std::shared_ptr<android::vold::Disk>& disk);
void handleDiskChanged(dev_t device);
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index e399141..59e8795 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -152,7 +152,8 @@
const int REMOUNT_MODE_DEFAULT = 1;
const int REMOUNT_MODE_READ = 2;
const int REMOUNT_MODE_WRITE = 3;
- const int REMOUNT_MODE_FULL = 4;
+ const int REMOUNT_MODE_INSTALLER = 4;
+ const int REMOUNT_MODE_FULL = 5;
const int VOLUME_STATE_UNMOUNTED = 0;
const int VOLUME_STATE_CHECKING = 1;
diff --git a/cryptfs.cpp b/cryptfs.cpp
index 21f434d..5d88a49 100644
--- a/cryptfs.cpp
+++ b/cryptfs.cpp
@@ -36,6 +36,7 @@
#include "secontext.h"
#include <android-base/properties.h>
+#include <android-base/stringprintf.h>
#include <bootloader_message/bootloader_message.h>
#include <cutils/android_reboot.h>
#include <cutils/properties.h>
@@ -77,6 +78,7 @@
#include <crypto_scrypt.h>
}
+using android::base::StringPrintf;
using namespace std::chrono_literals;
#define UNUSED __attribute__((unused))
@@ -466,6 +468,10 @@
constexpr CryptoType supported_crypto_types[] = {
default_crypto_type,
+ CryptoType()
+ .set_property_name("adiantum")
+ .set_crypto_name("xchacha12,aes-adiantum-plain64")
+ .set_keysize(32),
// Add new CryptoTypes here. Order is not important.
};
@@ -1216,6 +1222,21 @@
}
#endif
+// Only adds parameters if the property is set.
+static void add_sector_size_param(std::vector<std::string>* extra_params_vec) {
+ constexpr char DM_CRYPT_SECTOR_SIZE[] = "ro.crypto.fde_sector_size";
+ char sector_size[PROPERTY_VALUE_MAX];
+
+ if (property_get(DM_CRYPT_SECTOR_SIZE, sector_size, "") > 0) {
+ std::string param = StringPrintf("sector_size:%s", sector_size);
+ extra_params_vec->push_back(std::move(param));
+
+ // With this option, IVs will match the sector numbering, instead
+ // of being hard-coded to being based on 512-byte sectors.
+ extra_params_vec->emplace_back("iv_large_sectors");
+ }
+}
+
static int create_crypto_blk_dev(struct crypt_mnt_ftr* crypt_ftr, const unsigned char* master_key,
const char* real_blk_name, char* crypto_blk_name, const char* name,
uint32_t flags) {
@@ -1306,6 +1327,7 @@
if (flags & CREATE_CRYPTO_BLK_DEV_FLAGS_ALLOW_ENCRYPT_OVERRIDE) {
extra_params_vec.emplace_back("allow_encrypt_override");
}
+ add_sector_size_param(&extra_params_vec);
load_count = load_crypto_mapping_table(crypt_ftr, master_key, real_blk_name, name, fd,
extra_params_as_string(extra_params_vec).c_str());
#endif
diff --git a/fs/Exfat.cpp b/fs/Exfat.cpp
index 5c15075..c624eb9 100644
--- a/fs/Exfat.cpp
+++ b/fs/Exfat.cpp
@@ -43,7 +43,7 @@
cmd.push_back(kFsckPath);
cmd.push_back(source);
- int rc = ForkExecvp(cmd, sFsckUntrustedContext);
+ int rc = ForkExecvp(cmd, nullptr, sFsckUntrustedContext);
if (rc == 0) {
LOG(INFO) << "Check OK";
return 0;
diff --git a/fs/Ext4.cpp b/fs/Ext4.cpp
index 806cfd1..0059233 100644
--- a/fs/Ext4.cpp
+++ b/fs/Ext4.cpp
@@ -117,7 +117,7 @@
cmd.push_back(c_source);
// ext4 devices are currently always trusted
- return ForkExecvp(cmd, sFsckContext);
+ return ForkExecvp(cmd, nullptr, sFsckContext);
}
return 0;
diff --git a/fs/F2fs.cpp b/fs/F2fs.cpp
index c6e0f52..9517dc9 100644
--- a/fs/F2fs.cpp
+++ b/fs/F2fs.cpp
@@ -48,7 +48,7 @@
cmd.push_back(source);
// f2fs devices are currently always trusted
- return ForkExecvp(cmd, sFsckContext);
+ return ForkExecvp(cmd, nullptr, sFsckContext);
}
status_t Mount(const std::string& source, const std::string& target) {
diff --git a/fs/Vfat.cpp b/fs/Vfat.cpp
index 7b833d1..14c42d6 100644
--- a/fs/Vfat.cpp
+++ b/fs/Vfat.cpp
@@ -67,7 +67,7 @@
cmd.push_back(source);
// Fat devices are currently always untrusted
- rc = ForkExecvp(cmd, sFsckUntrustedContext);
+ rc = ForkExecvp(cmd, nullptr, sFsckUntrustedContext);
if (rc < 0) {
LOG(ERROR) << "Filesystem check failed due to logwrap error";
diff --git a/model/Disk.cpp b/model/Disk.cpp
index 3d25e4c..b66c336 100644
--- a/model/Disk.cpp
+++ b/model/Disk.cpp
@@ -153,7 +153,7 @@
return nullptr;
}
-void Disk::listVolumes(VolumeBase::Type type, std::list<std::string>& list) {
+void Disk::listVolumes(VolumeBase::Type type, std::list<std::string>& list) const {
for (const auto& vol : mVolumes) {
if (vol->getType() == type) {
list.push_back(vol->getId());
@@ -341,7 +341,7 @@
cmd.push_back(mDevPath);
std::vector<std::string> output;
- status_t res = ForkExecvp(cmd, output);
+ status_t res = ForkExecvp(cmd, &output);
if (res != OK) {
LOG(WARNING) << "sgdisk failed to scan " << mDevPath;
diff --git a/model/Disk.h b/model/Disk.h
index 3140144..889e906 100644
--- a/model/Disk.h
+++ b/model/Disk.h
@@ -54,18 +54,18 @@
kEmmc = 1 << 4,
};
- const std::string& getId() { return mId; }
- const std::string& getEventPath() { return mEventPath; }
- const std::string& getSysPath() { return mSysPath; }
- const std::string& getDevPath() { return mDevPath; }
- dev_t getDevice() { return mDevice; }
- uint64_t getSize() { return mSize; }
- const std::string& getLabel() { return mLabel; }
- int getFlags() { return mFlags; }
+ const std::string& getId() const { return mId; }
+ const std::string& getEventPath() const { return mEventPath; }
+ const std::string& getSysPath() const { return mSysPath; }
+ const std::string& getDevPath() const { return mDevPath; }
+ dev_t getDevice() const { return mDevice; }
+ uint64_t getSize() const { return mSize; }
+ const std::string& getLabel() const { return mLabel; }
+ int getFlags() const { return mFlags; }
std::shared_ptr<VolumeBase> findVolume(const std::string& id);
- void listVolumes(VolumeBase::Type type, std::list<std::string>& list);
+ void listVolumes(VolumeBase::Type type, std::list<std::string>& list) const;
status_t create();
status_t destroy();
diff --git a/model/PrivateVolume.h b/model/PrivateVolume.h
index 85aa4dc..cb8e75d 100644
--- a/model/PrivateVolume.h
+++ b/model/PrivateVolume.h
@@ -39,9 +39,9 @@
public:
PrivateVolume(dev_t device, const std::string& keyRaw);
virtual ~PrivateVolume();
- const std::string& getFsType() { return mFsType; };
- const std::string& getRawDevPath() { return mRawDevPath; };
- const std::string& getRawDmDevPath() { return mDmDevPath; };
+ const std::string& getFsType() const { return mFsType; };
+ const std::string& getRawDevPath() const { return mRawDevPath; };
+ const std::string& getRawDmDevPath() const { return mDmDevPath; };
protected:
status_t doCreate() override;
diff --git a/model/VolumeBase.cpp b/model/VolumeBase.cpp
index 29bc32c..a9c7fa3 100644
--- a/model/VolumeBase.cpp
+++ b/model/VolumeBase.cpp
@@ -153,7 +153,7 @@
return OK;
}
-android::sp<android::os::IVoldListener> VolumeBase::getListener() {
+android::sp<android::os::IVoldListener> VolumeBase::getListener() const {
if (mSilent) {
return nullptr;
} else {
diff --git a/model/VolumeBase.h b/model/VolumeBase.h
index ea187bd..e6c47f0 100644
--- a/model/VolumeBase.h
+++ b/model/VolumeBase.h
@@ -78,16 +78,16 @@
kBadRemoval,
};
- const std::string& getId() { return mId; }
- const std::string& getDiskId() { return mDiskId; }
- const std::string& getPartGuid() { return mPartGuid; }
- Type getType() { return mType; }
- int getMountFlags() { return mMountFlags; }
- userid_t getMountUserId() { return mMountUserId; }
- State getState() { return mState; }
- const std::string& getPath() { return mPath; }
- const std::string& getInternalPath() { return mInternalPath; }
- const std::string& getLabel() { return mLabel; }
+ const std::string& getId() const { return mId; }
+ const std::string& getDiskId() const { return mDiskId; }
+ const std::string& getPartGuid() const { return mPartGuid; }
+ Type getType() const { return mType; }
+ int getMountFlags() const { return mMountFlags; }
+ userid_t getMountUserId() const { return mMountUserId; }
+ State getState() const { return mState; }
+ const std::string& getPath() const { return mPath; }
+ const std::string& getInternalPath() const { return mInternalPath; }
+ const std::string& getLabel() const { return mLabel; }
status_t setDiskId(const std::string& diskId);
status_t setPartGuid(const std::string& partGuid);
@@ -124,7 +124,7 @@
status_t setInternalPath(const std::string& internalPath);
status_t setLabel(const std::string& label);
- android::sp<android::os::IVoldListener> getListener();
+ android::sp<android::os::IVoldListener> getListener() const;
private:
/* ID that uniquely references volume while alive */
diff --git a/vold_prepare_subdirs.cpp b/vold_prepare_subdirs.cpp
index 8c3df30..b8e5cb6 100644
--- a/vold_prepare_subdirs.cpp
+++ b/vold_prepare_subdirs.cpp
@@ -133,6 +133,10 @@
if (!prepare_dir(sehandle, 0700, AID_SYSTEM, AID_SYSTEM, vendor_de_path + "/fpdata")) {
return false;
}
+ auto facedata_path = vendor_de_path + "/facedata";
+ if (!prepare_dir(sehandle, 0700, AID_SYSTEM, AID_SYSTEM, facedata_path)) {
+ return false;
+ }
}
if (flags & android::os::IVold::STORAGE_FLAG_CE) {
auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id);