summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-10-15 01:08:58 +0000
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2021-10-15 01:08:58 +0000
commit2237faaae790ca8b751ea5d47056528c0c7f1892 (patch)
treee2f4d4cf6b34304ceabee3fdc0d29190830c7c1e
parentb590d925f9d40fc1f968d17d4ae3060536db5c5e (diff)
parent98e7f427e898c1f7dfe597cc4e15032c6563bbae (diff)
downloadcore-android12-qpr1-d-release.tar.gz
Change-Id: Idc1bad9acca53cbbae8c02d1da45e9cd2e9effc0
-rw-r--r--trusty/storage/interface/include/trusty/interface/storage.h40
-rw-r--r--trusty/storage/proxy/Android.bp3
-rw-r--r--trusty/storage/proxy/checkpoint_handling.cpp77
-rw-r--r--trusty/storage/proxy/checkpoint_handling.h37
-rw-r--r--trusty/storage/proxy/proxy.c16
5 files changed, 155 insertions, 18 deletions
diff --git a/trusty/storage/interface/include/trusty/interface/storage.h b/trusty/storage/interface/include/trusty/interface/storage.h
index b196d88b3..3f1dcb8c6 100644
--- a/trusty/storage/interface/include/trusty/interface/storage.h
+++ b/trusty/storage/interface/include/trusty/interface/storage.h
@@ -112,26 +112,30 @@ enum storage_file_open_flag {
/**
* enum storage_msg_flag - protocol-level flags in struct storage_msg
- * @STORAGE_MSG_FLAG_BATCH: if set, command belongs to a batch transaction.
- * No response will be sent by the server until
- * it receives a command with this flag unset, at
- * which point a cummulative result for all messages
- * sent with STORAGE_MSG_FLAG_BATCH will be sent.
- * This is only supported by the non-secure disk proxy
- * server.
- * @STORAGE_MSG_FLAG_PRE_COMMIT: if set, indicates that server need to commit
- * pending changes before processing this message.
- * @STORAGE_MSG_FLAG_POST_COMMIT: if set, indicates that server need to commit
- * pending changes after processing this message.
- * @STORAGE_MSG_FLAG_TRANSACT_COMPLETE: if set, indicates that server need to commit
- * current transaction after processing this message.
- * It is an alias for STORAGE_MSG_FLAG_POST_COMMIT.
+ * @STORAGE_MSG_FLAG_BATCH: if set, command belongs to a batch transaction.
+ * No response will be sent by the server until
+ * it receives a command with this flag unset, at
+ * which point a cumulative result for all messages
+ * sent with STORAGE_MSG_FLAG_BATCH will be sent.
+ * This is only supported by the non-secure disk proxy
+ * server.
+ * @STORAGE_MSG_FLAG_PRE_COMMIT: if set, indicates that server need to commit
+ * pending changes before processing this message.
+ * @STORAGE_MSG_FLAG_POST_COMMIT: if set, indicates that server need to commit
+ * pending changes after processing this message.
+ * @STORAGE_MSG_FLAG_TRANSACT_COMPLETE: if set, indicates that server need to commit
+ * current transaction after processing this message.
+ * It is an alias for STORAGE_MSG_FLAG_POST_COMMIT.
+ * @STORAGE_MSG_FLAG_PRE_COMMIT_CHECKPOINT: if set, indicates that server needs to ensure
+ * that there is not a pending checkpoint for
+ * userdata before processing this message.
*/
enum storage_msg_flag {
- STORAGE_MSG_FLAG_BATCH = 0x1,
- STORAGE_MSG_FLAG_PRE_COMMIT = 0x2,
- STORAGE_MSG_FLAG_POST_COMMIT = 0x4,
- STORAGE_MSG_FLAG_TRANSACT_COMPLETE = STORAGE_MSG_FLAG_POST_COMMIT,
+ STORAGE_MSG_FLAG_BATCH = 0x1,
+ STORAGE_MSG_FLAG_PRE_COMMIT = 0x2,
+ STORAGE_MSG_FLAG_POST_COMMIT = 0x4,
+ STORAGE_MSG_FLAG_TRANSACT_COMPLETE = STORAGE_MSG_FLAG_POST_COMMIT,
+ STORAGE_MSG_FLAG_PRE_COMMIT_CHECKPOINT = 0x8,
};
/*
diff --git a/trusty/storage/proxy/Android.bp b/trusty/storage/proxy/Android.bp
index d67089fb2..38d868508 100644
--- a/trusty/storage/proxy/Android.bp
+++ b/trusty/storage/proxy/Android.bp
@@ -23,6 +23,7 @@ cc_binary {
vendor: true,
srcs: [
+ "checkpoint_handling.cpp",
"ipc.c",
"rpmb.c",
"storage.c",
@@ -30,12 +31,14 @@ cc_binary {
],
shared_libs: [
+ "libbase",
"liblog",
"libhardware_legacy",
],
header_libs: ["libcutils_headers"],
static_libs: [
+ "libfstab",
"libtrustystorageinterface",
"libtrusty",
],
diff --git a/trusty/storage/proxy/checkpoint_handling.cpp b/trusty/storage/proxy/checkpoint_handling.cpp
new file mode 100644
index 000000000..6c2fd363e
--- /dev/null
+++ b/trusty/storage/proxy/checkpoint_handling.cpp
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "checkpoint_handling.h"
+#include "log.h"
+
+#include <fstab/fstab.h>
+#include <cstring>
+#include <string>
+
+namespace {
+
+bool checkpointingDoneForever = false;
+
+} // namespace
+
+int is_data_checkpoint_active(bool* active) {
+ if (!active) {
+ ALOGE("active out parameter is null");
+ return 0;
+ }
+
+ *active = false;
+
+ if (checkpointingDoneForever) {
+ return 0;
+ }
+
+ android::fs_mgr::Fstab procMounts;
+ bool success = android::fs_mgr::ReadFstabFromFile("/proc/mounts", &procMounts);
+ if (!success) {
+ ALOGE("Could not parse /proc/mounts\n");
+ /* Really bad. Tell the caller to abort the write. */
+ return -1;
+ }
+
+ android::fs_mgr::FstabEntry* dataEntry =
+ android::fs_mgr::GetEntryForMountPoint(&procMounts, "/data");
+ if (dataEntry == NULL) {
+ ALOGE("/data is not mounted yet\n");
+ return 0;
+ }
+
+ /* We can't handle e.g., ext4. Nothing we can do about it for now. */
+ if (dataEntry->fs_type != "f2fs") {
+ ALOGW("Checkpoint status not supported for filesystem %s\n", dataEntry->fs_type.c_str());
+ checkpointingDoneForever = true;
+ return 0;
+ }
+
+ /*
+ * The data entry looks like "... blah,checkpoint=disable:0,blah ...".
+ * checkpoint=disable means checkpointing is on (yes, arguably reversed).
+ */
+ size_t checkpointPos = dataEntry->fs_options.find("checkpoint=disable");
+ if (checkpointPos == std::string::npos) {
+ /* Assumption is that once checkpointing turns off, it stays off */
+ checkpointingDoneForever = true;
+ } else {
+ *active = true;
+ }
+
+ return 0;
+}
diff --git a/trusty/storage/proxy/checkpoint_handling.h b/trusty/storage/proxy/checkpoint_handling.h
new file mode 100644
index 000000000..f1bf27c8d
--- /dev/null
+++ b/trusty/storage/proxy/checkpoint_handling.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <stdbool.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * is_data_checkpoint_active() - Check for an active, uncommitted checkpoint of
+ * /data. If a checkpoint is active, storage should not commit any
+ * rollback-protected writes to /data.
+ * @active: Out parameter that will be set to the result of the check.
+ *
+ * Return: 0 if active was set and is valid, non-zero otherwise.
+ */
+int is_data_checkpoint_active(bool* active);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/trusty/storage/proxy/proxy.c b/trusty/storage/proxy/proxy.c
index e23094183..c690a2876 100644
--- a/trusty/storage/proxy/proxy.c
+++ b/trusty/storage/proxy/proxy.c
@@ -26,6 +26,7 @@
#include <cutils/android_filesystem_config.h>
+#include "checkpoint_handling.h"
#include "ipc.h"
#include "log.h"
#include "rpmb.h"
@@ -130,6 +131,21 @@ static int handle_req(struct storage_msg* msg, const void* req, size_t req_len)
}
}
+ if (msg->flags & STORAGE_MSG_FLAG_PRE_COMMIT_CHECKPOINT) {
+ bool is_checkpoint_active = false;
+
+ rc = is_data_checkpoint_active(&is_checkpoint_active);
+ if (rc != 0) {
+ ALOGE("is_data_checkpoint_active failed in an unexpected way. Aborting.\n");
+ msg->result = STORAGE_ERR_GENERIC;
+ return ipc_respond(msg, NULL, 0);
+ } else if (is_checkpoint_active) {
+ ALOGE("Checkpoint in progress, dropping write ...\n");
+ msg->result = STORAGE_ERR_GENERIC;
+ return ipc_respond(msg, NULL, 0);
+ }
+ }
+
switch (msg->cmd) {
case STORAGE_FILE_DELETE:
rc = storage_file_delete(msg, req, req_len);